1212from qiskit .circuit import Instruction as QiskitInstruction
1313from qiskit .circuit .library import get_standard_gate_name_mapping
1414from qiskit .circuit .parametervector import ParameterVectorElement
15- from qiskit .transpiler import Target
15+ from qiskit .transpiler import PassManager , Target
1616from qiskit_ionq import add_equivalences , ionq_gates
1717from sympy import Add , Mul , Pow , Symbol
1818
@@ -499,6 +499,8 @@ def to_braket(
499499 target : Target | None = None ,
500500 qubit_labels : Sequence [int ] | None = None ,
501501 optimization_level : int = 0 ,
502+ callback : Callable | None = None ,
503+ pass_manager : PassManager | None = None ,
502504) -> Circuit :
503505 """Return a Braket quantum circuit from a Qiskit quantum circuit.
504506
@@ -522,6 +524,10 @@ def to_braket(
522524 assumed to be contiguous.
523525 optimization_level (int): The optimization level to pass to `qiskit.transpile`.
524526 Default: 0 (no optimization).
527+ callback (Callable | None): A callback function that will be called after each transpiler
528+ pass execution. Default: `None`.
529+ pass_manager (PassManager): `PassManager` to transpile the circuit; will raise an error if
530+ used in conjunction with a target, basis gates, or connectivity. Default: `None`.
525531
526532 Returns:
527533 Circuit: Braket circuit
@@ -530,30 +536,41 @@ def to_braket(
530536 circuit = to_qiskit (circuit )
531537 if not isinstance (circuit , QuantumCircuit ):
532538 raise TypeError (f"Expected a QuantumCircuit, got { type (circuit )} instead." )
533- if (basis_gates or connectivity ) and target :
534- raise ValueError ("Basis gates and connectivity cannot be specified alongside target." )
535-
536- # If basis_gates is not None, then target remains empty
537- target = target if basis_gates or target else _create_default_target (circuit )
538- needs_transpilation = (
539- target
540- or connectivity
541- or (basis_gates and not {gate .name for gate , _ , _ in circuit .data }.issubset (basis_gates ))
542- )
543- if not verbatim and needs_transpilation :
544- circuit = transpile (
545- circuit ,
546- basis_gates = basis_gates ,
547- coupling_map = connectivity ,
548- optimization_level = optimization_level ,
549- target = target ,
539+ loose_constraints = basis_gates or connectivity
540+ if pass_manager and (target or loose_constraints ):
541+ raise ValueError (
542+ "Cannot specify target, basis gates, or connectivity alongside pass manager"
550543 )
544+ if loose_constraints and target :
545+ raise ValueError ("Cannot specify basis gates or connectivity alongside target." )
546+
547+ if pass_manager :
548+ circuit = pass_manager .run (circuit , callback = callback )
549+ elif not verbatim :
550+ # If basis_gates is not None, then target remains empty
551+ target = target if basis_gates or target else _default_target (circuit )
552+ if (
553+ target
554+ or connectivity
555+ or (
556+ basis_gates and not {gate .name for gate , _ , _ in circuit .data }.issubset (basis_gates )
557+ )
558+ ):
559+ circuit = transpile (
560+ circuit ,
561+ basis_gates = basis_gates ,
562+ coupling_map = connectivity ,
563+ optimization_level = optimization_level ,
564+ target = target ,
565+ callback = callback ,
566+ )
567+
551568 # Verify that ParameterVector would not collide with scalar variables after renaming.
552569 _validate_name_conflicts (circuit .parameters )
553570 # Handle qiskit to braket conversion
554571 measured_qubits : dict [int , int ] = {}
555572 braket_circuit = Circuit ()
556- qubit_labels = qubit_labels or sorted (circuit . find_bit ( q ). index for q in circuit . qubits )
573+ qubit_labels = qubit_labels or _default_qubit_labels (circuit )
557574 for circuit_instruction in circuit .data :
558575 operation = circuit_instruction .operation
559576 qubits = circuit_instruction .qubits
@@ -630,7 +647,7 @@ def to_braket(
630647
631648 # QPU targets will have qubits/pairs specified for each instruction;
632649 # Targets whose values consist solely of {None: None} are either simulator or default targets
633- if verbatim or (target and any (v != {None : None } for v in target .values ())):
650+ if verbatim or (target and any (v != {None : None } for v in target .values ())) or pass_manager :
634651 braket_circuit = Circuit (braket_circuit .result_types ).add_verbatim_box (
635652 Circuit (braket_circuit .instructions )
636653 )
@@ -641,15 +658,20 @@ def to_braket(
641658 return braket_circuit
642659
643660
644- def _create_default_target (circuit : QuantumCircuit ) -> Target :
661+ def _default_target (circuit : QuantumCircuit ) -> Target :
645662 target = Target (num_qubits = circuit .num_qubits )
646663 for braket_name , instruction in _BRAKET_GATE_NAME_TO_QISKIT_GATE .items ():
647- if ( name := braket_name .lower ()) in _BRAKET_TO_QISKIT_NAMES :
648- target .add_instruction (instruction , name = _BRAKET_TO_QISKIT_NAMES [ name ] )
664+ if name := _BRAKET_TO_QISKIT_NAMES . get ( braket_name .lower ()):
665+ target .add_instruction (instruction , name = name )
649666 target .add_instruction (Measure ())
650667 return target
651668
652669
670+ def _default_qubit_labels (circuit : QuantumCircuit ) -> tuple [int , ...]:
671+ bits = sorted (circuit .find_bit (q ).index for q in circuit .qubits )
672+ return tuple (range (max (bits ) + 1 )) if bits else tuple ()
673+
674+
653675def _create_free_parameters (operation ):
654676 params = operation .params if hasattr (operation , "params" ) else []
655677 for i , param in enumerate (params ):
0 commit comments