Skip to content

[Decomposition] controlled decomposition with single work wire #7383

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

Merged
merged 184 commits into from
May 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
184 commits
Select commit Hold shift + click to select a range
925f8a2
[Decomposition] Custom decomposition rules for symbolic operators
astralcai Apr 29, 2025
fa09eac
fix doc?
astralcai Apr 29, 2025
95c0383
tests and bug fix
astralcai Apr 29, 2025
8f0a0de
update changelog
astralcai Apr 29, 2025
5b074ed
add more tests
astralcai Apr 29, 2025
ff90882
one more test case
astralcai Apr 29, 2025
9a57289
Merge branch 'master' into symbolic-rules-01
astralcai Apr 29, 2025
956b9a2
pylint
astralcai Apr 29, 2025
a8ccb91
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai Apr 29, 2025
32dba0b
pylint
astralcai Apr 29, 2025
edff8d4
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai Apr 29, 2025
7b37f5b
[Decomposition] Clean up custom logic for adjoint and pow
astralcai Apr 29, 2025
9483966
changelog
astralcai Apr 29, 2025
9a141f7
pylint and black
astralcai Apr 29, 2025
8551113
ooops
astralcai Apr 29, 2025
a3705e8
unused import
astralcai Apr 29, 2025
12a52c1
remove test
astralcai Apr 29, 2025
7a0d0d1
add missing coverage
astralcai Apr 29, 2025
7188cee
tests and missing coverage
astralcai Apr 29, 2025
58a3b4d
fix test
astralcai Apr 30, 2025
499cf59
fix siswap and tests
astralcai Apr 30, 2025
82c8780
ooops
astralcai Apr 30, 2025
85f0485
add missing coverage
astralcai Apr 30, 2025
46a18a0
missing coverage
astralcai Apr 30, 2025
92f0b84
changelog
astralcai Apr 30, 2025
2060ca1
revert some changes
astralcai Apr 30, 2025
5bc807f
[Decomposition] Clean up custom logic for Controlled decompositions
astralcai Apr 30, 2025
80088bd
changelog
astralcai Apr 30, 2025
92d73c4
rename something
astralcai May 1, 2025
399f7b9
missing coverage
astralcai May 1, 2025
dcab143
add missing coverage
astralcai May 1, 2025
26a314d
Apply suggestions from code review
astralcai May 1, 2025
9f03ac9
ooops
astralcai May 1, 2025
12766a5
ooops
astralcai May 1, 2025
02f08f2
Apply suggestions from code review
astralcai May 1, 2025
fa54ba2
lol
astralcai May 1, 2025
c0ada71
missing coverage
astralcai May 1, 2025
331d5d8
pylint
astralcai May 1, 2025
b6d6dbe
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 2, 2025
30c0c3c
ooops
astralcai May 2, 2025
c10e20e
Merge branch 'symbolic-rules-01' of https://github.com/PennyLaneAI/pe…
astralcai May 2, 2025
658609a
Merge branch 'symbolic-rules-02' of https://github.com/PennyLaneAI/pe…
astralcai May 2, 2025
a2393a3
[WIP] [Decomposition] Decomposition rules for ControlledQubitUnitary
astralcai May 2, 2025
60ff84f
changelog
astralcai May 2, 2025
1d97d85
isort
astralcai May 2, 2025
91eb683
add flip_zero_control
astralcai May 2, 2025
5752434
add controlled two-qubit unitary decomp
astralcai May 2, 2025
2a6cf25
move ctrl_decomp_zyz
astralcai May 2, 2025
f821747
clean imports
astralcai May 2, 2025
913263e
fix global phase bug
astralcai May 2, 2025
e78b870
clean up more test
astralcai May 2, 2025
a85a40f
minor fix
astralcai May 2, 2025
c18b60d
Merge branch 'master' into symbolic-rules-01
astralcai May 2, 2025
fb6b917
Merge branch 'symbolic-rules-01' of https://github.com/PennyLaneAI/pe…
astralcai May 2, 2025
2f41d10
Merge branch 'symbolic-rules-02' of https://github.com/PennyLaneAI/pe…
astralcai May 2, 2025
67e2088
Merge branch 'symbolic-rules-03' of https://github.com/PennyLaneAI/pe…
astralcai May 2, 2025
4ec7d32
finish clean up zyz tests
astralcai May 2, 2025
d3b53e1
clean up od tests
astralcai May 5, 2025
87ad388
clean up md tests
astralcai May 5, 2025
e068ba0
clean up more tests
astralcai May 5, 2025
8777aee
finish test cleanup
astralcai May 5, 2025
8dfa9aa
fix import
astralcai May 5, 2025
cf1bdeb
minor fix
astralcai May 5, 2025
5db0fc2
get rid of funny business
astralcai May 5, 2025
28e0f0d
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 5, 2025
aeeb4c5
Merge branch 'symbolic-rules-01' into symbolic-rules-02
astralcai May 5, 2025
fc72966
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 5, 2025
98c0898
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 5, 2025
2bc18e8
pylint
astralcai May 5, 2025
bfad7af
fix tests and bugs
astralcai May 5, 2025
10681b0
fix capture compatibility
astralcai May 5, 2025
320a2d4
more fix
astralcai May 5, 2025
c47cf0e
[Decomposition] controlled decomposition with single work wire
astralcai May 5, 2025
2dba0e4
unused import
astralcai May 5, 2025
3225c63
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 5, 2025
4f69e5f
changelog
astralcai May 5, 2025
2b9ef1d
fix small bug
astralcai May 5, 2025
c87181b
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 5, 2025
8bd5e8f
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 5, 2025
87a7ea6
Merge branch 'symbolic-rules-01' into symbolic-rules-02
astralcai May 5, 2025
400f878
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 5, 2025
de9a68a
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 5, 2025
ab7d99a
missing coverage
astralcai May 5, 2025
4889552
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 5, 2025
66a4482
ooops
astralcai May 5, 2025
5118747
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 5, 2025
108cc43
missing coverage
astralcai May 6, 2025
64855e7
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 6, 2025
7937863
ooops
astralcai May 6, 2025
6fd6f80
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 6, 2025
87ab8e2
missing coverage
astralcai May 6, 2025
74604ab
minor rename
astralcai May 7, 2025
220f671
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 7, 2025
d12873d
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 9, 2025
ed646dd
Merge branch 'symbolic-rules-01' into symbolic-rules-02
astralcai May 9, 2025
0fae402
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 9, 2025
f618634
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 9, 2025
559abd8
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 9, 2025
3bce1fb
rename pow_self_adjoint to pow_involutory
astralcai May 12, 2025
9f77626
apply suggestions from code review
astralcai May 12, 2025
9da982d
error message for when a symbolic operator name isn't recognized
astralcai May 12, 2025
4dac3ae
Merge branch 'master' into symbolic-rules-01
astralcai May 13, 2025
951bb2d
Merge branch 'symbolic-rules-01' into symbolic-rules-02
astralcai May 13, 2025
9c88d80
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 13, 2025
710bb9c
rework handling of custom controlled ops
astralcai May 13, 2025
ba2048b
fix small bug
astralcai May 13, 2025
5cadd76
fix test
astralcai May 14, 2025
000dfe6
clean up
astralcai May 14, 2025
ce96d08
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 14, 2025
e51fd76
fix something
astralcai May 14, 2025
2da187e
update docs
astralcai May 14, 2025
39358ab
Update pennylane/decomposition/decomposition_graph.py
astralcai May 15, 2025
dc939f9
[Decomposition] Register conditions to decomposition rules
astralcai May 14, 2025
f9de715
Merge branch 'conditional-decomp' into symbolic-rules-01
astralcai May 15, 2025
384cc32
Merge branch 'symbolic-rules-01' into symbolic-rules-02
astralcai May 15, 2025
db98d92
clean up adjoint and pow conditional decomposition rules
astralcai May 15, 2025
b649ce1
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 15, 2025
316d4c5
pylint
astralcai May 15, 2025
5b959e9
Merge branch 'conditional-decomp' into symbolic-rules-01
astralcai May 15, 2025
3d668ff
Merge branch 'symbolic-rules-01' into symbolic-rules-02
astralcai May 15, 2025
28b139d
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 15, 2025
88c0a69
fix conditionals
astralcai May 15, 2025
85ef46c
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 15, 2025
45dd6bb
rewrite conditionals
astralcai May 15, 2025
b7b93ca
add to_controlled_qubit_unitary
astralcai May 15, 2025
0267157
sphinx
astralcai May 15, 2025
69c35c7
add missing coverage
astralcai May 15, 2025
b6a0dd4
Merge branch 'conditional-decomp' into symbolic-rules-01
astralcai May 15, 2025
9db998e
Merge branch 'symbolic-rules-01' into symbolic-rules-02
astralcai May 15, 2025
5a45e7b
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 15, 2025
5a04953
ooops
astralcai May 15, 2025
15722a2
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 15, 2025
36af9a0
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 15, 2025
ea4af0d
something I missed
astralcai May 15, 2025
16bd2c3
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 15, 2025
4cf117d
add conditions to wrappers
astralcai May 15, 2025
2a531da
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 15, 2025
fea5055
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 15, 2025
d3a9075
fix something
astralcai May 15, 2025
e410584
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 15, 2025
bbd8897
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 15, 2025
660de6f
ooops
astralcai May 15, 2025
532ce09
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 15, 2025
1645b6a
ooops
astralcai May 15, 2025
ed6a4b0
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 15, 2025
556aba2
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 15, 2025
39266a9
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 15, 2025
c12eeb6
ooops
astralcai May 15, 2025
e209a58
missing coverage
astralcai May 15, 2025
9b82156
haha
astralcai May 15, 2025
cc9d835
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 15, 2025
3887d55
fix something
astralcai May 15, 2025
15d979d
fix
astralcai May 15, 2025
449f582
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 15, 2025
9b06b7c
Apply suggestions from code review
astralcai May 15, 2025
120fc3f
Merge branch 'master' into conditional-decomp
astralcai May 16, 2025
3db0e21
missing coverage
astralcai May 16, 2025
89cd40f
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 16, 2025
b00968c
fix
astralcai May 16, 2025
2f2e050
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 19, 2025
e9e5b06
Merge branch 'conditional-decomp' into symbolic-rules-01
astralcai May 19, 2025
d6cfe39
Merge branch 'symbolic-rules-01' into symbolic-rules-02
astralcai May 19, 2025
5d43c0b
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 19, 2025
97d7d18
minor fix
astralcai May 19, 2025
530d25b
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 19, 2025
e2961ac
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 19, 2025
66b2bfb
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 21, 2025
29cdf82
Merge branch 'symbolic-rules-02' into symbolic-rules-03
astralcai May 21, 2025
f4af940
Merge branch 'master' into symbolic-rules-03
astralcai May 21, 2025
b185e97
ooops
astralcai May 21, 2025
d13211d
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 21, 2025
fde1418
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 21, 2025
184163e
Merge branch 'master' into symbolic-rules-03
astralcai May 21, 2025
4a55140
update
astralcai May 21, 2025
5ac8c45
Merge branch 'symbolic-rules-03' into ctrl-qu
astralcai May 21, 2025
cb702a4
Merge branch 'ctrl-qu' into ctrl-work-wire
astralcai May 21, 2025
8eb7d2e
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai May 28, 2025
107e49a
ooops
astralcai May 28, 2025
a1985fa
Merge branch 'master' into ctrl-work-wire
astralcai May 28, 2025
de3ac3b
Merge branch 'master' into ctrl-work-wire
astralcai May 28, 2025
d82f000
Apply suggestions from code review
astralcai May 29, 2025
2165b6d
Merge branch 'master' into ctrl-work-wire
astralcai May 29, 2025
d21dab6
Merge branch 'master' into ctrl-work-wire
astralcai May 30, 2025
b10bee6
Merge branch 'master' into ctrl-work-wire
astralcai May 30, 2025
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
3 changes: 3 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@
0: ──RX(0.00)──RY(1.57)──RX(3.14)──GlobalPhase(-1.57)─┤ <Z>
```

* A new decomposition rule that uses a single work wire for decomposing multi-controlled operators is added.
[(#7383)](https://github.com/PennyLaneAI/pennylane/pull/7383)

* A :func:`~.decomposition.register_condition` decorator is added that allows users to bind a condition to a
decomposition rule for when it is applicable. The condition should be a function that takes the
resource parameters of an operator as arguments and returns `True` or `False` based on whether
Expand Down
4 changes: 4 additions & 0 deletions pennylane/decomposition/decomposition_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from .symbolic_decomposition import (
adjoint_rotation,
cancel_adjoint,
controlled_decomp_with_work_wire,
decompose_to_base,
flip_control_adjoint,
flip_pow_adjoint,
Expand Down Expand Up @@ -306,6 +307,9 @@ def _get_controlled_decompositions(
# qubit unitary if the base operator has a matrix form.
rules.append(to_controlled_qubit_unitary)

# There's always Lemma 7.11 from https://arxiv.org/abs/quant-ph/9503016.
rules.append(controlled_decomp_with_work_wire)

return rules

def solve(self, lazy=True):
Expand Down
39 changes: 39 additions & 0 deletions pennylane/decomposition/symbolic_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,45 @@ def flip_control_adjoint(*_, wires, control_wires, control_values, work_wires, b
)


def _controlled_decomp_with_work_wire_condition(num_control_wires, num_work_wires, **__):
return num_work_wires > 1 and num_control_wires > 1


def _controlled_decomp_with_work_wire_resource(
base_class, base_params, num_control_wires, num_work_wires, **__
):
return {
controlled_resource_rep(qml.X, {}, num_control_wires, num_work_wires=num_work_wires - 1): 2,
controlled_resource_rep(base_class, base_params, 1, 0): 1,
}


# pylint: disable=protected-access,unused-argument
@register_condition(_controlled_decomp_with_work_wire_condition)
@register_resources(_controlled_decomp_with_work_wire_resource)
def _controlled_decomp_with_work_wire(
*params, wires, control_wires, control_values, work_wires, base, **__
):
"""Implements Lemma 7.11 from https://arxiv.org/abs/quant-ph/9503016."""
base_op = base._unflatten(*base._flatten())
qml.ctrl(
qml.X(work_wires[0]),
control=wires[: len(control_wires)],
control_values=control_values,
work_wires=work_wires[1:],
)
qml.ctrl(base_op, control=work_wires[0])
qml.ctrl(
qml.X(work_wires[0]),
control=wires[: len(control_wires)],
control_values=control_values,
work_wires=work_wires[1:],
)


controlled_decomp_with_work_wire = flip_zero_control(_controlled_decomp_with_work_wire)


def _to_controlled_qu_condition(base_class, **__):
return base_class.has_matrix and base_class.num_wires == 1

Expand Down
29 changes: 29 additions & 0 deletions tests/decomposition/test_decomposition_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,35 @@ def test_flip_controlled_adjoint(self, _):
graph.decomposition(op)(*op.parameters, wires=op.wires, **op.hyperparameters)
assert q.queue == [qml.adjoint(qml.ops.Controlled(qml.U1(0.5, wires=0), control_wires=[1]))]

def test_decompose_with_single_work_wire(self, _):
"""Tests that the Lemma 7.11 decomposition from https://arxiv.org/pdf/quant-ph/9503016 is applied correctly."""

op = qml.ctrl(qml.Rot(0.123, 0.234, 0.345, wires=0), control=[1, 2, 3], work_wires=[4, 5])

graph = DecompositionGraph(
operations=[op],
gate_set={"MultiControlledX", "CRot"},
)
graph.solve()
with qml.queuing.AnnotatedQueue() as q:
graph.decomposition(op)(*op.parameters, wires=op.wires, **op.hyperparameters)
assert q.queue == [
qml.MultiControlledX(wires=[1, 2, 3, 4], work_wires=[5]),
qml.CRot(0.123, 0.234, 0.345, wires=[4, 0]),
qml.MultiControlledX(wires=[1, 2, 3, 4], work_wires=[5]),
]
assert graph.resource_estimate(op) == to_resources(
{
resource_rep(
qml.MultiControlledX,
num_control_wires=3,
num_zero_control_values=0,
num_work_wires=1,
): 2,
qml.CRot: 1,
}
)


@patch(
"pennylane.decomposition.decomposition_graph.list_decomps",
Expand Down
26 changes: 26 additions & 0 deletions tests/decomposition/test_symbolic_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from pennylane.decomposition.symbolic_decomposition import (
adjoint_rotation,
cancel_adjoint,
controlled_decomp_with_work_wire,
controlled_resource_rep,
flip_control_adjoint,
flip_pow_adjoint,
Expand Down Expand Up @@ -706,6 +707,31 @@ def test_flip_control_adjoint(self):
}
)

@pytest.mark.unit
def test_controlled_decomp_with_work_wire(self):
"""Tests the controlled decomposition with a single work wire (Lemma 7.11 from https://arxiv.org/pdf/quant-ph/9503016)."""

U = qml.Rot.compute_matrix(0.123, 0.234, 0.345)
op = qml.ctrl(qml.QubitUnitary(U, wires=0), control=[1, 2], work_wires=[3])

with queuing.AnnotatedQueue() as q:
qml.Projector([0], wires=3)
controlled_decomp_with_work_wire(*op.parameters, wires=op.wires, **op.hyperparameters)

mat = qml.matrix(qml.tape.QuantumScript.from_queue(q), wire_order=[0, 1, 2, 3])
expected_mat = qml.matrix(op @ qml.Projector([0], wires=3), wire_order=[0, 1, 2, 3])
assert qml.math.allclose(mat, expected_mat)

@pytest.mark.unit
def test_controlled_decomp_with_work_wire_not_applicable(self):
"""Tests that the controlled_decomp_with_work_wire is not applicable sometimes."""

op = qml.ctrl(qml.RX(0.5, wires=0), control=[1], control_values=[0], work_wires=[3])
assert not controlled_decomp_with_work_wire.is_applicable(**op.resource_params)

op = qml.ctrl(qml.RX(0.5, wires=0), control=[1, 2])
assert not controlled_decomp_with_work_wire.is_applicable(**op.resource_params)

def test_decompose_to_controlled_unitary(self):
"""Tests the decomposition to controlled qubit unitary"""

Expand Down
Loading