Skip to content

Commit 9ba022b

Browse files
paul0403kipawaa
authored andcommitted
rules for multirz and paulirot; also change special lowering to check for the actual class instead of just name
1 parent 4aa9801 commit 9ba022b

3 files changed

Lines changed: 164 additions & 150 deletions

File tree

frontend/catalyst/from_plxpr/qref_operator2_primitives.py

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"""
1717

1818
# pylint: disable=unused-argument
19+
import pennylane as qp
1920
from jax._src.lib.mlir import ir
2021
from jax.core import ShapedArray
2122
from jax.extend.core import Primitive
@@ -76,9 +77,9 @@
7677
_SPECIAL_LOWERINGS = {}
7778

7879

79-
def _register_special_lowering(op_name):
80+
def _register_special_lowering(op_cls):
8081
def decorator(f):
81-
_SPECIAL_LOWERINGS[op_name] = f
82+
_SPECIAL_LOWERINGS[op_cls] = f
8283
return f
8384

8485
return decorator
@@ -224,7 +225,7 @@ def _abstractify_jax_array(val):
224225
def collect_decomp_rules(
225226
module,
226227
op_cls,
227-
op_type,
228+
is_custom_op=False,
228229
params=None,
229230
param_map=None,
230231
wire_lens=None,
@@ -239,7 +240,7 @@ def collect_decomp_rules(
239240
Generate all the decomposition rules registered on the current gate, recursively generating all
240241
the rules that are registered on the resource gates of these rules as well.
241242
"""
242-
if op_type == "CustomOp":
243+
if is_custom_op:
243244
dynamic_shape = {dynamic_argname: ["f64"] for dynamic_argname in op_cls.dynamic_argnames}
244245
op_id = (
245246
op_cls.__name__
@@ -257,9 +258,53 @@ def collect_decomp_rules(
257258
static_data={},
258259
)
259260

260-
inject_new_rules_into_module(module, decomp_rules)
261+
elif op_cls is qp.MultiRZ:
262+
dynamic_shape = {qp.MultiRZ.dynamic_argnames[0]: ["f64"]}
263+
wire_argname = qp.MultiRZ.wire_argnames[0]
264+
op_id = (
265+
"MultiRZ"
266+
+ format_dynamic_params_for_id(dynamic_shape)
267+
+ "{"
268+
+ f"{wire_argname}:{wire_lens[0]}"
269+
+ "}{}"
270+
)
271+
272+
decomp_rules = fetch_all_reachable_decomposition_rules_from_op(
273+
op_name="MultiRZ",
274+
op_id=op_id,
275+
dynamic_shape=dynamic_shape,
276+
wire_lens={f"{wire_argname}": wire_lens[0]},
277+
static_data={},
278+
)
261279

262-
elif op_type == "OperatorOp":
280+
elif op_cls is qp.PauliRot:
281+
dynamic_shape = {qp.PauliRot.dynamic_argnames[0]: ["f64"]}
282+
wire_argname = qp.PauliRot.wire_argnames[0]
283+
pauliword_argname = qp.PauliRot.compilable_argnames[0]
284+
op_id = (
285+
"PauliRot"
286+
+ format_dynamic_params_for_id(dynamic_shape)
287+
+ "{"
288+
+ f"{wire_argname}:{wire_lens[0]}"
289+
+ "}"
290+
+ "{"
291+
+ f"{pauliword_argname}:{repack_static_data[pauliword_argname]}"
292+
+ "}"
293+
)
294+
295+
decomp_rules = fetch_all_reachable_decomposition_rules_from_op(
296+
op_name="PauliRot",
297+
op_id=op_id,
298+
dynamic_shape=dynamic_shape,
299+
wire_lens={f"{wire_argname}": wire_lens[0]},
300+
static_data=repack_static_data,
301+
)
302+
303+
elif op_cls in (qp.GlobalPhase, qp.PCPhase, qp.QubitUnitary):
304+
raise NotImplementedError(f"{op_cls} has not been migrated to Operator2 yet")
305+
306+
else:
307+
# Operator Op
263308
dynamic_shape = {}
264309

265310
indices_to_remove = set()
@@ -329,7 +374,7 @@ def collect_decomp_rules(
329374
extra_data=extra_data,
330375
)
331376

332-
inject_new_rules_into_module(module, decomp_rules)
377+
inject_new_rules_into_module(module, decomp_rules)
333378

334379

335380
def _qref_operator_p_lowering(jax_ctx: mlir.LoweringRuleContext, *args, op_cls, **kwargs):
@@ -345,6 +390,8 @@ def _qref_operator_p_lowering(jax_ctx: mlir.LoweringRuleContext, *args, op_cls,
345390
wire_lens = kwargs.pop("wire_lens")
346391
skip_decomp_rules = kwargs.pop("skip_decomp_rules")
347392

393+
repack_static_data = {k: unflatten(*v) for k, v in kwargs.items()}
394+
348395
if n_ctrls:
349396
ctrl_qubits = args[-2 * n_ctrls : -n_ctrls]
350397
ctrl_values = [
@@ -356,11 +403,24 @@ def _qref_operator_p_lowering(jax_ctx: mlir.LoweringRuleContext, *args, op_cls,
356403
ctrl_qubits = ctrl_values = ()
357404

358405
# Custom lowerings (qref.multirz, qref.pcphase, etc.)
359-
if op_cls.__name__ in _SPECIAL_LOWERINGS:
406+
if op_cls in _SPECIAL_LOWERINGS:
360407
expected_len = len(op_cls.dynamic_argnames) + sum(wire_lens)
361408
assert len(args) == expected_len, f"Incorrect number of operands for {op_cls.__name__}."
362-
return _SPECIAL_LOWERINGS[op_cls.__name__](
363-
*args, ctrl_qubits=ctrl_qubits, ctrl_values=ctrl_values, adjoint=adjoint, **kwargs
409+
410+
if not skip_decomp_rules:
411+
collect_decomp_rules(
412+
module=jax_ctx.module_context.module,
413+
op_cls=op_cls,
414+
wire_lens=wire_lens,
415+
repack_static_data=repack_static_data,
416+
)
417+
418+
return _SPECIAL_LOWERINGS[op_cls](
419+
*args,
420+
ctrl_qubits=ctrl_qubits,
421+
ctrl_values=ctrl_values,
422+
adjoint=adjoint,
423+
**kwargs,
364424
)
365425

366426
name_attr = get_mlir_attribute_from_pyval(op_cls.__name__)
@@ -391,7 +451,7 @@ def _qref_operator_p_lowering(jax_ctx: mlir.LoweringRuleContext, *args, op_cls,
391451
collect_decomp_rules(
392452
module=jax_ctx.module_context.module,
393453
op_cls=op_cls,
394-
op_type="CustomOp",
454+
is_custom_op=True,
395455
wire_lens=wire_lens,
396456
)
397457

@@ -407,7 +467,6 @@ def _qref_operator_p_lowering(jax_ctx: mlir.LoweringRuleContext, *args, op_cls,
407467
qubits, qubit_map = _process_qubits(
408468
*args, op_cls=op_cls, wire_lens=wire_lens, hybrid_lens=hybrid_lens
409469
)
410-
repack_static_data = {k: unflatten(*v) for k, v in kwargs.items()}
411470

412471
if op_cls.hybrid_argnames or op_cls.static_argnames:
413472
uid = generate_uid(
@@ -446,7 +505,7 @@ def _qref_operator_p_lowering(jax_ctx: mlir.LoweringRuleContext, *args, op_cls,
446505
collect_decomp_rules(
447506
module=jax_ctx.module_context.module,
448507
op_cls=op_cls,
449-
op_type="OperatorOp",
508+
is_custom_op=False,
450509
params=params,
451510
param_map=param_map,
452511
wire_lens=wire_lens,
@@ -461,7 +520,7 @@ def _qref_operator_p_lowering(jax_ctx: mlir.LoweringRuleContext, *args, op_cls,
461520
return []
462521

463522

464-
@_register_special_lowering("MultiRZ")
523+
@_register_special_lowering(qp.MultiRZ)
465524
def _multirz_lowering(theta, *qubits, ctrl_qubits, ctrl_values, adjoint):
466525
MultiRZOp(
467526
theta=extract_scalar(safe_cast_to_f64(theta, "MultiRZ"), "MultiRZ"),
@@ -473,7 +532,7 @@ def _multirz_lowering(theta, *qubits, ctrl_qubits, ctrl_values, adjoint):
473532
return []
474533

475534

476-
@_register_special_lowering("PCPhase")
535+
@_register_special_lowering(qp.PCPhase)
477536
def _pcphase_lowering(theta, *qubits, ctrl_qubits, ctrl_values, adjoint, dim):
478537
dim = unflatten(*dim)
479538
PCPhaseOp(
@@ -487,7 +546,7 @@ def _pcphase_lowering(theta, *qubits, ctrl_qubits, ctrl_values, adjoint, dim):
487546
return ()
488547

489548

490-
@_register_special_lowering("GlobalPhase")
549+
@_register_special_lowering(qp.GlobalPhase)
491550
def _special_gphase_lowering(angle, *_, ctrl_qubits, ctrl_values, adjoint):
492551
GlobalPhaseOp(
493552
angle=extract_scalar(safe_cast_to_f64(angle, "GlobalPhase"), "GlobalPhase"),
@@ -498,7 +557,7 @@ def _special_gphase_lowering(angle, *_, ctrl_qubits, ctrl_values, adjoint):
498557
return ()
499558

500559

501-
@_register_special_lowering("QubitUnitary")
560+
@_register_special_lowering(qp.QubitUnitary)
502561
def _special_unitary_lowering(matrix, *qubits, ctrl_qubits, ctrl_values, adjoint):
503562
matrix_type = matrix.type
504563
is_tensor = ir.RankedTensorType.isinstance(matrix_type)
@@ -534,7 +593,7 @@ def _special_unitary_lowering(matrix, *qubits, ctrl_qubits, ctrl_values, adjoint
534593
return ()
535594

536595

537-
@_register_special_lowering("PauliRot")
596+
@_register_special_lowering(qp.PauliRot)
538597
def _special_paulirot_lowering(angle, *qubits, ctrl_qubits, ctrl_values, adjoint, pauli_word):
539598
pauli_word = unflatten(*pauli_word)
540599
pauli_word = ir.ArrayAttr.get([ir.StringAttr.get(p) for p in pauli_word])

frontend/test/lit/operator2_dummy_gates.py

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -90,49 +90,6 @@ def __init__(self, a, b, c, wires):
9090
super().__init__(a, b, c, wires)
9191

9292

93-
class MultiRZ(qp.core.Operator2):
94-
95-
dynamic_argnames = ("phi",)
96-
97-
def __init__(self, phi, wires):
98-
super().__init__(phi, wires)
99-
100-
101-
class PauliRot(qp.core.Operator2):
102-
103-
dynamic_argnames = ("phi",)
104-
compilable_argnames = ("pauli_word",)
105-
106-
def __init__(self, phi, pauli_word, wires):
107-
super().__init__(phi, pauli_word, wires)
108-
109-
110-
class GlobalPhase(qp.core.Operator2):
111-
112-
dynamic_argnames = ("phi",)
113-
wire_argnames = ()
114-
115-
def __init__(self, phi):
116-
super().__init__(phi=phi)
117-
118-
119-
class QubitUnitary(qp.core.Operator2):
120-
121-
dynamic_argnames = ("matrix",)
122-
123-
def __init__(self, matrix, wires):
124-
super().__init__(matrix, wires)
125-
126-
127-
class PCPhase(qp.core.Operator2):
128-
129-
dynamic_argnames = ("phi",)
130-
compilable_argnames = ("dim",)
131-
132-
def __init__(self, phi, dim, wires):
133-
super().__init__(phi, dim, wires)
134-
135-
13693
class StaticData(qp.core.Operator2):
13794

13895
static_argnames = ("label",)

0 commit comments

Comments
 (0)