Skip to content
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
476 commits
Select commit Hold shift + click to select a range
6cda3bf
format
andrijapau Nov 26, 2025
86b5662
Update frontend/catalyst/python_interface/visualization/dag_builder.py
andrijapau Nov 26, 2025
9c26efd
Update frontend/catalyst/python_interface/visualization/pydot_dag_bui…
andrijapau Nov 26, 2025
81a9aa6
Update frontend/catalyst/python_interface/visualization/pydot_dag_bui…
andrijapau Nov 26, 2025
ab06276
Update frontend/test/pytest/python_interface/visualization/test_pydot…
andrijapau Nov 26, 2025
3e4102b
Update frontend/catalyst/python_interface/visualization/pydot_dag_bui…
andrijapau Nov 26, 2025
194f14a
Update frontend/catalyst/python_interface/visualization/dag_builder.py
andrijapau Nov 26, 2025
199ab70
add reset
andrijapau Nov 26, 2025
e28a1a9
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
24d3dd3
Apply suggestion from @andrijapau
andrijapau Nov 26, 2025
685842c
fix fakebackend
andrijapau Nov 26, 2025
986fb3f
Merge branch 'fix/upgrade-dag-builders' into feature/mlir-to-dag-pass
andrijapau Nov 26, 2025
07b7655
Merge branch 'feature/mlir-to-dag-pass' into feature/visualize-qnode
andrijapau Nov 26, 2025
11f5864
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
8c64d81
isort
andrijapau Nov 26, 2025
606f5f5
Merge branch 'fix/upgrade-dag-builders' into feature/mlir-to-dag-pass
andrijapau Nov 26, 2025
edfcb93
Merge branch 'feature/mlir-to-dag-pass' into feature/visualize-qnode
andrijapau Nov 26, 2025
0370886
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
9847b39
try moving cluster stack to dag builder
andrijapau Nov 26, 2025
57ce573
add test
andrijapau Nov 26, 2025
805d21b
Revert "add test"
andrijapau Nov 26, 2025
c0e0283
Revert "try moving cluster stack to dag builder"
andrijapau Nov 26, 2025
e1a6c64
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
2a960cf
improve device test
andrijapau Nov 26, 2025
a21e6dd
fix black isort
andrijapau Nov 26, 2025
b06585b
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
f666a9f
add exceptions check
andrijapau Nov 26, 2025
e28b2b7
add better documentation
andrijapau Nov 26, 2025
af5e52c
fix
andrijapau Nov 26, 2025
952fd7f
fix typo
andrijapau Nov 26, 2025
99f9fc6
Merge branch 'fix/upgrade-dag-builders' into feature/mlir-to-dag-pass
andrijapau Nov 26, 2025
492276d
Merge branch 'feature/mlir-to-dag-pass' into feature/visualize-qnode
andrijapau Nov 26, 2025
8f2dc98
Apply suggestion from @andrijapau
andrijapau Nov 26, 2025
eac25d5
Merge branch 'fix/upgrade-dag-builders' into feature/mlir-to-dag-pass
andrijapau Nov 26, 2025
b06e92e
Merge branch 'feature/mlir-to-dag-pass' into feature/visualize-qnode
andrijapau Nov 26, 2025
53497ba
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
83225b3
Merge branch 'feature/graph-visualization' into feature/mlir-to-dag-pass
andrijapau Nov 26, 2025
7d04249
fix tests
andrijapau Nov 26, 2025
fbb0c5a
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
941675f
Merge branch 'feature/mlir-to-dag-pass' into feature/visualize-qnode
andrijapau Nov 26, 2025
bb9549d
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
2bad538
add reminder comments
andrijapau Nov 26, 2025
683768e
add back comment
andrijapau Nov 26, 2025
2adb3b2
format
andrijapau Nov 26, 2025
f7bbb6b
fix test name
andrijapau Nov 26, 2025
f7f4b5a
fix test
andrijapau Nov 26, 2025
a21f878
fix tests
andrijapau Nov 26, 2025
ae0ff32
format
andrijapau Nov 26, 2025
26ae968
Apply suggestion from @andrijapau
andrijapau Nov 26, 2025
1d4f1f1
more explanation
andrijapau Nov 26, 2025
70ec17a
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 26, 2025
ed8bae0
more fixes
andrijapau Nov 26, 2025
25e8051
fix up testing
andrijapau Nov 26, 2025
ffc9726
fix naming
andrijapau Nov 26, 2025
a243614
Merge branch 'feature/mlir-to-dag-pass' into feature/visualize-qnode
andrijapau Nov 26, 2025
0659cdf
Merge branch 'feature/mlir-to-dag-pass' into feature/visualize-nodes
andrijapau Nov 26, 2025
e58891a
new testing approach
andrijapau Nov 27, 2025
6d1ab99
format
andrijapau Nov 27, 2025
710e6a8
test the fakebackend
andrijapau Nov 27, 2025
cb931d1
whoops forgot test
andrijapau Nov 27, 2025
049a683
improve test
andrijapau Nov 27, 2025
9ea917e
add new feature of jit_ prefix removal and single qnode
andrijapau Nov 27, 2025
fd41bc5
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 27, 2025
fd26a37
whoops
andrijapau Nov 27, 2025
1ad2ec0
format
andrijapau Nov 27, 2025
7fdbac0
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 27, 2025
8fc4a30
improve some tests
andrijapau Nov 27, 2025
bfd28b2
shouldn't have conditional label
andrijapau Nov 27, 2025
4753071
Merge branch 'feature/graph-visualization' into feature/visualize-qnode
andrijapau Nov 28, 2025
6200c76
Merge branch 'feature/graph-visualization' into feature/visualize-qnode
andrijapau Nov 28, 2025
1f90c6d
Merge branch 'feature/graph-visualization' into feature/visualize-qnode
andrijapau Nov 28, 2025
9aef399
id to uid rename
andrijapau Nov 28, 2025
e87dba2
format
andrijapau Nov 28, 2025
14ed4bc
Merge branch 'feature/graph-visualization' into feature/visualize-qnode
andrijapau Nov 28, 2025
be1961c
rename inner stack
andrijapau Nov 28, 2025
c92736a
format
andrijapau Nov 28, 2025
ca44e59
Apply suggestion from @andrijapau
andrijapau Nov 28, 2025
f84a6f1
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 28, 2025
3a8da55
Apply suggestion from @andrijapau
andrijapau Nov 28, 2025
26e95f9
format
andrijapau Nov 28, 2025
d7f21bd
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 28, 2025
c9594ee
fix
andrijapau Nov 28, 2025
d76fcca
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Nov 28, 2025
c0554c5
fix
andrijapau Nov 28, 2025
a80141c
format
andrijapau Nov 28, 2025
529cace
rename cluster stack
andrijapau Nov 28, 2025
4a172dd
return op doesnt have regions
andrijapau Dec 1, 2025
a54de21
Apply suggestion from @andrijapau
andrijapau Dec 1, 2025
5a731c0
Merge branch 'feature/graph-visualization' into feature/visualize-qnode
andrijapau Dec 1, 2025
53f80b3
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Dec 1, 2025
2bb5bde
update testing and add for loop label upgrade
andrijapau Dec 1, 2025
434c500
fix
andrijapau Dec 1, 2025
cfa5f3b
add more tests
andrijapau Dec 1, 2025
a62f2b1
add dev comments
andrijapau Dec 1, 2025
d9026ef
more testing
andrijapau Dec 1, 2025
faf338f
move things around
andrijapau Dec 1, 2025
5d03a81
add more qol
andrijapau Dec 2, 2025
56e4756
Update frontend/catalyst/python_interface/visualization/construct_cir…
andrijapau Dec 2, 2025
c95c45f
Update frontend/catalyst/python_interface/visualization/construct_cir…
andrijapau Dec 2, 2025
18aa30b
Update frontend/catalyst/python_interface/visualization/construct_cir…
andrijapau Dec 2, 2025
929bd23
add flattened ifop ability
andrijapau Dec 2, 2025
709e961
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Dec 2, 2025
b51bb7b
fix
andrijapau Dec 2, 2025
89f45f3
fix
andrijapau Dec 2, 2025
b45b2f0
fix
andrijapau Dec 2, 2025
2028fa7
fix
andrijapau Dec 2, 2025
4e994e6
simplify PR by making it for ...
andrijapau Dec 2, 2025
e590847
format
andrijapau Dec 2, 2025
eb6a0c3
fix tests
andrijapau Dec 2, 2025
7eb31b6
format
andrijapau Dec 2, 2025
8e787c9
fix logic in flatten if op
andrijapau Dec 2, 2025
8b6287f
format
andrijapau Dec 2, 2025
83ebb18
fix type hinting
andrijapau Dec 2, 2025
6d84d36
add dev comment
andrijapau Dec 2, 2025
1d8ac14
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 2, 2025
3c42841
more deviceop tests
andrijapau Dec 2, 2025
e319aae
Apply suggestion from @andrijapau
andrijapau Dec 2, 2025
1c9c857
re-order changelog
andrijapau Dec 2, 2025
093a5d5
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Dec 2, 2025
2ca7bb8
add cl entry
andrijapau Dec 2, 2025
9d724bf
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 2, 2025
61b70d9
add smaller fontsize for the conditional bit
andrijapau Dec 2, 2025
3a2ab18
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 2, 2025
e9c69d8
format
andrijapau Dec 2, 2025
f47b1a5
fix id to uid
andrijapau Dec 2, 2025
5e83fe4
fix
andrijapau Dec 2, 2025
d5a0611
Apply suggestion from @andrijapau
andrijapau Dec 2, 2025
98bf7ea
clean-up
andrijapau Dec 2, 2025
818448c
clean up
andrijapau Dec 2, 2025
b924c43
format
andrijapau Dec 2, 2025
089cb14
both single and multi qnode have qjit bounding box
andrijapau Dec 3, 2025
2a2d55c
Apply suggestion from @andrijapau
andrijapau Dec 3, 2025
220c6d5
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Dec 3, 2025
f7261a9
add more detail to the for loop label
andrijapau Dec 3, 2025
a8cd49c
format
andrijapau Dec 3, 2025
44bf9d3
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 3, 2025
70b0d93
fix test
andrijapau Dec 3, 2025
d983e97
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 3, 2025
cb05921
use counter instead of builtin id function
andrijapau Dec 4, 2025
1883fb3
whoops
andrijapau Dec 4, 2025
5e2d456
Apply suggestion from @andrijapau
andrijapau Dec 4, 2025
36b5f7d
Apply suggestion from @andrijapau
andrijapau Dec 4, 2025
ee15b67
Apply suggestion from @andrijapau
andrijapau Dec 4, 2025
16e003d
add two counters
andrijapau Dec 4, 2025
23561f7
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Dec 4, 2025
d5ccaf7
use the counters for uid
andrijapau Dec 4, 2025
1dd9f38
update tests to be simpler
andrijapau Dec 4, 2025
6a9b01d
fix tests
andrijapau Dec 4, 2025
a2ac9ff
minor fix
andrijapau Dec 4, 2025
0dbe4fe
foramt
andrijapau Dec 4, 2025
d92aea4
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Dec 4, 2025
8afc67a
Apply suggestion from @andrijapau
andrijapau Dec 4, 2025
c0d4d67
update tests
andrijapau Dec 4, 2025
9706967
update tests
andrijapau Dec 4, 2025
5e62c31
format
andrijapau Dec 4, 2025
1474a66
whoops fix test
andrijapau Dec 4, 2025
82430af
Merge branch 'feature/visualize-qnode' into feature/control-flow-clus…
andrijapau Dec 4, 2025
ced6f75
format
andrijapau Dec 4, 2025
649aed2
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 4, 2025
9c74b6a
update id
andrijapau Dec 4, 2025
5641e68
fix test
andrijapau Dec 4, 2025
4ffc9d3
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 4, 2025
22c8ae1
add more nested testing
andrijapau Dec 4, 2025
ab7c471
format
andrijapau Dec 4, 2025
dd1df44
adjust test
andrijapau Dec 4, 2025
57409bd
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 4, 2025
9996684
fix test
andrijapau Dec 4, 2025
303fb03
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 4, 2025
c262df9
format
andrijapau Dec 4, 2025
05df88c
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 4, 2025
3175efa
add tests
andrijapau Dec 4, 2025
194b357
fix get_nodes -> nodes
andrijapau Dec 4, 2025
506f839
fix labels
andrijapau Dec 4, 2025
f67802f
fix labels
andrijapau Dec 4, 2025
ad35efc
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 4, 2025
fac6150
fix measure
andrijapau Dec 5, 2025
9bdf8da
fix globalphase test
andrijapau Dec 5, 2025
b9479b1
fix sample test
andrijapau Dec 5, 2025
60e83c4
fix sample
andrijapau Dec 5, 2025
ebd108e
format
andrijapau Dec 5, 2025
bfd1d10
add dev comment
andrijapau Dec 5, 2025
aec9f83
fix code
andrijapau Dec 5, 2025
c36a43e
fix naming
andrijapau Dec 5, 2025
6c1d825
add expected error messages
andrijapau Dec 5, 2025
7b56f89
fix test for probs
andrijapau Dec 5, 2025
4f83355
format
andrijapau Dec 5, 2025
9f6a131
add compileerror
andrijapau Dec 5, 2025
9855985
update
andrijapau Dec 5, 2025
30db67e
Merge branch 'feature/graph-visualization' into feature/control-flow-…
andrijapau Dec 5, 2025
2fe2074
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 5, 2025
d069fef
fix
andrijapau Dec 5, 2025
b65ae16
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 5, 2025
e29f546
bring back ssavalue
andrijapau Dec 5, 2025
b34d8e2
format
andrijapau Dec 5, 2025
aa1d90c
format
andrijapau Dec 5, 2025
d3fdfea
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 5, 2025
27ff971
remove random import
andrijapau Dec 5, 2025
1a0ac68
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 5, 2025
5e3a6d2
re-work node labels to be records with ports
andrijapau Dec 5, 2025
a25f7b4
format
andrijapau Dec 5, 2025
02d4a55
fix tests
andrijapau Dec 5, 2025
7237a3f
move mid measure to an operator
andrijapau Dec 5, 2025
6410aae
fix test
andrijapau Dec 6, 2025
20efb54
get rid of unnecessary function
andrijapau Dec 9, 2025
81e9fe5
Update frontend/catalyst/python_interface/visualization/construct_cir…
andrijapau Dec 9, 2025
dcf59ae
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 9, 2025
7eb1da4
Update frontend/test/pytest/python_interface/visualization/test_const…
andrijapau Dec 9, 2025
f7daa8a
Update doc/releases/changelog-dev.md
andrijapau Dec 9, 2025
80da43c
Update frontend/test/pytest/python_interface/visualization/test_const…
andrijapau Dec 9, 2025
5fc9cf1
fix bug and add test coverage
andrijapau Dec 9, 2025
ef5550f
fix test and format
andrijapau Dec 9, 2025
5476e6d
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 9, 2025
dfde76d
format
andrijapau Dec 9, 2025
ecddff7
fix
andrijapau Dec 9, 2025
c2bd854
remove ssa condition, not needed for now
andrijapau Dec 9, 2025
4176d03
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 9, 2025
f8b2922
refactor a bit
andrijapau Dec 9, 2025
89dad36
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 9, 2025
e58cc4e
add another test
andrijapau Dec 9, 2025
1877cf9
whoops
andrijapau Dec 9, 2025
8643a24
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 9, 2025
c35b8c1
Apply suggestion from @andrijapau
andrijapau Dec 9, 2025
5728859
Apply suggestion from @andrijapau
andrijapau Dec 9, 2025
5345dfc
format
andrijapau Dec 9, 2025
04ee8e2
update how the node labels look
andrijapau Dec 9, 2025
74e8358
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 9, 2025
d8c1b7a
improve logic
andrijapau Dec 9, 2025
bafd278
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 9, 2025
284f56b
Update frontend/catalyst/python_interface/visualization/construct_cir…
andrijapau Dec 9, 2025
8b2ec3c
remove redundant label
andrijapau Dec 9, 2025
488de58
add dev comment
andrijapau Dec 9, 2025
490949b
format
andrijapau Dec 9, 2025
3494f17
improve function naming
andrijapau Dec 9, 2025
fee7e1b
fix labels for measurements
andrijapau Dec 10, 2025
e15bdc0
add record
andrijapau Dec 10, 2025
2071360
Merge branch 'feature/graph-visualization' into feature/control-flow-…
andrijapau Dec 10, 2025
c86043f
remove node label
andrijapau Dec 10, 2025
5aeba5e
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 10, 2025
ea8c9b7
add labeljust
andrijapau Dec 10, 2025
d224c0c
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 10, 2025
8392c2b
remove comment
andrijapau Dec 10, 2025
80798f9
fix cluster
andrijapau Dec 10, 2025
cb1e531
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 10, 2025
1f48498
fix
andrijapau Dec 10, 2025
ac5ffe7
Apply suggestion from @andrijapau
andrijapau Dec 10, 2025
27cc772
Merge branch 'feature/control-flow-clusters' into feature/visualize-n…
andrijapau Dec 10, 2025
90e6588
fix
andrijapau Dec 10, 2025
2983d67
fix
andrijapau Dec 10, 2025
24ffa25
Merge branch 'feature/graph-visualization' into feature/visualize-nodes
andrijapau Dec 10, 2025
c9ec867
fix
andrijapau Dec 10, 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
2 changes: 2 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
[(#2214)](https://github.com/PennyLaneAI/catalyst/pull/2214)
[(#2246)](https://github.com/PennyLaneAI/catalyst/pull/2246)
[(#2231)](https://github.com/PennyLaneAI/catalyst/pull/2231)
[(#2234)](https://github.com/PennyLaneAI/catalyst/pull/2234)
[(#2218)](https://github.com/PennyLaneAI/catalyst/pull/2218)

* Added ``catalyst.switch``, a qjit compatible, index-switch style control flow decorator.
[(#2171)](https://github.com/PennyLaneAI/catalyst/pull/2171)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@

"""Contains the ConstructCircuitDAG tool for constructing a DAG from an xDSL module."""

from functools import singledispatchmethod

from xdsl.dialects import builtin, func
from xdsl.ir import Block, Operation, Region

from catalyst.python_interface.dialects import catalyst, quantum
from functools import singledispatch, singledispatchmethod

from pennylane.measurements import MeasurementProcess
from pennylane.operation import Operator
from xdsl.dialects import builtin, func, scf
from xdsl.ir import Block, Operation, Region, SSAValue

from catalyst.python_interface.dialects import quantum
from catalyst.python_interface.inspection.xdsl_conversion import (
xdsl_to_qml_measurement,
xdsl_to_qml_op,
)
from catalyst.python_interface.visualization.dag_builder import DAGBuilder


Expand Down Expand Up @@ -85,6 +91,205 @@ def _visit_block(self, block: Block) -> None:
for op in block.ops:
self._visit_operation(op)

# ===================
# QUANTUM OPERATIONS
# ===================

@_visit_operation.register
def _unitary(
self,
op: quantum.CustomOp | quantum.GlobalPhaseOp | quantum.QubitUnitaryOp | quantum.MultiRZOp,
) -> None:
"""Generic handler for unitary gates."""

# Create PennyLane instance
qml_op = xdsl_to_qml_op(op)

# Add node to current cluster
node_uid = f"node{self._node_uid_counter}"
self.dag_builder.add_node(
uid=node_uid,
label=get_label(qml_op),
cluster_uid=self._cluster_uid_stack[-1],
# NOTE: "record" allows us to use ports (https://graphviz.org/doc/info/shapes.html#record)
shape="record",
)
self._node_uid_counter += 1

@_visit_operation.register
def _projective_measure_op(self, op: quantum.MeasureOp) -> None:
"""Handler for the single-qubit projective measurement operation."""

# Create PennyLane instance
meas = xdsl_to_qml_measurement(op)

# Add node to current cluster
node_uid = f"node{self._node_uid_counter}"
self.dag_builder.add_node(
uid=node_uid,
label=get_label(meas),
cluster_uid=self._cluster_uid_stack[-1],
# NOTE: "record" allows us to use ports (https://graphviz.org/doc/info/shapes.html#record)
shape="record",
)
self._node_uid_counter += 1

# =====================
# QUANTUM MEASUREMENTS
# =====================

@_visit_operation.register
def _state_op(self, op: quantum.StateOp) -> None:
"""Handler for the terminal state measurement operation."""

# Create PennyLane instance
meas = xdsl_to_qml_measurement(op)

# Add node to current cluster
node_uid = f"node{self._node_uid_counter}"
self.dag_builder.add_node(
uid=node_uid,
label=get_label(meas),
cluster_uid=self._cluster_uid_stack[-1],
fillcolor="lightpink",
color="lightpink3",
)
self._node_uid_counter += 1

@_visit_operation.register
def _statistical_measurement_ops(
self,
op: quantum.ExpvalOp | quantum.VarianceOp,
) -> None:
"""Handler for statistical measurement operations."""

# Create PennyLane instance
obs_op = op.obs.owner
meas = xdsl_to_qml_measurement(op, xdsl_to_qml_measurement(obs_op))

# Add node to current cluster
node_uid = f"node{self._node_uid_counter}"
self.dag_builder.add_node(
uid=node_uid,
label=get_label(meas),
cluster_uid=self._cluster_uid_stack[-1],
fillcolor="lightpink",
color="lightpink3",
)
self._node_uid_counter += 1

@_visit_operation.register
def _visit_sample_and_probs_ops(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about counts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I don't really see why you're handling all the measurements in separate functions. Let me know if your agree, but they seem too similar to need different dispatches. I think a match-case might make more sense. I can totally be convinced otherwise though

Copy link
Contributor Author

@andrijapau andrijapau Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about counts?

Turns out Pietro's work didn't have support for counts 😬. Not sure why.

self,
op: quantum.SampleOp | quantum.ProbsOp,
) -> None:
"""Handler for sample operations."""

# Create PennyLane instance
obs_op = op.obs.owner

# TODO: This doesn't logically make sense, but quantum.compbasis
# is obs_op and function below just pulls out the static wires
wires = xdsl_to_qml_measurement(obs_op)
meas = xdsl_to_qml_measurement(op, wires=None if wires == [] else wires)

# Add node to current cluster
node_uid = f"node{self._node_uid_counter}"
self.dag_builder.add_node(
uid=node_uid,
label=get_label(meas),
cluster_uid=self._cluster_uid_stack[-1],
fillcolor="lightpink",
color="lightpink3",
)
self._node_uid_counter += 1

# =============
# CONTROL FLOW
# =============

@_visit_operation.register
def _for_op(self, operation: scf.ForOp) -> None:
"""Handle an xDSL ForOp operation."""

uid = f"cluster{self._cluster_uid_counter}"
self.dag_builder.add_cluster(
uid,
node_label="for loop",
label="",
cluster_uid=self._cluster_uid_stack[-1],
)
self._cluster_uid_stack.append(uid)
self._cluster_uid_counter += 1

self._visit_region(operation.regions[0])

self._cluster_uid_stack.pop()

@_visit_operation.register
def _while_op(self, operation: scf.WhileOp) -> None:
"""Handle an xDSL WhileOp operation."""
uid = f"cluster{self._cluster_uid_counter}"
self.dag_builder.add_cluster(
uid,
node_label="while loop",
label="",
cluster_uid=self._cluster_uid_stack[-1],
)
self._cluster_uid_stack.append(uid)
self._cluster_uid_counter += 1

for region in operation.regions:
self._visit_region(region)

self._cluster_uid_stack.pop()

@_visit_operation.register
def _if_op(self, operation: scf.IfOp):
"""Handles the scf.IfOp operation."""
uid = f"cluster{self._cluster_uid_counter}"
self.dag_builder.add_cluster(
uid,
node_label="",
label="conditional",
labeljust="l",
cluster_uid=self._cluster_uid_stack[-1],
)
self._cluster_uid_stack.append(uid)
self._cluster_uid_counter += 1

# Loop through each branch and visualize as a cluster
flattened_if_op: list[Region] = _flatten_if_op(operation)
num_regions = len(flattened_if_op)
for i, region in enumerate(flattened_if_op):
node_label = "elif"
if i == 0:
node_label = "if"
elif i == num_regions - 1:
node_label = "else"

uid = f"cluster{self._cluster_uid_counter}"
self.dag_builder.add_cluster(
uid,
node_label=node_label,
label="",
style="dashed",
penwidth=1,
cluster_uid=self._cluster_uid_stack[-1],
)
self._cluster_uid_stack.append(uid)
self._cluster_uid_counter += 1

# Go recursively into the branch to process internals
self._visit_region(region)

# Pop branch cluster after processing to ensure
# logical branches are treated as 'parallel'
self._cluster_uid_stack.pop()

# Pop IfOp cluster before leaving this handler
self._cluster_uid_stack.pop()

# ============
# DEVICE NODE
# ============
Expand Down Expand Up @@ -138,3 +343,61 @@ def _func_return(self, operation: func.ReturnOp) -> None:
# If we hit a func.return operation we know we are leaving
# the FuncOp's scope and so we can pop the ID off the stack.
self._cluster_uid_stack.pop()


def _flatten_if_op(op: scf.IfOp) -> list[Region]:
"""Recursively flattens a nested IfOp (if/elif/else chains)."""

then_region, else_region = op.regions

flattened_op: list[Region] = [then_region]

# Check to see if there are any nested quantum operations in the else block
else_block: Block = else_region.block
has_quantum_ops = False
nested_if_op = None
for op in else_block.ops:
if isinstance(op, scf.IfOp):
nested_if_op = op
# No need to walk this op as this will be
# recursively handled down below
continue
for internal_op in op.walk():
if type(internal_op) in quantum.Quantum.operations:
has_quantum_ops = True
# No need to check anything else
break

if nested_if_op and not has_quantum_ops:
# Recursively flatten any IfOps found in said block
nested_flattened_op: list[Region] = _flatten_if_op(nested_if_op)
flattened_op.extend(nested_flattened_op)
return flattened_op

# No more nested IfOps, therefore append final region
# with no SSAValue
flattened_op.append(else_region)
return flattened_op


@singledispatch
def get_label(op: Operator | MeasurementProcess) -> str:
"""Gets the appropriate label for a PennyLane object."""
return str(op)


@get_label.register
def _operator(op: Operator) -> str:
"""Returns the appropriate label for an xDSL operation."""
wires = list(op.wires.labels)
if wires == []:
wires_str = "all"
else:
wires_str = f"[{', '.join(map(str, wires))}]"
return f"<name> {op.name}|<wire> {wires_str}"


@get_label.register
def _mp(mp: MeasurementProcess) -> str:
"""Returns the appropriate label for an xDSL operation."""
return str(mp)
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,9 @@ def add_cluster(
node = Node(
node_uid,
label=node_label,
shape="rectangle",
style="dashed",
margin=0,
shape="plaintext",
fontname="Helvetica",
penwidth=2,
)
rank_subgraph.add_node(node)
cluster.add_subgraph(rank_subgraph)
Expand Down
Loading
Loading