qiskit 1.3.0b1__cp39-abi3-win32.whl → 1.3.0rc1__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 +83 -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 +153 -1
- 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/providers/__init__.py +1 -1
- 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 +5 -5
- 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 +40 -130
- 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 +257 -93
- 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 +124 -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.0rc1.dist-info}/METADATA +3 -2
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc1.dist-info}/RECORD +356 -345
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc1.dist-info}/WHEEL +1 -1
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc1.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.0rc1.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc1.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,160 @@ 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] = (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
410
|
if node in synthesized_nodes:
|
350
|
-
op,
|
351
|
-
|
411
|
+
op, op_context = synthesized_nodes[node]
|
412
|
+
|
352
413
|
if isinstance(op, Operation):
|
353
|
-
out.apply_operation_back(op, qargs, cargs
|
414
|
+
out.apply_operation_back(op, node.qargs, node.cargs)
|
354
415
|
continue
|
355
416
|
|
356
417
|
if isinstance(op, QuantumCircuit):
|
357
418
|
op = circuit_to_dag(op, copy_operations=False)
|
358
419
|
|
420
|
+
inner_to_global = op_context.to_global_mapping()
|
359
421
|
if isinstance(op, DAGCircuit):
|
360
422
|
qubit_map = {
|
361
|
-
|
423
|
+
q: index_to_qubit[outer_to_local[inner_to_global[i]]]
|
424
|
+
for (i, q) in enumerate(op.qubits)
|
362
425
|
}
|
363
426
|
clbit_map = dict(zip(op.clbits, node.cargs))
|
427
|
+
|
364
428
|
for sub_node in op.op_nodes():
|
365
429
|
out.apply_operation_back(
|
366
430
|
sub_node.op,
|
@@ -368,11 +432,15 @@ class HighLevelSynthesis(TransformationPass):
|
|
368
432
|
tuple(clbit_map[carg] for carg in sub_node.cargs),
|
369
433
|
)
|
370
434
|
out.global_phase += op.global_phase
|
435
|
+
|
371
436
|
else:
|
372
|
-
raise
|
437
|
+
raise TranspilerError(f"Unexpected synthesized type: {type(op)}")
|
373
438
|
else:
|
374
439
|
out.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
|
375
440
|
|
441
|
+
if out.num_qubits() != context.num_qubits():
|
442
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
443
|
+
|
376
444
|
return out
|
377
445
|
|
378
446
|
def _synthesize_operation(
|
@@ -380,7 +448,23 @@ class HighLevelSynthesis(TransformationPass):
|
|
380
448
|
operation: Operation,
|
381
449
|
qubits: tuple[int],
|
382
450
|
tracker: QubitTracker,
|
383
|
-
|
451
|
+
context: QubitContext,
|
452
|
+
use_ancillas: bool,
|
453
|
+
) -> tuple[QuantumCircuit | Operation | DAGCircuit | None, QubitContext | None]:
|
454
|
+
"""
|
455
|
+
Synthesizes an operation. The function receives the qubits on which the operation
|
456
|
+
is defined in the current DAG, the correspondence between the qubits of the current
|
457
|
+
DAG and the global qubits and the global qubits tracker. The function returns the
|
458
|
+
result of synthesizing the operation. The value of `None` means that the operation
|
459
|
+
should remain as it is. When it's a circuit, we also return the context, i.e. the
|
460
|
+
correspondence of its local qubits and the global qubits. The function changes
|
461
|
+
in-place the tracker (state of the global qubits), the qubits (when the synthesized
|
462
|
+
operation is defined over additional ancilla qubits), and the context (to keep track
|
463
|
+
of where these ancilla qubits maps to).
|
464
|
+
"""
|
465
|
+
|
466
|
+
synthesized_context = None
|
467
|
+
|
384
468
|
# Try to synthesize the operation. We'll go through the following options:
|
385
469
|
# (1) Annotations: if the operator is annotated, synthesize the base operation
|
386
470
|
# and then apply the modifiers. Returns a circuit (e.g. applying a power)
|
@@ -389,31 +473,62 @@ class HighLevelSynthesis(TransformationPass):
|
|
389
473
|
# if the operation is a Clifford). Returns a circuit.
|
390
474
|
# (3) Unrolling custom definitions: try defining the operation if it is not yet
|
391
475
|
# in the set of supported instructions. Returns a circuit.
|
476
|
+
#
|
392
477
|
# If any of the above were triggered, we will recurse and go again through these steps
|
393
478
|
# until no further change occurred. At this point, we convert circuits to DAGs (the final
|
394
479
|
# possible return type). If there was no change, we just return ``None``.
|
480
|
+
num_original_qubits = len(qubits)
|
481
|
+
qubits = list(qubits)
|
482
|
+
|
395
483
|
synthesized = None
|
396
484
|
|
397
485
|
# Try synthesizing via AnnotatedOperation. This is faster than an isinstance check
|
398
486
|
# but a bit less safe since someone could create operations with a ``modifiers`` attribute.
|
399
487
|
if len(modifiers := getattr(operation, "modifiers", [])) > 0:
|
400
|
-
#
|
488
|
+
# Note: the base operation must be synthesized without using potential control qubits
|
401
489
|
# used in the modifiers.
|
402
490
|
num_ctrl = sum(
|
403
491
|
mod.num_ctrl_qubits for mod in modifiers if isinstance(mod, ControlModifier)
|
404
492
|
)
|
405
493
|
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
494
|
|
408
495
|
# get qubits of base operation
|
496
|
+
control_qubits = qubits[0:num_ctrl]
|
497
|
+
|
498
|
+
# Do not allow access to control qubits
|
499
|
+
tracker.disable(context.to_globals(control_qubits))
|
409
500
|
synthesized_base_op, _ = self._synthesize_operation(
|
410
|
-
operation.base_op,
|
501
|
+
operation.base_op,
|
502
|
+
baseop_qubits,
|
503
|
+
tracker,
|
504
|
+
context,
|
505
|
+
use_ancillas=use_ancillas,
|
411
506
|
)
|
507
|
+
|
412
508
|
if synthesized_base_op is None:
|
413
509
|
synthesized_base_op = operation.base_op
|
414
510
|
elif isinstance(synthesized_base_op, DAGCircuit):
|
415
511
|
synthesized_base_op = dag_to_circuit(synthesized_base_op)
|
416
512
|
|
513
|
+
# Handle the case that synthesizing the base operation introduced
|
514
|
+
# additional qubits (e.g. the base operation is a circuit that includes
|
515
|
+
# an MCX gate).
|
516
|
+
if synthesized_base_op.num_qubits > len(baseop_qubits):
|
517
|
+
global_aux_qubits = tracker.borrow(
|
518
|
+
synthesized_base_op.num_qubits - len(baseop_qubits),
|
519
|
+
context.to_globals(baseop_qubits),
|
520
|
+
)
|
521
|
+
global_to_local = context.to_local_mapping()
|
522
|
+
for aq in global_aux_qubits:
|
523
|
+
if aq in global_to_local:
|
524
|
+
qubits.append(global_to_local[aq])
|
525
|
+
else:
|
526
|
+
new_local_qubit = context.add_qubit(aq)
|
527
|
+
qubits.append(new_local_qubit)
|
528
|
+
# Restore access to control qubits.
|
529
|
+
tracker.enable(context.to_globals(control_qubits))
|
530
|
+
|
531
|
+
# This step currently does not introduce ancilla qubits.
|
417
532
|
synthesized = self._apply_annotations(synthesized_base_op, operation.modifiers)
|
418
533
|
|
419
534
|
# If it was no AnnotatedOperation, try synthesizing via HLS or by unrolling.
|
@@ -421,57 +536,106 @@ class HighLevelSynthesis(TransformationPass):
|
|
421
536
|
# Try synthesis via HLS -- which will return ``None`` if unsuccessful.
|
422
537
|
indices = qubits if self._use_qubit_indices else None
|
423
538
|
if len(hls_methods := self._methods_to_try(operation.name)) > 0:
|
539
|
+
if use_ancillas:
|
540
|
+
num_clean_available = tracker.num_clean(context.to_globals(qubits))
|
541
|
+
num_dirty_available = tracker.num_dirty(context.to_globals(qubits))
|
542
|
+
else:
|
543
|
+
num_clean_available = 0
|
544
|
+
num_dirty_available = 0
|
424
545
|
synthesized = self._synthesize_op_using_plugins(
|
425
546
|
hls_methods,
|
426
547
|
operation,
|
427
548
|
indices,
|
428
|
-
|
429
|
-
|
549
|
+
num_clean_available,
|
550
|
+
num_dirty_available,
|
430
551
|
)
|
431
552
|
|
553
|
+
# It may happen that the plugin synthesis method uses clean/dirty ancilla qubits
|
554
|
+
if (synthesized is not None) and (synthesized.num_qubits > len(qubits)):
|
555
|
+
# need to borrow more qubits from tracker
|
556
|
+
global_aux_qubits = tracker.borrow(
|
557
|
+
synthesized.num_qubits - len(qubits), context.to_globals(qubits)
|
558
|
+
)
|
559
|
+
global_to_local = context.to_local_mapping()
|
560
|
+
|
561
|
+
for aq in global_aux_qubits:
|
562
|
+
if aq in global_to_local:
|
563
|
+
qubits.append(global_to_local[aq])
|
564
|
+
else:
|
565
|
+
new_local_qubit = context.add_qubit(aq)
|
566
|
+
qubits.append(new_local_qubit)
|
567
|
+
|
432
568
|
# If HLS did not apply, or was unsuccessful, try unrolling custom definitions.
|
433
569
|
if synthesized is None and not self._top_level_only:
|
434
|
-
synthesized = self.
|
570
|
+
synthesized = self._get_custom_definition(operation, indices)
|
435
571
|
|
436
572
|
if synthesized is None:
|
437
|
-
# if we didn't synthesize, there was nothing to unroll
|
438
|
-
|
573
|
+
# if we didn't synthesize, there was nothing to unroll
|
574
|
+
# updating the tracker will be handled upstream
|
575
|
+
pass
|
576
|
+
|
577
|
+
# if it has been synthesized, recurse and finally store the decomposition
|
578
|
+
elif isinstance(synthesized, Operation):
|
579
|
+
resynthesized, resynthesized_context = self._synthesize_operation(
|
580
|
+
synthesized, qubits, tracker, context, use_ancillas=use_ancillas
|
581
|
+
)
|
439
582
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
583
|
+
if resynthesized is not None:
|
584
|
+
synthesized = resynthesized
|
585
|
+
else:
|
586
|
+
tracker.set_dirty(context.to_globals(qubits))
|
587
|
+
if isinstance(resynthesized, DAGCircuit):
|
588
|
+
synthesized_context = resynthesized_context
|
589
|
+
|
590
|
+
elif isinstance(synthesized, QuantumCircuit):
|
591
|
+
# Synthesized is a quantum circuit which we want to process recursively.
|
592
|
+
# For example, it's the definition circuit of a custom gate
|
593
|
+
# or a circuit obtained by calling a synthesis method on a high-level-object.
|
594
|
+
# In the second case, synthesized may have more qubits than the original node.
|
595
|
+
|
596
|
+
as_dag = circuit_to_dag(synthesized, copy_operations=False)
|
597
|
+
inner_context = context.restrict(qubits)
|
598
|
+
|
599
|
+
if as_dag.num_qubits() != inner_context.num_qubits():
|
600
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
601
|
+
|
602
|
+
# We save the current state of the tracker to be able to return the ancilla
|
603
|
+
# qubits to the current positions. Note that at this point we do not know
|
604
|
+
# which ancilla qubits will be allocated.
|
605
|
+
saved_tracker = tracker.copy()
|
606
|
+
synthesized = self._run(
|
607
|
+
as_dag, tracker, inner_context, use_ancillas=use_ancillas, top_level=False
|
608
|
+
)
|
609
|
+
synthesized_context = inner_context
|
610
|
+
|
611
|
+
if (synthesized is not None) and (synthesized.num_qubits() > len(qubits)):
|
612
|
+
# need to borrow more qubits from tracker
|
613
|
+
global_aux_qubits = tracker.borrow(
|
614
|
+
synthesized.num_qubits() - len(qubits), context.to_globals(qubits)
|
615
|
+
)
|
616
|
+
global_to_local = context.to_local_mapping()
|
617
|
+
|
618
|
+
for aq in global_aux_qubits:
|
619
|
+
if aq in global_to_local:
|
620
|
+
qubits.append(global_to_local[aq])
|
621
|
+
else:
|
622
|
+
new_local_qubit = context.add_qubit(aq)
|
623
|
+
qubits.append(new_local_qubit)
|
624
|
+
|
625
|
+
if len(qubits) > num_original_qubits:
|
626
|
+
tracker.replace_state(
|
627
|
+
saved_tracker, context.to_globals(qubits[num_original_qubits:])
|
445
628
|
)
|
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
629
|
|
466
|
-
|
467
|
-
|
630
|
+
else:
|
631
|
+
raise TranspilerError(f"Unexpected synthesized type: {type(synthesized)}")
|
468
632
|
|
469
|
-
if synthesized
|
470
|
-
raise
|
633
|
+
if isinstance(synthesized, DAGCircuit) and synthesized_context is None:
|
634
|
+
raise TranspilerError("HighLevelSynthesis internal error.")
|
471
635
|
|
472
|
-
return synthesized,
|
636
|
+
return synthesized, synthesized_context
|
473
637
|
|
474
|
-
def
|
638
|
+
def _get_custom_definition(
|
475
639
|
self, inst: Instruction, qubits: list[int] | None
|
476
640
|
) -> QuantumCircuit | None:
|
477
641
|
# check if the operation is already supported natively
|
@@ -646,7 +810,7 @@ class HighLevelSynthesis(TransformationPass):
|
|
646
810
|
node (which is _most_ nodes)."""
|
647
811
|
|
648
812
|
if (
|
649
|
-
dag.
|
813
|
+
dag._has_calibration_for(node)
|
650
814
|
or len(node.qargs) < self._min_qubits
|
651
815
|
or node.is_directive()
|
652
816
|
):
|
@@ -673,7 +837,7 @@ class HighLevelSynthesis(TransformationPass):
|
|
673
837
|
or (
|
674
838
|
self._equiv_lib is not None
|
675
839
|
and equivalence.Key(name=node.name, num_qubits=node.num_qubits)
|
676
|
-
in self._equiv_lib.
|
840
|
+
in self._equiv_lib.keys()
|
677
841
|
)
|
678
842
|
)
|
679
843
|
)
|