Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simulate of analytic case for DefaultMixedNewAPI #6618

Merged
merged 83 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 79 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
1b8e845
Implement execution for new default mixed api
JerryChen97 Nov 19, 2024
8809d76
add preproc signature
JerryChen97 Nov 19, 2024
5ff4f14
add _setup_execution_config
JerryChen97 Nov 19, 2024
e2f3d0a
add necessary other components to the default_mixed device
JerryChen97 Nov 19, 2024
b620d0b
add test modules for preprocessing.
JerryChen97 Nov 19, 2024
95ae121
Merge remote-tracking branch 'origin/master' into add-default_mixed.p…
JerryChen97 Nov 19, 2024
a57013c
add changelog
JerryChen97 Nov 19, 2024
07b3b56
add two more tests to cover codecov missing lines
JerryChen97 Nov 19, 2024
7899ab9
Update pennylane/devices/default_mixed.py
JerryChen97 Nov 19, 2024
5fe16c3
Add simulate of analytic case for DefaultMixedNewAPI
JerryChen97 Nov 20, 2024
04b5cb8
save
JerryChen97 Nov 20, 2024
429d42e
Merge branch 'master' into add-default_mixed.preprocess
JerryChen97 Nov 21, 2024
fcafde3
update comparing against the DefaultMixedNewAPI
JerryChen97 Nov 21, 2024
aad256e
add LinearCombination branch for tests
JerryChen97 Nov 21, 2024
de1e38d
unify the style better for potential debug in future
JerryChen97 Nov 21, 2024
1fb86a7
Merge branch 'master' into add-default_mixed.preprocess
JerryChen97 Nov 21, 2024
60ecb2b
lift operation list from class attri to global [skip-ci]
JerryChen97 Nov 21, 2024
21fc557
not providing shots stopping cond
JerryChen97 Nov 21, 2024
92aa57b
[skip-ci]
JerryChen97 Nov 21, 2024
97a35a4
Update pennylane/devices/default_mixed.py
JerryChen97 Nov 21, 2024
8bc5d8d
Update pennylane/devices/default_mixed.py
JerryChen97 Nov 21, 2024
b4eed5b
Update pennylane/devices/default_mixed.py
JerryChen97 Nov 21, 2024
ce91585
not provide accepted sample measuremnet [skip-ci]
JerryChen97 Nov 21, 2024
84799a3
correct test for using device backprop
JerryChen97 Nov 21, 2024
fd618b2
Merge branch 'master' into add-default_mixed.preprocess
JerryChen97 Nov 21, 2024
4443acc
Merge branch 'add-default_mixed.preprocess' into new-mixed-execution
JerryChen97 Nov 21, 2024
e681435
add execute (copying paste from qutrit ...) [skip-ci]
JerryChen97 Nov 21, 2024
7897386
placeholder simualte.py
JerryChen97 Nov 21, 2024
589aeac
Merge branch 'new-mixed-execution' into add-analytic-simulate-for-mix…
JerryChen97 Nov 21, 2024
9d42c2b
temp save
JerryChen97 Nov 25, 2024
4c8b0cb
debug H test expected method
JerryChen97 Nov 26, 2024
584a5dc
add conftest
JerryChen97 Nov 26, 2024
05ba66d
debug expval analytic
JerryChen97 Nov 26, 2024
a58d6e7
add measure
JerryChen97 Nov 26, 2024
ac8ecd2
add import
JerryChen97 Nov 26, 2024
8ba948d
add coverage and stop pylint from crime
JerryChen97 Nov 26, 2024
9816727
let's just eazy fix it
JerryChen97 Nov 26, 2024
d752148
Merge branch 'master' into add-qubit_mixed/measure
JerryChen97 Nov 26, 2024
0aa7876
add item to log
JerryChen97 Nov 26, 2024
a02bc51
draft?
JerryChen97 Nov 26, 2024
1b221a6
add sim to init
JerryChen97 Nov 27, 2024
3c8493e
tests: 1. interface
JerryChen97 Nov 27, 2024
5dd46dd
tests: 2. basic circuits
JerryChen97 Nov 27, 2024
87130e3
tests: 3. broadcasting
JerryChen97 Nov 27, 2024
863eea8
del debugger test since debug is yet implemented until everything els…
JerryChen97 Nov 27, 2024
cfe3aa0
merge changelogs of 6576 and 6564 into one
JerryChen97 Nov 27, 2024
9187533
reuse math.reduce_dm
JerryChen97 Nov 28, 2024
1307961
[skip-ci]
JerryChen97 Nov 28, 2024
a22d65b
Use probsmp process_density_matrix
JerryChen97 Nov 28, 2024
47f4929
Update doc/releases/changelog-dev.md
JerryChen97 Nov 28, 2024
6cd7698
Update pennylane/devices/default_mixed.py
JerryChen97 Nov 28, 2024
ff09567
Merge branch 'master' into add-qubit_mixed/measure
JerryChen97 Nov 28, 2024
3fb417a
Merge branch 'add-qubit_mixed/measure' into add-analytic-simulate-for…
JerryChen97 Nov 28, 2024
c5eed89
not needed
JerryChen97 Nov 28, 2024
cca927e
fix sphinx
JerryChen97 Nov 28, 2024
c266b34
2nd time to save sphinx
JerryChen97 Nov 28, 2024
d80046d
forgot the second line...
JerryChen97 Nov 29, 2024
f3f26ec
fix some merge issue
JerryChen97 Nov 29, 2024
da9e8af
another
JerryChen97 Nov 29, 2024
f8437da
Merge branch 'master' into add-analytic-simulate-for-mixed-new-api
JerryChen97 Dec 2, 2024
eca2efd
correct log
JerryChen97 Dec 2, 2024
ae7f314
revert some unnecessary change for now in absence of execution PR
JerryChen97 Dec 2, 2024
8d7b5fa
revert an implicit merge conflict
JerryChen97 Dec 2, 2024
8877ec1
revert unnecessary mod
JerryChen97 Dec 2, 2024
5aba100
raise NotImplemented for finite shots along with tests
JerryChen97 Dec 2, 2024
3405308
fix docstr
JerryChen97 Dec 2, 2024
4718055
Update pennylane/devices/qubit_mixed/measure.py
JerryChen97 Dec 3, 2024
2b0eecc
rm pylint/black blockers
JerryChen97 Dec 3, 2024
b423027
rm non from interface dict
JerryChen97 Dec 3, 2024
1253025
Merge branch 'master' into add-analytic-simulate-for-mixed-new-api
JerryChen97 Dec 3, 2024
547f140
Update pennylane/devices/qubit_mixed/simulate.py
JerryChen97 Dec 4, 2024
71f9b1a
Update pennylane/devices/qubit_mixed/simulate.py
JerryChen97 Dec 4, 2024
5181416
del many comments causing confusion
JerryChen97 Dec 4, 2024
cbeb539
rename subspace -> wires
JerryChen97 Dec 4, 2024
628d67d
del unnecessary static method
JerryChen97 Dec 4, 2024
f135459
apply all wires
JerryChen97 Dec 4, 2024
af6d75b
apply suggestions
JerryChen97 Dec 4, 2024
611c77d
Merge branch 'add-analytic-simulate-for-mixed-new-api' of https://git…
JerryChen97 Dec 4, 2024
85c4af1
debug
JerryChen97 Dec 4, 2024
d4348c5
mroe informative comment
JerryChen97 Dec 4, 2024
d550d95
more simplification along with infromation comments [skip-ci]
JerryChen97 Dec 4, 2024
52a681f
Merge branch 'master' into add-analytic-simulate-for-mixed-new-api
JerryChen97 Dec 4, 2024
e9c8f7e
Merge branch 'master' into add-analytic-simulate-for-mixed-new-api
JerryChen97 Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ added `binary_mapping()` function to map `BoseWord` and `BoseSentence` to qubit
* Added submodule `devices.qubit_mixed.measure` as a necessary step for the new API, featuring a `measure` function for measuring qubits in mixed-state devices.
[(#6637)](https://github.com/PennyLaneAI/pennylane/pull/6637)

* Added submodule `devices.qubit_mixed.simulate` as a necessary step for the new API,
featuring a `simulate` function for simulating mixed states in analytic mode.
[(#6618)](https://github.com/PennyLaneAI/pennylane/pull/6618)

* Support is added for `if`/`else` statements and `for` and `while` loops in circuits executed with `qml.capture.enabled`, via `autograph`
[(#6406)](https://github.com/PennyLaneAI/pennylane/pull/6406)
[(#6413)](https://github.com/PennyLaneAI/pennylane/pull/6413)
Expand Down
3 changes: 1 addition & 2 deletions pennylane/devices/default_mixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,7 @@ def stopping_condition(op: qml.operation.Operator) -> bool:
def warn_readout_error_state(
tape: qml.tape.QuantumTape,
) -> tuple[Sequence[qml.tape.QuantumTape], Callable]:
"""If a measurement in the QNode is an analytic state or density_matrix, and a readout error
parameter is defined, warn that readout error will not be applied.
"""If a measurement in the QNode is an analytic state or density_matrix, warn that readout error will not be applied.

Args:
tape (QuantumTape, .QNode, Callable): a quantum circuit.
Expand Down
2 changes: 2 additions & 0 deletions pennylane/devices/qubit_mixed/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
apply_operation
create_initial_state
measure
simulate
"""
from .apply_operation import apply_operation
from .initialize_state import create_initial_state
from .measure import measure
from .simulate import get_final_state, measure_final_state, simulate
7 changes: 4 additions & 3 deletions pennylane/devices/qubit_mixed/initialize_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"""Functions to prepare a state."""

from collections.abc import Iterable
from typing import Union

import pennylane as qml
import pennylane.numpy as np
Expand All @@ -22,8 +23,8 @@

def create_initial_state(
# pylint: disable=unsupported-binary-operation
wires: qml.wires.Wires | Iterable,
prep_operation: qml.operation.StatePrepBase | qml.QubitDensityMatrix = None,
wires: Union[qml.wires.Wires, Iterable],
prep_operation: Union[qml.operation.StatePrepBase, qml.QubitDensityMatrix] = None,
like: str = None,
):
r"""
Expand Down Expand Up @@ -60,7 +61,7 @@ def _post_process(density_matrix, num_axes, like):
r"""
This post processor is necessary to ensure that the density matrix is in the correct format, i.e. the original tensor form, instead of the pure matrix form, as requested by all the other more fundamental chore functions in the module (again from some legacy code).
"""
density_matrix = np.reshape(density_matrix, (-1,) + (2,) * num_axes)
density_matrix = np.reshape(density_matrix, (2,) * num_axes)
dtype = str(density_matrix.dtype)
floating_single = "float32" in dtype or "complex64" in dtype
dtype = "complex64" if floating_single else "complex128"
Expand Down
1 change: 1 addition & 0 deletions pennylane/devices/qubit_mixed/measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def calculate_reduced_density_matrix(
state (TensorLike): state to apply the measurement to.
is_state_batched (bool): whether the state is batched or not.
readout_errors (List[Callable]): List of channels to apply to each wire being measured
to simulate readout errors. These are not applied on this type of measurement.

Returns:
TensorLike: state or reduced density matrix.
Expand Down
188 changes: 188 additions & 0 deletions pennylane/devices/qubit_mixed/simulate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Copyright 2018-2024 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Simulate a quantum script for a qubit mixed state device."""
import pennylane as qml
from pennylane.typing import Result

from .apply_operation import apply_operation
from .initialize_state import create_initial_state
from .measure import measure

INTERFACE_TO_LIKE = {
JerryChen97 marked this conversation as resolved.
Show resolved Hide resolved
# map interfaces known by autoray to themselves
"numpy": "numpy",
"autograd": "autograd",
"jax": "jax",
"torch": "torch",
"tensorflow": "tensorflow",
# map non-standard interfaces to those known by autoray
"auto": None,
"scipy": "numpy",
"jax-jit": "jax",
"jax-python": "jax",
"JAX": "jax",
"pytorch": "torch",
"tf": "tensorflow",
"tensorflow-autograph": "tensorflow",
"tf-autograph": "tensorflow",
}


def get_final_state(circuit, debugger=None, interface=None, **kwargs):
"""
Get the final state that results from executing the given quantum script.

This is an internal function that will be called by ``default.mixed``.

Args:
circuit (.QuantumScript): The single circuit to simulate
debugger (._Debugger): The debugger to use
interface (str): The machine learning interface to create the initial state with

Returns:
Tuple[TensorLike, bool]: A tuple containing the final state of the quantum script and
whether the state has a batch dimension.

"""
circuit = circuit.map_to_standard_wires()

prep = None
if len(circuit) > 0 and isinstance(circuit[0], qml.operation.StatePrepBase):
prep = circuit[0]

state = create_initial_state(
sorted(circuit.op_wires), prep, like=INTERFACE_TO_LIKE[interface] if interface else None
)

# initial state is batched only if the state preparation (if it exists) is batched
is_state_batched = bool(prep and prep.batch_size is not None)
for op in circuit.operations[bool(prep) :]:
state = apply_operation(
op,
state,
is_state_batched=is_state_batched,
debugger=debugger,
tape_shots=circuit.shots,
**kwargs,
)

# new state is batched if i) the old state is batched, or ii) the new op adds a batch dim
is_state_batched = is_state_batched or op.batch_size is not None

num_operated_wires = len(circuit.op_wires)
for i in range(len(circuit.wires) - num_operated_wires):
# If any measured wires are not operated on, we pad the density matrix with zeros.
# We know they belong at the end because the circuit is in standard wire-order
# Since it is a dm, we must pad it with 0s on the last row and last column
current_axis = num_operated_wires + i + is_state_batched
state = qml.math.stack(([state] + [qml.math.zeros_like(state)]), axis=current_axis)
state = qml.math.stack(([state] + [qml.math.zeros_like(state)]), axis=-1)

return state, is_state_batched


# pylint: disable=too-many-arguments, too-many-positional-arguments, unused-argument
def measure_final_state(
circuit, state, is_state_batched, rng=None, prng_key=None, readout_errors=None
) -> Result:
"""
Perform the measurements required by the circuit on the provided state.

This is an internal function that will be called by ``default.mixed``.

Args:
circuit (.QuantumScript): The single circuit to simulate
state (TensorLike): The state to perform measurement on
is_state_batched (bool): Whether the state has a batch dimension or not.
rng (Union[None, int, array_like[int], SeedSequence, BitGenerator, Generator]): A
seed-like parameter matching that of ``seed`` for ``numpy.random.default_rng``.
If no value is provided, a default RNG will be used.
prng_key (Optional[jax.random.PRNGKey]): An optional ``jax.random.PRNGKey``. This is
the key to the JAX pseudo random number generator. Only for simulation using JAX.
If None, the default ``sample_state`` function and a ``numpy.random.default_rng``
will be for sampling.
readout_errors (List[Callable]): List of channels to apply to each wire being measured
to simulate readout errors.

Returns:
Tuple[TensorLike]: The measurement results
"""

circuit = circuit.map_to_standard_wires()

if not circuit.shots:
# analytic case
if len(circuit.measurements) == 1:
return measure(circuit.measurements[0], state, is_state_batched, readout_errors)

return tuple(
measure(mp, state, is_state_batched, readout_errors) for mp in circuit.measurements
)
JerryChen97 marked this conversation as resolved.
Show resolved Hide resolved
# !TODO: add finite-shot branch afterwards. After implementation of finite-shot scenario, del this line.
raise NotImplementedError


# pylint: disable=too-many-arguments, too-many-positional-arguments
def simulate(
circuit: qml.tape.QuantumScript,
rng=None,
prng_key=None,
debugger=None,
interface=None,
readout_errors=None,
) -> Result:
"""Simulate a single quantum script.

This is an internal function that will be called by ``default.mixed``.

Args:
circuit (QuantumScript): The single circuit to simulate
rng (Optional[Union[None, int, array_like[int], SeedSequence, BitGenerator, Generator]]): A
seed-like parameter matching that of ``seed`` for ``numpy.random.default_rng``.
If no value is provided, a default RNG will be used.
prng_key (Optional[jax.random.PRNGKey]): An optional ``jax.random.PRNGKey``. This is
the key to the JAX pseudo random number generator. If None, a random key will be
generated. Only for simulation using JAX.
debugger (_Debugger): The debugger to use
interface (str): The machine learning interface to create the initial state with
readout_errors (List[Callable]): List of channels to apply to each wire being measured
to simulate readout errors.

Returns:
tuple(TensorLike): The results of the simulation

Note that this function can return measurements for non-commuting observables simultaneously.

This function assumes that all operations provide matrices.

>>> qs = qml.tape.QuantumScript(
... [qml.RX(1.2, wires=0)],
... [qml.expval(qml.PauliX(0)), qml.probs(wires=(0, 1))]
... )
>>> simulate(qs)
(0.0, array([0.68117888, 0. , 0.31882112, 0. ]))


"""
state, is_state_batched = get_final_state(
circuit, debugger=debugger, interface=interface, rng=rng, prng_key=prng_key
)
return measure_final_state(
circuit,
state,
is_state_batched,
rng=rng,
prng_key=prng_key,
readout_errors=readout_errors,
)
Loading
Loading