1616"""
1717
1818# pylint: disable=unused-argument
19+ import pennylane as qp
1920from jax ._src .lib .mlir import ir
2021from jax .core import ShapedArray
2122from jax .extend .core import Primitive
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):
224225def 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
335380def _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 )
465524def _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 )
477536def _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 )
491550def _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 )
502561def _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 )
538597def _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 ])
0 commit comments