Skip to content

Commit

Permalink
Merge branch 'master' into sprod-terms
Browse files Browse the repository at this point in the history
  • Loading branch information
astralcai authored Jul 11, 2024
2 parents f792182 + 7174beb commit eb86f21
Show file tree
Hide file tree
Showing 18 changed files with 156 additions and 297 deletions.
12 changes: 6 additions & 6 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ Pending deprecations
- Deprecated in v0.37
- Will be removed in v0.39

* ``qml.transforms.map_batch_transform`` is deprecated, since transforms can be applied directly to a batch of tapes.
See :func:`~.pennylane.transform` for more information.

- Deprecated in v0.37
- Will be removed in v0.38

* ``qml.from_qasm`` will no longer remove measurements from the QASM code. Calling ``qml.from_qasm``
on a circuit containing measurements without specifying ``measurements`` will raise a deprecation
warning in v0.37, and in v0.38, the default behaviour will be changed to keeping measurements. Use
Expand Down Expand Up @@ -73,6 +67,12 @@ Other deprecations
Completed deprecation cycles
----------------------------

* ``qml.transforms.map_batch_transform`` has been removed, since transforms can be applied directly to a batch of tapes.
See :func:`~.pennylane.transform` for more information.

- Deprecated in v0.37
- Removed in v0.38

* ``qml.from_qasm_file`` has been removed. Instead, the user can open the file and then load its content using ``qml.from_qasm``.

