Skip to content

Commit f369d30

Browse files
authored
Merge branch 'main' into deprecate-rot-angles
2 parents 0093147 + ca8af82 commit f369d30

13 files changed

Lines changed: 1940 additions & 342 deletions

File tree

doc/releases/changelog-dev.md

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,58 @@
1515
The new function returns a tuple of four values, where the first three corresponds to the rotation
1616
angles of the ZYZ decomposition of this operator, and the last one corresponds to the global phase.
1717

18+
* :func:`~.specs` will now output symbolic resource information when it encounters a loop that uses dynamic control-flow
19+
that can't be resolved at compile time.
20+
In such cases the returned :class:`~.resource.CircuitSpecs` will contain :class:`~.resource.SymbolicSpecsResources` instances instead of the usual :class:`~.resource.SpecsResources` instances.
21+
22+
```python
23+
@qp.qjit(autograph=True)
24+
@qp.qnode(qp.device("lightning.qubit", wires=1))
25+
def circuit(x):
26+
qp.Hadamard(0)
27+
qp.PauliX(0)
28+
for _ in range(x):
29+
qp.PauliX(0)
30+
return qp.expval(qp.PauliX(0))
31+
32+
specs_result = qp.specs(circuit, level=0)(5)
33+
```
34+
35+
```pycon
36+
>>> print(specs_result)
37+
Device: lightning.qubit
38+
Device wires: 1
39+
Shots: Shots(total=None)
40+
Level: Before MLIR Passes
41+
<BLANKLINE>
42+
Symbolic Variables: a
43+
Wire allocations: 1
44+
Total gates: a + 2
45+
Gate counts:
46+
- Hadamard: 1
47+
- PauliX: a + 1
48+
Measurements:
49+
- expval(PauliX): 1
50+
Depth: Not computed
51+
52+
```
53+
54+
These symbolic resources include expressions with variables which can substituted for concrete values to compute the associated resources for a circuit, via the ``subs`` method.
55+
56+
```pycon
57+
>>> res = specs_result.resources
58+
>>> print(res.subs(a=5))
59+
Wire allocations: 1
60+
Total gates: 7
61+
Gate counts:
62+
- Hadamard: 1
63+
- PauliX: 6
64+
Measurements:
65+
- expval(PauliX): 1
66+
Depth: Not computed
67+
68+
```
69+
1870
* A new template for Fast Fermionic Fourier Transforms called :class:`~.FFFT` has been added.
1971
This algorithm is based on [Ferris (2013)](https://arxiv.org/abs/1310.7605) and applies to
2072
efficient simulation of quantum materials and chemistry systems.
@@ -46,7 +98,7 @@
4698

4799
Alongside the addition of :class:`~.FFFT`, a new operation called :class:`~.TwoWireFFT`
48100
has been added to enable its implementation: the :class:`~.FFFT` operation is
49-
decomposed recursively into :class:`~.FermionicSWAP` and :class:`~.TwoWireFFT` operations
101+
decomposed recursively into :class:`~.FermionicSWAP` and :class:`~.TwoWireFFT` operations
50102
(two-site Fermionic Fourier transforms).
51103

52104
<h3>Improvements 🛠</h3>
@@ -92,7 +144,7 @@
92144
```
93145
[(#9368)](https://github.com/PennyLaneAI/pennylane/pull/9368)
94146

95-
* Updated `qp.registers` to accept empty registers (e.g., `qp.registers({"algo_wires": 5, "work_wires": 0})).
147+
* Updated `qp.registers` to accept empty registers (e.g., `qp.registers({"algo_wires": 5, "work_wires": 0})).
96148
[(#9543)](https://github.com/PennyLaneAI/pennylane/pull/9543)
97149

98150
* Removed instances of using the deprecated way to set shots on a device `device(..., shots=...)`.
@@ -150,7 +202,7 @@
150202
True
151203

152204
```
153-
205+
154206
* Created a new ``labs.templates.LeftClassicalComparator`` template for performing an inequality
155207
test of a quantum register and an integer.
156208
[(#9308)](https://github.com/PennyLaneAI/pennylane/pull/9308)
@@ -175,12 +227,12 @@
175227
)
176228
return qp.sample(wires=3)
177229
```
178-
230+
179231
```pycon
180232
>>> output = circuit(3, 2)
181233
>>> print(bool(output)) # 3 >= 2
182234
True
183-
235+
184236
```
185237

186238
* Update phase gradient transforms to use ``BasisState`` instead of ``BasisEmbedding``.
@@ -360,6 +412,10 @@
360412

361413
<h3>Bug fixes 🐛</h3>
362414

415+
* Fixed a bug in `change_op_basis` where `TypeError` raised within the body of callable inputs were
416+
accidentally being masked by internal try/except logic.
417+
[(#9552)](https://github.com/PennyLaneAI/pennylane/pull/9552)
418+
363419
* Fixed a bug in unary iteration in `Select` where work wires were not restored correctly
364420
if the number of selected operators is notably smaller than the maximal capacity for the given
365421
number of control wires. This bug only surfaced for `partial=False`.
@@ -423,4 +479,5 @@ Andrija Paurevic,
423479
Francesco Pernice Botta,
424480
Jay Soni,
425481
Paul Haochen Wang,
426-
David Wierichs.
482+
David Wierichs,
483+
Jake Zaia.

pennylane/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616
Version number (major.minor.patch[-label])
1717
"""
1818

19-
__version__ = "0.46.0-dev21"
19+
__version__ = "0.46.0-dev23"

pennylane/ops/op_math/change_op_basis.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
This submodule defines a class for compute-uncompute patterns.
1616
"""
1717

18+
import inspect
1819
from collections import Counter, defaultdict
1920
from collections.abc import Callable
2021
from functools import reduce
@@ -39,14 +40,31 @@
3940
from .composite import CompositeOp, handle_recursion_error
4041

4142

42-
def _apply_op_or_func(op_or_func):
43-
if isinstance(op_or_func, Callable):
44-
try:
45-
op_or_func()
46-
except TypeError as e:
43+
def _validate_callable(func: Callable) -> None:
44+
"""Validates that a callable has no unbound mandatory parameters."""
45+
sig = inspect.signature(func)
46+
47+
for param in sig.parameters.values():
48+
# The function,
49+
#
50+
# def f(*args, **kwargs):
51+
# pass
52+
#
53+
# technically doesn't have any required parameters.
54+
if param.kind in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD):
55+
continue
56+
57+
# If param has no default we can early exit
58+
if param.default is inspect.Parameter.empty:
4759
raise TypeError(
48-
"change_op_basis requires that Callable inputs have no parameters. functools.partial can be used to achieve this."
49-
) from e
60+
"change_op_basis requires that Callable inputs have no unbound mandatory parameters. Please use functools.partial to bind them."
61+
)
62+
63+
64+
def _apply_op_or_func(op_or_func):
65+
if callable(op_or_func):
66+
_validate_callable(op_or_func)
67+
op_or_func()
5068
elif isinstance(op_or_func, Operator):
5169
type(op_or_func)._unflatten(*op_or_func._flatten()) # pylint: disable=protected-access
5270
elif math.is_abstract(op_or_func):
@@ -58,13 +76,9 @@ def _apply_op_or_func(op_or_func):
5876

5977

6078
def _convert_to_prod(op_or_func):
61-
if isinstance(op_or_func, Callable):
62-
try:
63-
return prod(op_or_func)()
64-
except TypeError as e:
65-
raise TypeError(
66-
"change_op_basis requires that Callable inputs have no parameters. functools.partial can be used to achieve this."
67-
) from e
79+
if callable(op_or_func):
80+
_validate_callable(op_or_func)
81+
return prod(op_or_func)()
6882
if isinstance(op_or_func, Operator):
6983
return op_or_func
7084
raise TypeError(

pennylane/resource/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@
3737
:toctree: api
3838
3939
~CircuitSpecs
40+
~Expression
4041
~SpecsResources
42+
~SymbolicSpecsResources
4143
4244
~resources_from_tape
4345
@@ -138,6 +140,7 @@ def circuit(theta):
138140
Resources,
139141
ResourcesOperation,
140142
SpecsResources,
143+
SymbolicSpecsResources,
141144
CircuitSpecs,
142145
add_in_series,
143146
add_in_parallel,
@@ -146,4 +149,5 @@ def circuit(theta):
146149
resources_from_tape,
147150
substitute,
148151
)
152+
from .expression import Expression
149153
from .specs import specs

0 commit comments

Comments
 (0)