qiskit 1.3.0b1__cp39-abi3-win32.whl → 1.3.0rc2__cp39-abi3-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qiskit/VERSION.txt +1 -1
- qiskit/__init__.py +20 -1
- qiskit/_accelerate.pyd +0 -0
- qiskit/assembler/assemble_schedules.py +2 -0
- qiskit/circuit/__init__.py +44 -1
- qiskit/circuit/_standard_gates_commutations.py +585 -0
- qiskit/circuit/barrier.py +2 -0
- qiskit/circuit/controlflow/builder.py +3 -3
- qiskit/circuit/controlflow/if_else.py +13 -5
- qiskit/circuit/controlflow/while_loop.py +10 -2
- qiskit/circuit/delay.py +20 -3
- qiskit/circuit/equivalence.py +13 -214
- qiskit/circuit/gate.py +3 -1
- qiskit/circuit/instruction.py +32 -11
- qiskit/circuit/instructionset.py +2 -0
- qiskit/circuit/library/__init__.py +110 -14
- qiskit/circuit/library/arithmetic/__init__.py +9 -2
- qiskit/circuit/library/arithmetic/adders/__init__.py +1 -0
- qiskit/circuit/library/arithmetic/adders/adder.py +154 -2
- qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +20 -56
- qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +14 -1
- qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +21 -91
- qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
- qiskit/circuit/library/arithmetic/multipliers/__init__.py +1 -0
- qiskit/circuit/library/arithmetic/multipliers/hrs_cumulative_multiplier.py +8 -1
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +94 -3
- qiskit/circuit/library/arithmetic/multipliers/rg_qft_multiplier.py +8 -1
- qiskit/circuit/library/arithmetic/weighted_adder.py +1 -1
- qiskit/circuit/library/basis_change/qft.py +20 -38
- qiskit/circuit/library/blueprintcircuit.py +64 -0
- qiskit/circuit/library/boolean_logic/__init__.py +4 -4
- qiskit/circuit/library/boolean_logic/inner_product.py +81 -4
- qiskit/circuit/library/boolean_logic/quantum_and.py +107 -4
- qiskit/circuit/library/boolean_logic/quantum_or.py +107 -3
- qiskit/circuit/library/boolean_logic/quantum_xor.py +97 -3
- qiskit/circuit/library/data_preparation/__init__.py +6 -3
- qiskit/circuit/library/data_preparation/{z_feature_map.py → _z_feature_map.py} +45 -34
- qiskit/circuit/library/data_preparation/_zz_feature_map.py +150 -0
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +342 -29
- qiskit/circuit/library/fourier_checking.py +72 -11
- qiskit/circuit/library/generalized_gates/__init__.py +1 -1
- qiskit/circuit/library/generalized_gates/diagonal.py +45 -51
- qiskit/circuit/library/generalized_gates/gms.py +67 -14
- qiskit/circuit/library/generalized_gates/gr.py +4 -4
- qiskit/circuit/library/generalized_gates/isometry.py +2 -2
- qiskit/circuit/library/generalized_gates/linear_function.py +12 -6
- qiskit/circuit/library/generalized_gates/mcmt.py +167 -107
- qiskit/circuit/library/generalized_gates/permutation.py +8 -6
- qiskit/circuit/library/generalized_gates/rv.py +8 -9
- qiskit/circuit/library/graph_state.py +93 -10
- qiskit/circuit/library/grover_operator.py +270 -2
- qiskit/circuit/library/hidden_linear_function.py +83 -20
- qiskit/circuit/library/iqp.py +99 -20
- qiskit/circuit/library/n_local/__init__.py +19 -7
- qiskit/circuit/library/n_local/efficient_su2.py +118 -5
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +259 -0
- qiskit/circuit/library/n_local/excitation_preserving.py +130 -6
- qiskit/circuit/library/n_local/n_local.py +406 -5
- qiskit/circuit/library/n_local/pauli_two_design.py +106 -4
- qiskit/circuit/library/n_local/qaoa_ansatz.py +80 -1
- qiskit/circuit/library/n_local/real_amplitudes.py +127 -7
- qiskit/circuit/library/n_local/two_local.py +14 -7
- qiskit/circuit/library/overlap.py +91 -26
- qiskit/circuit/library/pauli_evolution.py +17 -15
- qiskit/circuit/library/phase_estimation.py +80 -4
- qiskit/circuit/library/quantum_volume.py +72 -20
- qiskit/circuit/library/standard_gates/__init__.py +20 -1
- qiskit/circuit/library/standard_gates/dcx.py +2 -1
- qiskit/circuit/library/standard_gates/ecr.py +2 -2
- qiskit/circuit/library/standard_gates/h.py +4 -3
- qiskit/circuit/library/standard_gates/i.py +2 -1
- qiskit/circuit/library/standard_gates/iswap.py +2 -2
- qiskit/circuit/library/standard_gates/p.py +20 -12
- qiskit/circuit/library/standard_gates/r.py +1 -1
- qiskit/circuit/library/standard_gates/rx.py +4 -3
- qiskit/circuit/library/standard_gates/rxx.py +2 -2
- qiskit/circuit/library/standard_gates/ry.py +4 -3
- qiskit/circuit/library/standard_gates/ryy.py +2 -2
- qiskit/circuit/library/standard_gates/rz.py +13 -12
- qiskit/circuit/library/standard_gates/rzx.py +6 -6
- qiskit/circuit/library/standard_gates/rzz.py +1 -1
- qiskit/circuit/library/standard_gates/s.py +4 -4
- qiskit/circuit/library/standard_gates/swap.py +3 -3
- qiskit/circuit/library/standard_gates/sx.py +4 -3
- qiskit/circuit/library/standard_gates/t.py +2 -2
- qiskit/circuit/library/standard_gates/u.py +11 -3
- qiskit/circuit/library/standard_gates/u1.py +65 -15
- qiskit/circuit/library/standard_gates/u2.py +4 -1
- qiskit/circuit/library/standard_gates/u3.py +31 -3
- qiskit/circuit/library/standard_gates/x.py +7 -5
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +2 -2
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +2 -2
- qiskit/circuit/library/standard_gates/y.py +4 -3
- qiskit/circuit/library/standard_gates/z.py +3 -3
- qiskit/circuit/library/templates/clifford/clifford_2_1.py +9 -8
- qiskit/circuit/library/templates/clifford/clifford_2_2.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_2_3.py +9 -7
- qiskit/circuit/library/templates/clifford/clifford_2_4.py +9 -8
- qiskit/circuit/library/templates/clifford/clifford_3_1.py +9 -8
- qiskit/circuit/library/templates/clifford/clifford_4_1.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_4_2.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_4_3.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_4_4.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_5_1.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_6_1.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_6_2.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_6_3.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_6_4.py +9 -8
- qiskit/circuit/library/templates/clifford/clifford_6_5.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_8_1.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_8_2.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_8_3.py +10 -9
- qiskit/circuit/library/templates/nct/template_nct_2a_1.py +9 -7
- qiskit/circuit/library/templates/nct/template_nct_2a_2.py +10 -8
- qiskit/circuit/library/templates/nct/template_nct_2a_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_4a_1.py +16 -14
- qiskit/circuit/library/templates/nct/template_nct_4a_2.py +14 -12
- qiskit/circuit/library/templates/nct/template_nct_4a_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_4b_1.py +14 -12
- qiskit/circuit/library/templates/nct/template_nct_4b_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_5a_1.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_5a_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_5a_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_5a_4.py +11 -9
- qiskit/circuit/library/templates/nct/template_nct_6a_1.py +11 -9
- qiskit/circuit/library/templates/nct/template_nct_6a_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6a_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6a_4.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6b_1.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6b_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6c_1.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_7a_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_7b_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_7c_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_7d_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_7e_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_9a_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_9c_1.py +11 -9
- qiskit/circuit/library/templates/nct/template_nct_9c_10.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_11.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_12.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_4.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_5.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_6.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_7.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_8.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_9.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_1.py +11 -9
- qiskit/circuit/library/templates/nct/template_nct_9d_10.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_4.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_5.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_6.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_7.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_8.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_9.py +12 -10
- qiskit/circuit/library/templates/rzx/rzx_cy.py +11 -10
- qiskit/circuit/library/templates/rzx/rzx_xz.py +16 -15
- qiskit/circuit/library/templates/rzx/rzx_yz.py +12 -10
- qiskit/circuit/library/templates/rzx/rzx_zz1.py +22 -20
- qiskit/circuit/library/templates/rzx/rzx_zz2.py +16 -15
- qiskit/circuit/library/templates/rzx/rzx_zz3.py +17 -15
- qiskit/circuit/parameter.py +4 -0
- qiskit/circuit/parameterexpression.py +167 -34
- qiskit/circuit/quantumcircuit.py +162 -126
- qiskit/circuit/singleton.py +2 -0
- qiskit/circuit/store.py +2 -0
- qiskit/circuit/twirling.py +145 -0
- qiskit/compiler/assembler.py +17 -4
- qiskit/compiler/scheduler.py +2 -0
- qiskit/compiler/sequencer.py +2 -0
- qiskit/compiler/transpiler.py +81 -26
- qiskit/converters/circuit_to_dag.py +2 -2
- qiskit/converters/circuit_to_dagdependency.py +1 -1
- qiskit/converters/circuit_to_dagdependency_v2.py +1 -1
- qiskit/converters/circuit_to_instruction.py +1 -1
- qiskit/converters/dag_to_circuit.py +7 -5
- qiskit/converters/dag_to_dagdependency.py +1 -1
- qiskit/converters/dag_to_dagdependency_v2.py +1 -1
- qiskit/converters/dagdependency_to_circuit.py +5 -1
- qiskit/converters/dagdependency_to_dag.py +6 -1
- qiskit/dagcircuit/collect_blocks.py +3 -3
- qiskit/dagcircuit/dagdependency.py +18 -5
- qiskit/dagcircuit/dagdependency_v2.py +1 -1
- qiskit/dagcircuit/dagnode.py +2 -2
- qiskit/passmanager/__init__.py +2 -2
- qiskit/primitives/backend_estimator.py +5 -2
- qiskit/primitives/backend_sampler_v2.py +61 -18
- qiskit/primitives/base/base_estimator.py +2 -2
- qiskit/primitives/containers/data_bin.py +9 -1
- qiskit/primitives/statevector_sampler.py +1 -1
- qiskit/primitives/utils.py +1 -1
- qiskit/providers/__init__.py +3 -3
- qiskit/providers/backend.py +12 -1
- qiskit/providers/backend_compat.py +23 -3
- qiskit/providers/basic_provider/basic_simulator.py +12 -2
- qiskit/providers/fake_provider/fake_pulse_backend.py +6 -1
- qiskit/providers/fake_provider/generic_backend_v2.py +46 -30
- qiskit/providers/models/pulsedefaults.py +2 -0
- qiskit/pulse/builder.py +59 -18
- qiskit/pulse/calibration_entries.py +4 -1
- qiskit/pulse/channels.py +2 -0
- qiskit/pulse/exceptions.py +2 -0
- qiskit/pulse/instruction_schedule_map.py +21 -6
- qiskit/pulse/instructions/acquire.py +2 -0
- qiskit/pulse/instructions/delay.py +2 -0
- qiskit/pulse/instructions/directives.py +8 -0
- qiskit/pulse/instructions/frequency.py +3 -0
- qiskit/pulse/instructions/instruction.py +2 -0
- qiskit/pulse/instructions/phase.py +3 -0
- qiskit/pulse/instructions/play.py +2 -0
- qiskit/pulse/instructions/reference.py +2 -0
- qiskit/pulse/instructions/snapshot.py +2 -0
- qiskit/pulse/library/pulse.py +2 -0
- qiskit/pulse/library/symbolic_pulses.py +28 -0
- qiskit/pulse/library/waveform.py +2 -0
- qiskit/pulse/macros.py +1 -1
- qiskit/pulse/schedule.py +12 -13
- qiskit/pulse/transforms/alignments.py +5 -3
- qiskit/pulse/transforms/dag.py +7 -0
- qiskit/qasm2/export.py +5 -3
- qiskit/qasm2/parse.py +46 -2
- qiskit/qasm3/__init__.py +1 -0
- qiskit/qasm3/ast.py +123 -15
- qiskit/qasm3/exporter.py +103 -77
- qiskit/qobj/converters/pulse_instruction.py +6 -4
- qiskit/qpy/__init__.py +181 -0
- qiskit/qpy/binary_io/circuits.py +20 -5
- qiskit/qpy/binary_io/schedules.py +3 -4
- qiskit/qpy/binary_io/value.py +310 -13
- qiskit/qpy/common.py +46 -2
- qiskit/qpy/formats.py +7 -0
- qiskit/qpy/interface.py +40 -4
- qiskit/quantum_info/__init__.py +4 -0
- qiskit/quantum_info/operators/channel/transformations.py +28 -21
- qiskit/quantum_info/operators/dihedral/dihedral.py +1 -1
- qiskit/quantum_info/operators/operator.py +54 -8
- qiskit/quantum_info/operators/symplectic/base_pauli.py +11 -19
- qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
- qiskit/quantum_info/operators/symplectic/clifford_circuits.py +1 -1
- qiskit/quantum_info/operators/symplectic/pauli.py +2 -0
- qiskit/quantum_info/operators/symplectic/pauli_list.py +4 -4
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +23 -2
- qiskit/quantum_info/states/densitymatrix.py +5 -5
- qiskit/quantum_info/states/stabilizerstate.py +1 -1
- qiskit/quantum_info/states/statevector.py +6 -6
- qiskit/result/mitigation/base_readout_mitigator.py +1 -1
- qiskit/result/mitigation/correlated_readout_mitigator.py +9 -1
- qiskit/result/mitigation/local_readout_mitigator.py +9 -1
- qiskit/result/mitigation/utils.py +57 -0
- qiskit/scheduler/config.py +2 -0
- qiskit/scheduler/methods/basic.py +3 -0
- qiskit/scheduler/schedule_circuit.py +2 -0
- qiskit/scheduler/sequence.py +2 -0
- qiskit/synthesis/__init__.py +25 -0
- qiskit/synthesis/arithmetic/__init__.py +16 -0
- qiskit/synthesis/arithmetic/adders/__init__.py +17 -0
- qiskit/synthesis/arithmetic/adders/cdkm_ripple_carry_adder.py +154 -0
- qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +103 -0
- qiskit/synthesis/arithmetic/adders/vbe_ripple_carry_adder.py +161 -0
- qiskit/synthesis/arithmetic/multipliers/__init__.py +16 -0
- qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +102 -0
- qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +99 -0
- qiskit/synthesis/clifford/clifford_decompose_bm.py +1 -2
- qiskit/synthesis/clifford/clifford_decompose_greedy.py +3 -2
- qiskit/synthesis/clifford/clifford_decompose_layers.py +2 -1
- qiskit/synthesis/evolution/__init__.py +1 -0
- qiskit/synthesis/evolution/lie_trotter.py +16 -42
- qiskit/synthesis/evolution/pauli_network.py +80 -0
- qiskit/synthesis/evolution/product_formula.py +165 -238
- qiskit/synthesis/evolution/qdrift.py +36 -29
- qiskit/synthesis/evolution/suzuki_trotter.py +87 -27
- qiskit/synthesis/multi_controlled/__init__.py +1 -0
- qiskit/synthesis/multi_controlled/mcmt_vchain.py +52 -0
- qiskit/synthesis/qft/qft_decompose_full.py +19 -1
- qiskit/synthesis/qft/qft_decompose_lnn.py +2 -1
- qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -1
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +4 -63
- qiskit/synthesis/unitary/qsd.py +5 -5
- qiskit/transpiler/__init__.py +21 -14
- qiskit/transpiler/basepasses.py +1 -1
- qiskit/transpiler/passes/__init__.py +2 -0
- qiskit/transpiler/passes/basis/basis_translator.py +9 -565
- qiskit/transpiler/passes/basis/decompose.py +45 -12
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
- qiskit/transpiler/passes/calibration/pulse_gate.py +4 -2
- qiskit/transpiler/passes/calibration/rx_builder.py +11 -7
- qiskit/transpiler/passes/calibration/rzx_builder.py +46 -30
- qiskit/transpiler/passes/layout/disjoint_utils.py +15 -13
- qiskit/transpiler/passes/layout/sabre_layout.py +7 -2
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +5 -0
- qiskit/transpiler/passes/optimization/__init__.py +1 -0
- qiskit/transpiler/passes/optimization/collect_cliffords.py +19 -3
- qiskit/transpiler/passes/optimization/collect_linear_functions.py +1 -1
- qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
- qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.py +1 -1
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +48 -131
- qiskit/transpiler/passes/optimization/echo_rzx_weyl_decomposition.py +4 -2
- qiskit/transpiler/passes/optimization/elide_permutations.py +9 -32
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +5 -11
- qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
- qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py +1 -1
- qiskit/transpiler/passes/optimization/remove_identity_equiv.py +69 -0
- qiskit/transpiler/passes/optimization/template_matching/backward_match.py +5 -5
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +4 -4
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +2 -2
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +1 -1
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +7 -3
- qiskit/transpiler/passes/routing/star_prerouting.py +2 -2
- qiskit/transpiler/passes/scheduling/alap.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/align_measures.py +2 -2
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +2 -0
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +2 -2
- qiskit/transpiler/passes/scheduling/asap.py +1 -1
- qiskit/transpiler/passes/scheduling/base_scheduler.py +14 -12
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +9 -4
- qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +16 -5
- qiskit/transpiler/passes/scheduling/padding/pad_delay.py +4 -1
- qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +6 -2
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +9 -4
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +262 -99
- qiskit/transpiler/passes/synthesis/hls_plugins.py +637 -7
- qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +3 -3
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +55 -34
- qiskit/transpiler/passes/utils/barrier_before_final_measurements.py +2 -56
- qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +5 -0
- qiskit/transpiler/passes/utils/gate_direction.py +12 -275
- qiskit/transpiler/passes/utils/gates_basis.py +7 -30
- qiskit/transpiler/passes/utils/merge_adjacent_barriers.py +2 -1
- qiskit/transpiler/passmanager_config.py +22 -4
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +40 -14
- qiskit/transpiler/preset_passmanagers/common.py +5 -3
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +125 -42
- qiskit/transpiler/preset_passmanagers/plugin.py +1 -1
- qiskit/transpiler/target.py +74 -16
- qiskit/utils/deprecate_pulse.py +119 -0
- qiskit/visualization/circuit/_utils.py +2 -2
- qiskit/visualization/circuit/circuit_visualization.py +3 -2
- qiskit/visualization/circuit/matplotlib.py +1 -1
- qiskit/visualization/dag_visualization.py +1 -1
- qiskit/visualization/pass_manager_visualization.py +3 -14
- qiskit/visualization/pulse_v2/interface.py +3 -1
- qiskit/visualization/timeline/core.py +25 -2
- qiskit/visualization/timeline/interface.py +12 -0
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/METADATA +9 -8
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/RECORD +357 -346
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/WHEEL +1 -1
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/entry_points.txt +19 -0
- qiskit/circuit/library/data_preparation/zz_feature_map.py +0 -118
- qiskit/synthesis/two_qubit/weyl.py +0 -97
- qiskit/transpiler/passes/synthesis/qubit_tracker.py +0 -132
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/top_level.txt +0 -0
@@ -64,10 +64,14 @@ class BaseScheduler(AnalysisPass):
|
|
64
64
|
"""A helper method to get duration from node or calibration."""
|
65
65
|
indices = [dag.find_bit(qarg).index for qarg in node.qargs]
|
66
66
|
|
67
|
-
if dag.
|
67
|
+
if dag._has_calibration_for(node):
|
68
68
|
# If node has calibration, this value should be the highest priority
|
69
69
|
cal_key = tuple(indices), tuple(float(p) for p in node.op.params)
|
70
|
-
|
70
|
+
with warnings.catch_warnings():
|
71
|
+
warnings.simplefilter(action="ignore", category=DeprecationWarning)
|
72
|
+
# `schedule.duration` emits pulse deprecation warnings which we don't want
|
73
|
+
# to see here
|
74
|
+
duration = dag._calibrations_prop[node.op.name][cal_key].duration
|
71
75
|
|
72
76
|
# Note that node duration is updated (but this is analysis pass)
|
73
77
|
op = node.op.to_mutable()
|
@@ -12,6 +12,7 @@
|
|
12
12
|
|
13
13
|
"""Unify time unit in circuit for scheduling and following passes."""
|
14
14
|
from typing import Set
|
15
|
+
import warnings
|
15
16
|
|
16
17
|
from qiskit.circuit import Delay
|
17
18
|
from qiskit.dagcircuit import DAGCircuit
|
@@ -121,11 +122,15 @@ class TimeUnitConversion(TransformationPass):
|
|
121
122
|
"""
|
122
123
|
circ_durations = InstructionDurations()
|
123
124
|
|
124
|
-
if dag.
|
125
|
+
if dag._calibrations_prop:
|
125
126
|
cal_durations = []
|
126
|
-
|
127
|
-
|
128
|
-
|
127
|
+
with warnings.catch_warnings():
|
128
|
+
warnings.simplefilter(action="ignore", category=DeprecationWarning)
|
129
|
+
# `schedule.duration` emits pulse deprecation warnings which we don't want
|
130
|
+
# to see here
|
131
|
+
for gate, gate_cals in dag._calibrations_prop.items():
|
132
|
+
for (qubits, parameters), schedule in gate_cals.items():
|
133
|
+
cal_durations.append((gate, qubits, parameters, schedule.duration))
|
129
134
|
circ_durations.update(cal_durations, circ_durations.dt)
|
130
135
|
|
131
136
|
if self._durations_provided:
|
@@ -28,7 +28,7 @@ from qiskit.circuit.instruction import Instruction
|
|
28
28
|
from qiskit.converters import circuit_to_dag, dag_to_circuit
|
29
29
|
from qiskit.transpiler.basepasses import TransformationPass
|
30
30
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
31
|
-
from qiskit.circuit import ControlledGate, EquivalenceLibrary, equivalence
|
31
|
+
from qiskit.circuit import ControlledGate, EquivalenceLibrary, equivalence, Qubit
|
32
32
|
from qiskit.transpiler.passes.utils import control_flow
|
33
33
|
from qiskit.transpiler.target import Target
|
34
34
|
from qiskit.transpiler.coupling import CouplingMap
|
@@ -42,8 +42,8 @@ from qiskit.circuit.annotated_operation import (
|
|
42
42
|
PowerModifier,
|
43
43
|
)
|
44
44
|
|
45
|
+
from qiskit._accelerate.high_level_synthesis import QubitTracker, QubitContext
|
45
46
|
from .plugin import HighLevelSynthesisPluginManager
|
46
|
-
from .qubit_tracker import QubitTracker
|
47
47
|
|
48
48
|
if typing.TYPE_CHECKING:
|
49
49
|
from qiskit.dagcircuit import DAGOpNode
|
@@ -271,96 +271,161 @@ class HighLevelSynthesis(TransformationPass):
|
|
271
271
|
(for instance, when the specified synthesis method is not available).
|
272
272
|
"""
|
273
273
|
qubits = tuple(dag.find_bit(q).index for q in dag.qubits)
|
274
|
+
context = QubitContext(list(range(len(dag.qubits))))
|
275
|
+
tracker = QubitTracker(num_qubits=dag.num_qubits())
|
274
276
|
if self.qubits_initially_zero:
|
275
|
-
|
276
|
-
else:
|
277
|
-
clean, dirty = set(), set(qubits)
|
277
|
+
tracker.set_clean(context.to_globals(qubits))
|
278
278
|
|
279
|
-
|
280
|
-
return
|
279
|
+
out_dag = self._run(dag, tracker, context, use_ancillas=True, top_level=True)
|
280
|
+
return out_dag
|
281
281
|
|
282
|
-
def _run(
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
282
|
+
def _run(
|
283
|
+
self,
|
284
|
+
dag: DAGCircuit,
|
285
|
+
tracker: QubitTracker,
|
286
|
+
context: QubitContext,
|
287
|
+
use_ancillas: bool,
|
288
|
+
top_level: bool,
|
289
|
+
) -> DAGCircuit:
|
290
|
+
"""
|
291
|
+
The main recursive function that synthesizes a DAGCircuit.
|
292
|
+
|
293
|
+
Input:
|
294
|
+
dag: the DAG to be synthesized.
|
295
|
+
tracker: the global tracker, tracking the state of original qubits.
|
296
|
+
context: the correspondence between the dag's qubits and the global qubits.
|
297
|
+
use_ancillas: if True, synthesis algorithms are allowed to use ancillas.
|
298
|
+
top_level: specifies if this is the top-level of the recursion.
|
299
|
+
|
300
|
+
The function returns the synthesized DAG.
|
301
|
+
|
302
|
+
Note that by using the auxiliary qubits to synthesize operations present in the input DAG,
|
303
|
+
the synthesized DAG may be defined over more qubits than the input DAG. In this case,
|
304
|
+
the function update in-place the global qubits tracker and extends the local-to-global
|
305
|
+
context.
|
306
|
+
"""
|
307
|
+
|
308
|
+
if dag.num_qubits() != context.num_qubits():
|
309
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
291
310
|
|
292
|
-
#
|
293
|
-
#
|
294
|
-
|
295
|
-
|
296
|
-
|
311
|
+
# STEP 1: Check if HighLevelSynthesis can be skipped altogether. This is only
|
312
|
+
# done at the top-level since this does not update the global qubits tracker.
|
313
|
+
if top_level:
|
314
|
+
for node in dag.op_nodes():
|
315
|
+
qubits = tuple(dag.find_bit(q).index for q in node.qargs)
|
316
|
+
if not self._definitely_skip_node(node, qubits, dag):
|
317
|
+
break
|
318
|
+
else:
|
319
|
+
# The for-loop terminates without reaching the break statement
|
320
|
+
if dag.num_qubits() != context.num_qubits():
|
321
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
322
|
+
return dag
|
323
|
+
|
324
|
+
# STEP 2: Analyze the nodes in the DAG. For each node in the DAG that needs
|
325
|
+
# to be synthesized, we recursively synthesize it and store the result. For
|
326
|
+
# instance, the result of synthesizing a custom gate is a DAGCircuit corresponding
|
327
|
+
# to the (recursively synthesized) gate's definition. When the result is a
|
328
|
+
# DAG, we also store its context (the mapping of its qubits to global qubits).
|
329
|
+
# In addition, we keep track of the qubit states using the (global) qubits tracker.
|
330
|
+
#
|
331
|
+
# Note: This is a first version of a potentially more elaborate approach to find
|
332
|
+
# good operation/ancilla allocations. The current approach is greedy and just gives
|
333
|
+
# all available ancilla qubits to the current operation ("the-first-takes-all" approach).
|
334
|
+
# It does not distribute ancilla qubits between different operations present in the DAG.
|
297
335
|
synthesized_nodes = {}
|
298
336
|
|
299
337
|
for node in dag.topological_op_nodes():
|
300
338
|
qubits = tuple(dag.find_bit(q).index for q in node.qargs)
|
339
|
+
processed = False
|
301
340
|
synthesized = None
|
302
|
-
|
341
|
+
synthesized_context = None
|
342
|
+
|
343
|
+
# Start by handling special operations. Other cases can also be
|
344
|
+
# considered: swaps, automatically simplifying control gate (e.g. if
|
345
|
+
# a control is 0).
|
346
|
+
if node.op.name in ["id", "delay", "barrier"]:
|
347
|
+
# tracker not updated, these are no-ops
|
348
|
+
processed = True
|
349
|
+
|
350
|
+
elif node.op.name == "reset":
|
351
|
+
# reset qubits to 0
|
352
|
+
tracker.set_clean(context.to_globals(qubits))
|
353
|
+
processed = True
|
303
354
|
|
304
355
|
# check if synthesis for the operation can be skipped
|
305
|
-
|
306
|
-
|
356
|
+
elif self._definitely_skip_node(node, qubits, dag):
|
357
|
+
tracker.set_dirty(context.to_globals(qubits))
|
307
358
|
|
308
359
|
# next check control flow
|
309
360
|
elif node.is_control_flow():
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
361
|
+
inner_context = context.restrict(qubits)
|
362
|
+
synthesized = control_flow.map_blocks(
|
363
|
+
partial(
|
364
|
+
self._run,
|
365
|
+
tracker=tracker,
|
366
|
+
context=inner_context,
|
367
|
+
use_ancillas=False,
|
368
|
+
top_level=False,
|
369
|
+
),
|
370
|
+
node.op,
|
314
371
|
)
|
315
372
|
|
316
373
|
# now we are free to synthesize
|
317
374
|
else:
|
318
|
-
#
|
319
|
-
#
|
320
|
-
|
375
|
+
# This returns the synthesized operation and its context (when the result is
|
376
|
+
# a DAG, it's the correspondence between its qubits and the global qubits).
|
377
|
+
# Also note that the DAG may use auxiliary qubits. The qubits tracker and the
|
378
|
+
# current DAG's context are updated in-place.
|
379
|
+
synthesized, synthesized_context = self._synthesize_operation(
|
380
|
+
node.op, qubits, tracker, context, use_ancillas=use_ancillas
|
381
|
+
)
|
321
382
|
|
322
|
-
#
|
323
|
-
# and mark the operation qubits as used
|
383
|
+
# If the synthesis changed the operation (i.e. it is not None), store the result.
|
324
384
|
if synthesized is not None:
|
325
|
-
synthesized_nodes[node] = (synthesized,
|
326
|
-
tracker.used(qubits) # assumes that auxiliary are returned in the same state
|
385
|
+
synthesized_nodes[node._node_id] = (synthesized, synthesized_context)
|
327
386
|
|
328
|
-
#
|
329
|
-
|
330
|
-
|
331
|
-
if node.op.name in ["id", "delay", "barrier"]:
|
332
|
-
pass # tracker not updated, these are no-ops
|
333
|
-
elif node.op.name == "reset":
|
334
|
-
tracker.reset(qubits) # reset qubits to 0
|
335
|
-
else:
|
336
|
-
tracker.used(qubits) # any other op used the clean state up
|
387
|
+
# If the synthesis did not change anything, just update the qubit tracker.
|
388
|
+
elif not processed:
|
389
|
+
tracker.set_dirty(context.to_globals(qubits))
|
337
390
|
|
338
|
-
#
|
391
|
+
# We did not change anything just return the input.
|
339
392
|
if len(synthesized_nodes) == 0:
|
393
|
+
if dag.num_qubits() != context.num_qubits():
|
394
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
340
395
|
return dag
|
341
396
|
|
342
|
-
#
|
397
|
+
# STEP 3. We rebuild the DAG with new operations. Note that we could also
|
343
398
|
# check if no operation changed in size and substitute in-place, but rebuilding is
|
344
399
|
# generally as fast or faster, unless very few operations are changed.
|
345
400
|
out = dag.copy_empty_like()
|
346
|
-
|
401
|
+
num_additional_qubits = context.num_qubits() - out.num_qubits()
|
402
|
+
|
403
|
+
if num_additional_qubits > 0:
|
404
|
+
out.add_qubits([Qubit() for _ in range(num_additional_qubits)])
|
405
|
+
|
406
|
+
index_to_qubit = dict(enumerate(out.qubits))
|
407
|
+
outer_to_local = context.to_local_mapping()
|
347
408
|
|
348
409
|
for node in dag.topological_op_nodes():
|
349
|
-
|
350
|
-
|
351
|
-
|
410
|
+
|
411
|
+
if op_tuple := synthesized_nodes.get(node._node_id, None):
|
412
|
+
op, op_context = op_tuple
|
413
|
+
|
352
414
|
if isinstance(op, Operation):
|
353
|
-
out.apply_operation_back(op, qargs, cargs
|
415
|
+
out.apply_operation_back(op, node.qargs, node.cargs)
|
354
416
|
continue
|
355
417
|
|
356
418
|
if isinstance(op, QuantumCircuit):
|
357
419
|
op = circuit_to_dag(op, copy_operations=False)
|
358
420
|
|
421
|
+
inner_to_global = op_context.to_global_mapping()
|
359
422
|
if isinstance(op, DAGCircuit):
|
360
423
|
qubit_map = {
|
361
|
-
|
424
|
+
q: index_to_qubit[outer_to_local[inner_to_global[i]]]
|
425
|
+
for (i, q) in enumerate(op.qubits)
|
362
426
|
}
|
363
427
|
clbit_map = dict(zip(op.clbits, node.cargs))
|
428
|
+
|
364
429
|
for sub_node in op.op_nodes():
|
365
430
|
out.apply_operation_back(
|
366
431
|
sub_node.op,
|
@@ -368,11 +433,15 @@ class HighLevelSynthesis(TransformationPass):
|
|
368
433
|
tuple(clbit_map[carg] for carg in sub_node.cargs),
|
369
434
|
)
|
370
435
|
out.global_phase += op.global_phase
|
436
|
+
|
371
437
|
else:
|
372
|
-
raise
|
438
|
+
raise TranspilerError(f"Unexpected synthesized type: {type(op)}")
|
373
439
|
else:
|
374
440
|
out.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
|
375
441
|
|
442
|
+
if out.num_qubits() != context.num_qubits():
|
443
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
444
|
+
|
376
445
|
return out
|
377
446
|
|
378
447
|
def _synthesize_operation(
|
@@ -380,7 +449,23 @@ class HighLevelSynthesis(TransformationPass):
|
|
380
449
|
operation: Operation,
|
381
450
|
qubits: tuple[int],
|
382
451
|
tracker: QubitTracker,
|
383
|
-
|
452
|
+
context: QubitContext,
|
453
|
+
use_ancillas: bool,
|
454
|
+
) -> tuple[QuantumCircuit | Operation | DAGCircuit | None, QubitContext | None]:
|
455
|
+
"""
|
456
|
+
Synthesizes an operation. The function receives the qubits on which the operation
|
457
|
+
is defined in the current DAG, the correspondence between the qubits of the current
|
458
|
+
DAG and the global qubits and the global qubits tracker. The function returns the
|
459
|
+
result of synthesizing the operation. The value of `None` means that the operation
|
460
|
+
should remain as it is. When it's a circuit, we also return the context, i.e. the
|
461
|
+
correspondence of its local qubits and the global qubits. The function changes
|
462
|
+
in-place the tracker (state of the global qubits), the qubits (when the synthesized
|
463
|
+
operation is defined over additional ancilla qubits), and the context (to keep track
|
464
|
+
of where these ancilla qubits maps to).
|
465
|
+
"""
|
466
|
+
|
467
|
+
synthesized_context = None
|
468
|
+
|
384
469
|
# Try to synthesize the operation. We'll go through the following options:
|
385
470
|
# (1) Annotations: if the operator is annotated, synthesize the base operation
|
386
471
|
# and then apply the modifiers. Returns a circuit (e.g. applying a power)
|
@@ -389,31 +474,62 @@ class HighLevelSynthesis(TransformationPass):
|
|
389
474
|
# if the operation is a Clifford). Returns a circuit.
|
390
475
|
# (3) Unrolling custom definitions: try defining the operation if it is not yet
|
391
476
|
# in the set of supported instructions. Returns a circuit.
|
477
|
+
#
|
392
478
|
# If any of the above were triggered, we will recurse and go again through these steps
|
393
479
|
# until no further change occurred. At this point, we convert circuits to DAGs (the final
|
394
480
|
# possible return type). If there was no change, we just return ``None``.
|
481
|
+
num_original_qubits = len(qubits)
|
482
|
+
qubits = list(qubits)
|
483
|
+
|
395
484
|
synthesized = None
|
396
485
|
|
397
486
|
# Try synthesizing via AnnotatedOperation. This is faster than an isinstance check
|
398
487
|
# but a bit less safe since someone could create operations with a ``modifiers`` attribute.
|
399
488
|
if len(modifiers := getattr(operation, "modifiers", [])) > 0:
|
400
|
-
#
|
489
|
+
# Note: the base operation must be synthesized without using potential control qubits
|
401
490
|
# used in the modifiers.
|
402
491
|
num_ctrl = sum(
|
403
492
|
mod.num_ctrl_qubits for mod in modifiers if isinstance(mod, ControlModifier)
|
404
493
|
)
|
405
494
|
baseop_qubits = qubits[num_ctrl:] # reminder: control qubits are the first ones
|
406
|
-
baseop_tracker = tracker.copy(drop=qubits[:num_ctrl]) # no access to control qubits
|
407
495
|
|
408
496
|
# get qubits of base operation
|
497
|
+
control_qubits = qubits[0:num_ctrl]
|
498
|
+
|
499
|
+
# Do not allow access to control qubits
|
500
|
+
tracker.disable(context.to_globals(control_qubits))
|
409
501
|
synthesized_base_op, _ = self._synthesize_operation(
|
410
|
-
operation.base_op,
|
502
|
+
operation.base_op,
|
503
|
+
baseop_qubits,
|
504
|
+
tracker,
|
505
|
+
context,
|
506
|
+
use_ancillas=use_ancillas,
|
411
507
|
)
|
508
|
+
|
412
509
|
if synthesized_base_op is None:
|
413
510
|
synthesized_base_op = operation.base_op
|
414
511
|
elif isinstance(synthesized_base_op, DAGCircuit):
|
415
512
|
synthesized_base_op = dag_to_circuit(synthesized_base_op)
|
416
513
|
|
514
|
+
# Handle the case that synthesizing the base operation introduced
|
515
|
+
# additional qubits (e.g. the base operation is a circuit that includes
|
516
|
+
# an MCX gate).
|
517
|
+
if synthesized_base_op.num_qubits > len(baseop_qubits):
|
518
|
+
global_aux_qubits = tracker.borrow(
|
519
|
+
synthesized_base_op.num_qubits - len(baseop_qubits),
|
520
|
+
context.to_globals(baseop_qubits),
|
521
|
+
)
|
522
|
+
global_to_local = context.to_local_mapping()
|
523
|
+
for aq in global_aux_qubits:
|
524
|
+
if aq in global_to_local:
|
525
|
+
qubits.append(global_to_local[aq])
|
526
|
+
else:
|
527
|
+
new_local_qubit = context.add_qubit(aq)
|
528
|
+
qubits.append(new_local_qubit)
|
529
|
+
# Restore access to control qubits.
|
530
|
+
tracker.enable(context.to_globals(control_qubits))
|
531
|
+
|
532
|
+
# This step currently does not introduce ancilla qubits.
|
417
533
|
synthesized = self._apply_annotations(synthesized_base_op, operation.modifiers)
|
418
534
|
|
419
535
|
# If it was no AnnotatedOperation, try synthesizing via HLS or by unrolling.
|
@@ -421,57 +537,106 @@ class HighLevelSynthesis(TransformationPass):
|
|
421
537
|
# Try synthesis via HLS -- which will return ``None`` if unsuccessful.
|
422
538
|
indices = qubits if self._use_qubit_indices else None
|
423
539
|
if len(hls_methods := self._methods_to_try(operation.name)) > 0:
|
540
|
+
if use_ancillas:
|
541
|
+
num_clean_available = tracker.num_clean(context.to_globals(qubits))
|
542
|
+
num_dirty_available = tracker.num_dirty(context.to_globals(qubits))
|
543
|
+
else:
|
544
|
+
num_clean_available = 0
|
545
|
+
num_dirty_available = 0
|
424
546
|
synthesized = self._synthesize_op_using_plugins(
|
425
547
|
hls_methods,
|
426
548
|
operation,
|
427
549
|
indices,
|
428
|
-
|
429
|
-
|
550
|
+
num_clean_available,
|
551
|
+
num_dirty_available,
|
430
552
|
)
|
431
553
|
|
554
|
+
# It may happen that the plugin synthesis method uses clean/dirty ancilla qubits
|
555
|
+
if (synthesized is not None) and (synthesized.num_qubits > len(qubits)):
|
556
|
+
# need to borrow more qubits from tracker
|
557
|
+
global_aux_qubits = tracker.borrow(
|
558
|
+
synthesized.num_qubits - len(qubits), context.to_globals(qubits)
|
559
|
+
)
|
560
|
+
global_to_local = context.to_local_mapping()
|
561
|
+
|
562
|
+
for aq in global_aux_qubits:
|
563
|
+
if aq in global_to_local:
|
564
|
+
qubits.append(global_to_local[aq])
|
565
|
+
else:
|
566
|
+
new_local_qubit = context.add_qubit(aq)
|
567
|
+
qubits.append(new_local_qubit)
|
568
|
+
|
432
569
|
# If HLS did not apply, or was unsuccessful, try unrolling custom definitions.
|
433
570
|
if synthesized is None and not self._top_level_only:
|
434
|
-
synthesized = self.
|
571
|
+
synthesized = self._get_custom_definition(operation, indices)
|
435
572
|
|
436
573
|
if synthesized is None:
|
437
|
-
# if we didn't synthesize, there was nothing to unroll
|
438
|
-
|
574
|
+
# if we didn't synthesize, there was nothing to unroll
|
575
|
+
# updating the tracker will be handled upstream
|
576
|
+
pass
|
577
|
+
|
578
|
+
# if it has been synthesized, recurse and finally store the decomposition
|
579
|
+
elif isinstance(synthesized, Operation):
|
580
|
+
resynthesized, resynthesized_context = self._synthesize_operation(
|
581
|
+
synthesized, qubits, tracker, context, use_ancillas=use_ancillas
|
582
|
+
)
|
439
583
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
584
|
+
if resynthesized is not None:
|
585
|
+
synthesized = resynthesized
|
586
|
+
else:
|
587
|
+
tracker.set_dirty(context.to_globals(qubits))
|
588
|
+
if isinstance(resynthesized, DAGCircuit):
|
589
|
+
synthesized_context = resynthesized_context
|
590
|
+
|
591
|
+
elif isinstance(synthesized, QuantumCircuit):
|
592
|
+
# Synthesized is a quantum circuit which we want to process recursively.
|
593
|
+
# For example, it's the definition circuit of a custom gate
|
594
|
+
# or a circuit obtained by calling a synthesis method on a high-level-object.
|
595
|
+
# In the second case, synthesized may have more qubits than the original node.
|
596
|
+
|
597
|
+
as_dag = circuit_to_dag(synthesized, copy_operations=False)
|
598
|
+
inner_context = context.restrict(qubits)
|
599
|
+
|
600
|
+
if as_dag.num_qubits() != inner_context.num_qubits():
|
601
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
602
|
+
|
603
|
+
# We save the current state of the tracker to be able to return the ancilla
|
604
|
+
# qubits to the current positions. Note that at this point we do not know
|
605
|
+
# which ancilla qubits will be allocated.
|
606
|
+
saved_tracker = tracker.copy()
|
607
|
+
synthesized = self._run(
|
608
|
+
as_dag, tracker, inner_context, use_ancillas=use_ancillas, top_level=False
|
609
|
+
)
|
610
|
+
synthesized_context = inner_context
|
611
|
+
|
612
|
+
if (synthesized is not None) and (synthesized.num_qubits() > len(qubits)):
|
613
|
+
# need to borrow more qubits from tracker
|
614
|
+
global_aux_qubits = tracker.borrow(
|
615
|
+
synthesized.num_qubits() - len(qubits), context.to_globals(qubits)
|
616
|
+
)
|
617
|
+
global_to_local = context.to_local_mapping()
|
618
|
+
|
619
|
+
for aq in global_aux_qubits:
|
620
|
+
if aq in global_to_local:
|
621
|
+
qubits.append(global_to_local[aq])
|
622
|
+
else:
|
623
|
+
new_local_qubit = context.add_qubit(aq)
|
624
|
+
qubits.append(new_local_qubit)
|
625
|
+
|
626
|
+
if len(qubits) > num_original_qubits:
|
627
|
+
tracker.replace_state(
|
628
|
+
saved_tracker, context.to_globals(qubits[num_original_qubits:])
|
445
629
|
)
|
446
|
-
if re_synthesized is not None:
|
447
|
-
synthesized = re_synthesized
|
448
|
-
used_qubits = qubits
|
449
|
-
|
450
|
-
elif isinstance(synthesized, QuantumCircuit):
|
451
|
-
aux_qubits = tracker.borrow(synthesized.num_qubits - len(qubits), qubits)
|
452
|
-
used_qubits = qubits + tuple(aux_qubits)
|
453
|
-
as_dag = circuit_to_dag(synthesized, copy_operations=False)
|
454
|
-
|
455
|
-
# map used qubits to subcircuit
|
456
|
-
new_qubits = [as_dag.find_bit(q).index for q in as_dag.qubits]
|
457
|
-
qubit_map = dict(zip(used_qubits, new_qubits))
|
458
|
-
|
459
|
-
synthesized = self._run(as_dag, tracker.copy(qubit_map))
|
460
|
-
if synthesized.num_qubits() != len(used_qubits):
|
461
|
-
raise RuntimeError(
|
462
|
-
f"Mismatching number of qubits, using {synthesized.num_qubits()} "
|
463
|
-
f"but have {len(used_qubits)}."
|
464
|
-
)
|
465
630
|
|
466
|
-
|
467
|
-
|
631
|
+
else:
|
632
|
+
raise TranspilerError(f"Unexpected synthesized type: {type(synthesized)}")
|
468
633
|
|
469
|
-
if synthesized
|
470
|
-
raise
|
634
|
+
if isinstance(synthesized, DAGCircuit) and synthesized_context is None:
|
635
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
471
636
|
|
472
|
-
return synthesized,
|
637
|
+
return synthesized, synthesized_context
|
473
638
|
|
474
|
-
def
|
639
|
+
def _get_custom_definition(
|
475
640
|
self, inst: Instruction, qubits: list[int] | None
|
476
641
|
) -> QuantumCircuit | None:
|
477
642
|
# check if the operation is already supported natively
|
@@ -646,9 +811,10 @@ class HighLevelSynthesis(TransformationPass):
|
|
646
811
|
node (which is _most_ nodes)."""
|
647
812
|
|
648
813
|
if (
|
649
|
-
dag.
|
814
|
+
dag._has_calibration_for(node)
|
650
815
|
or len(node.qargs) < self._min_qubits
|
651
816
|
or node.is_directive()
|
817
|
+
or (self._instruction_supported(node.name, qubits) and not node.is_control_flow())
|
652
818
|
):
|
653
819
|
return True
|
654
820
|
|
@@ -666,15 +832,12 @@ class HighLevelSynthesis(TransformationPass):
|
|
666
832
|
# If all the above constraints hold, and it's already supported or the basis translator
|
667
833
|
# can handle it, we'll leave it be.
|
668
834
|
and (
|
669
|
-
self._instruction_supported(node.name, qubits)
|
670
835
|
# This uses unfortunately private details of `EquivalenceLibrary`, but so does the
|
671
836
|
# `BasisTranslator`, and this is supposed to just be temporary til this is moved
|
672
837
|
# into Rust space.
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
in self._equiv_lib._key_to_node_index
|
677
|
-
)
|
838
|
+
self._equiv_lib is not None
|
839
|
+
and equivalence.Key(name=node.name, num_qubits=node.num_qubits)
|
840
|
+
in self._equiv_lib.keys()
|
678
841
|
)
|
679
842
|
)
|
680
843
|
|