>>> with open("test.qasm", "r") as f:
Expand Down
11 changes: 11 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,18 @@
* `QuantumScript.hash` is now cached, leading to performance improvements.
[(#5919)](https://github.com/PennyLaneAI/pennylane/pull/5919)

* Observable validation for `default.qubit` is now based on execution mode (analytic vs. finite shots) and measurement type (sample measurement vs. state measurement).
[(#5890)](https://github.com/PennyLaneAI/pennylane/pull/5890)

<h3>Breaking changes 💔</h3>

* ``qml.transforms.map_batch_transform`` has been removed, since transforms can be applied directly to a batch of tapes.
See :func:`~.pennylane.transform` for more information.
[(#5981)](https://github.com/PennyLaneAI/pennylane/pull/5981)

* `QuantumScript.interface` has been removed.
[(#5980)](https://github.com/PennyLaneAI/pennylane/pull/5980)

<h3>Deprecations 👋</h3>

<h3>Documentation 📝</h3>
Expand All @@ -45,6 +55,7 @@

This release contains contributions from (in alphabetical order):

Ahmed Darwish,
Astral Cai,
Yushao Chen,
Christina Lee,
Expand Down
1 change: 0 additions & 1 deletion pennylane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@
transform,
batch_params,
batch_input,
batch_transform,
batch_partial,
compile,
defer_measurements,
Expand Down
96 changes: 65 additions & 31 deletions pennylane/devices/default_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,6 @@
PostprocessingFn = Callable[[ResultBatch], Result_or_ResultBatch]


observables = {
"PauliX",
"PauliY",
"PauliZ",
"Hadamard",
"Hermitian",
"Identity",
"Projector",
"SparseHamiltonian",
"Hamiltonian",
"LinearCombination",
"Sum",
"SProd",
"Prod",
"Exp",
"Evolution",
}


def observable_stopping_condition(obs: qml.operation.Operator) -> bool:
"""Specifies whether or not an observable is accepted by DefaultQubit."""
return obs.name in observables


def stopping_condition(op: qml.operation.Operator) -> bool:
"""Specify whether or not an Operator object is supported by the device."""
if op.name == "QFT" and len(op.wires) >= 6:
Expand All @@ -103,16 +79,74 @@ def stopping_condition_shots(op: qml.operation.Operator) -> bool:
return isinstance(op, (Conditional, MidMeasureMP)) or stopping_condition(op)


def observable_accepts_sampling(obs: qml.operation.Operator) -> bool:
"""Verifies whether an observable supports sample measurement"""

if isinstance(obs, qml.ops.CompositeOp):
return all(observable_accepts_sampling(o) for o in obs.operands)

if isinstance(obs, qml.ops.SymbolicOp):
return observable_accepts_sampling(obs.base)

if isinstance(obs, qml.ops.Hamiltonian):
return all(observable_accepts_sampling(o) for o in obs.ops)

if isinstance(obs, qml.operation.Tensor):
return all(observable_accepts_sampling(o) for o in obs.obs)

return obs.has_diagonalizing_gates


def observable_accepts_analytic(obs: qml.operation.Operator, is_expval=False) -> bool:
"""Verifies whether an observable supports analytic measurement"""

if isinstance(obs, qml.ops.CompositeOp):
return all(observable_accepts_analytic(o, is_expval) for o in obs.operands)

if isinstance(obs, qml.ops.SymbolicOp):
return observable_accepts_analytic(obs.base, is_expval)

if isinstance(obs, qml.ops.Hamiltonian):
return all(observable_accepts_analytic(o, is_expval) for o in obs.ops)

if isinstance(obs, qml.operation.Tensor):
return all(observable_accepts_analytic(o, is_expval) for o in obs.obs)

if is_expval and isinstance(obs, (qml.ops.SparseHamiltonian, qml.ops.Hermitian)):
return True

return obs.has_diagonalizing_gates


def accepted_sample_measurement(m: qml.measurements.MeasurementProcess) -> bool:
"""Specifies whether or not a measurement is accepted when sampling."""
return isinstance(
"""Specifies whether a measurement is accepted when sampling."""

if not isinstance(
m,
(
qml.measurements.SampleMeasurement,
qml.measurements.ClassicalShadowMP,
qml.measurements.ShadowExpvalMP,
),
)
):
return False

if m.obs is not None:
return observable_accepts_sampling(m.obs)

return True


def accepted_analytic_measurement(m: qml.measurements.MeasurementProcess) -> bool:
"""Specifies whether a measurement is accepted when analytic."""

if not isinstance(m, qml.measurements.StateMeasurement):
return False

if m.obs is not None:
return observable_accepts_analytic(m.obs, isinstance(m, qml.measurements.ExpectationMP))

return True


def null_postprocessing(results):
Expand Down Expand Up @@ -514,10 +548,10 @@ def preprocess(
name=self.name,
)
transform_program.add_transform(
validate_measurements, sample_measurements=accepted_sample_measurement, name=self.name
)
transform_program.add_transform(
validate_observables, stopping_condition=observable_stopping_condition, name=self.name
validate_measurements,
analytic_measurements=accepted_analytic_measurement,
sample_measurements=accepted_sample_measurement,
name=self.name,
)
if config.mcm_config.mcm_method == "tree-traversal":
transform_program.add_transform(qml.transforms.broadcast_expand)
Expand Down
4 changes: 3 additions & 1 deletion pennylane/devices/preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,9 @@ def sample_measurements(m):
and not isinstance(meas := op.hyperparameters["measurement"], qml.measurements.StateMP)
]

if tape.shots:
shots = qml.measurements.Shots(tape.shots)

if shots.total_shots is not None:
for m in chain(snapshot_measurements, tape.measurements):
if not sample_measurements(m):
raise DeviceError(f"Measurement {m} not accepted with finite shots on {name}")
Expand Down
5 changes: 0 additions & 5 deletions pennylane/tape/qscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,6 @@ def __len__(self):
# QSCRIPT properties
# ========================================================

@property
def interface(self):
"""str, None: automatic differentiation interface used by the quantum script (if any)"""
return None

@property
def circuit(self):
"""Returns the underlying quantum circuit as a list of operations and measurements.
Expand Down
2 changes: 0 additions & 2 deletions pennylane/transforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@
:toctree: api
~transforms.make_tape
~transforms.map_batch_transform
~transforms.create_expand_fn
~transforms.create_decomp_expand_fn
~transforms.expand_invalid_trainable
Expand Down Expand Up @@ -279,7 +278,6 @@ def circuit(x, y):

# Import the decorators first to prevent circular imports when used in other transforms
from .core import transform, TransformError
from .batch_transform import map_batch_transform
from .batch_params import batch_params
from .batch_input import batch_input
from .batch_partial import batch_partial
Expand Down
119 changes: 0 additions & 119 deletions pennylane/transforms/batch_transform.py

This file was deleted.

Loading

0 comments on commit eb86f21

Please sign in to comment.