qiskit 2.0.3__cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.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 -0
- qiskit/__init__.py +141 -0
- qiskit/_accelerate.abi3.so +0 -0
- qiskit/_numpy_compat.py +73 -0
- qiskit/circuit/__init__.py +1343 -0
- qiskit/circuit/_add_control.py +312 -0
- qiskit/circuit/_classical_resource_map.py +150 -0
- qiskit/circuit/_standard_gates_commutations.py +3849 -0
- qiskit/circuit/_utils.py +167 -0
- qiskit/circuit/annotated_operation.py +279 -0
- qiskit/circuit/barrier.py +46 -0
- qiskit/circuit/classical/__init__.py +41 -0
- qiskit/circuit/classical/expr/__init__.py +266 -0
- qiskit/circuit/classical/expr/constructors.py +764 -0
- qiskit/circuit/classical/expr/expr.py +498 -0
- qiskit/circuit/classical/expr/visitors.py +375 -0
- qiskit/circuit/classical/types/__init__.py +113 -0
- qiskit/circuit/classical/types/ordering.py +229 -0
- qiskit/circuit/classical/types/types.py +153 -0
- qiskit/circuit/commutation_checker.py +133 -0
- qiskit/circuit/commutation_library.py +20 -0
- qiskit/circuit/controlflow/__init__.py +59 -0
- qiskit/circuit/controlflow/_builder_utils.py +211 -0
- qiskit/circuit/controlflow/box.py +163 -0
- qiskit/circuit/controlflow/break_loop.py +56 -0
- qiskit/circuit/controlflow/builder.py +791 -0
- qiskit/circuit/controlflow/continue_loop.py +56 -0
- qiskit/circuit/controlflow/control_flow.py +94 -0
- qiskit/circuit/controlflow/for_loop.py +218 -0
- qiskit/circuit/controlflow/if_else.py +498 -0
- qiskit/circuit/controlflow/switch_case.py +411 -0
- qiskit/circuit/controlflow/while_loop.py +166 -0
- qiskit/circuit/controlledgate.py +274 -0
- qiskit/circuit/delay.py +157 -0
- qiskit/circuit/duration.py +80 -0
- qiskit/circuit/equivalence.py +94 -0
- qiskit/circuit/equivalence_library.py +18 -0
- qiskit/circuit/exceptions.py +19 -0
- qiskit/circuit/gate.py +261 -0
- qiskit/circuit/instruction.py +564 -0
- qiskit/circuit/instructionset.py +132 -0
- qiskit/circuit/library/__init__.py +984 -0
- qiskit/circuit/library/arithmetic/__init__.py +40 -0
- qiskit/circuit/library/arithmetic/adders/__init__.py +18 -0
- qiskit/circuit/library/arithmetic/adders/adder.py +235 -0
- qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +123 -0
- qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +129 -0
- qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +95 -0
- qiskit/circuit/library/arithmetic/exact_reciprocal.py +131 -0
- qiskit/circuit/library/arithmetic/functional_pauli_rotations.py +114 -0
- qiskit/circuit/library/arithmetic/integer_comparator.py +200 -0
- qiskit/circuit/library/arithmetic/linear_amplitude_function.py +363 -0
- qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +243 -0
- qiskit/circuit/library/arithmetic/multipliers/__init__.py +17 -0
- qiskit/circuit/library/arithmetic/multipliers/hrs_cumulative_multiplier.py +145 -0
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +201 -0
- qiskit/circuit/library/arithmetic/multipliers/rg_qft_multiplier.py +108 -0
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +502 -0
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +387 -0
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +493 -0
- qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +389 -0
- qiskit/circuit/library/arithmetic/quadratic_form.py +364 -0
- qiskit/circuit/library/arithmetic/weighted_adder.py +409 -0
- qiskit/circuit/library/basis_change/__init__.py +15 -0
- qiskit/circuit/library/basis_change/qft.py +316 -0
- qiskit/circuit/library/bit_flip_oracle.py +130 -0
- qiskit/circuit/library/blueprintcircuit.py +316 -0
- qiskit/circuit/library/boolean_logic/__init__.py +18 -0
- qiskit/circuit/library/boolean_logic/inner_product.py +157 -0
- qiskit/circuit/library/boolean_logic/quantum_and.py +204 -0
- qiskit/circuit/library/boolean_logic/quantum_or.py +206 -0
- qiskit/circuit/library/boolean_logic/quantum_xor.py +167 -0
- qiskit/circuit/library/data_preparation/__init__.py +57 -0
- qiskit/circuit/library/data_preparation/_z_feature_map.py +115 -0
- qiskit/circuit/library/data_preparation/_zz_feature_map.py +150 -0
- qiskit/circuit/library/data_preparation/initializer.py +107 -0
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +656 -0
- qiskit/circuit/library/data_preparation/state_preparation.py +336 -0
- qiskit/circuit/library/fourier_checking.py +160 -0
- qiskit/circuit/library/generalized_gates/__init__.py +30 -0
- qiskit/circuit/library/generalized_gates/diagonal.py +159 -0
- qiskit/circuit/library/generalized_gates/gms.py +175 -0
- qiskit/circuit/library/generalized_gates/gr.py +219 -0
- qiskit/circuit/library/generalized_gates/isometry.py +370 -0
- qiskit/circuit/library/generalized_gates/linear_function.py +318 -0
- qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +143 -0
- qiskit/circuit/library/generalized_gates/mcmt.py +316 -0
- qiskit/circuit/library/generalized_gates/pauli.py +84 -0
- qiskit/circuit/library/generalized_gates/permutation.py +198 -0
- qiskit/circuit/library/generalized_gates/rv.py +96 -0
- qiskit/circuit/library/generalized_gates/uc.py +303 -0
- qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +164 -0
- qiskit/circuit/library/generalized_gates/ucrx.py +32 -0
- qiskit/circuit/library/generalized_gates/ucry.py +32 -0
- qiskit/circuit/library/generalized_gates/ucrz.py +32 -0
- qiskit/circuit/library/generalized_gates/unitary.py +217 -0
- qiskit/circuit/library/graph_state.py +172 -0
- qiskit/circuit/library/grover_operator.py +583 -0
- qiskit/circuit/library/hamiltonian_gate.py +142 -0
- qiskit/circuit/library/hidden_linear_function.py +163 -0
- qiskit/circuit/library/iqp.py +180 -0
- qiskit/circuit/library/n_local/__init__.py +45 -0
- qiskit/circuit/library/n_local/efficient_su2.py +282 -0
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +520 -0
- qiskit/circuit/library/n_local/excitation_preserving.py +303 -0
- qiskit/circuit/library/n_local/n_local.py +1477 -0
- qiskit/circuit/library/n_local/pauli_two_design.py +246 -0
- qiskit/circuit/library/n_local/qaoa_ansatz.py +367 -0
- qiskit/circuit/library/n_local/real_amplitudes.py +312 -0
- qiskit/circuit/library/n_local/two_local.py +289 -0
- qiskit/circuit/library/overlap.py +183 -0
- qiskit/circuit/library/pauli_evolution.py +201 -0
- qiskit/circuit/library/phase_estimation.py +177 -0
- qiskit/circuit/library/phase_oracle.py +239 -0
- qiskit/circuit/library/quantum_volume.py +180 -0
- qiskit/circuit/library/standard_gates/__init__.py +141 -0
- qiskit/circuit/library/standard_gates/dcx.py +77 -0
- qiskit/circuit/library/standard_gates/ecr.py +129 -0
- qiskit/circuit/library/standard_gates/equivalence_library.py +1800 -0
- qiskit/circuit/library/standard_gates/global_phase.py +84 -0
- qiskit/circuit/library/standard_gates/h.py +253 -0
- qiskit/circuit/library/standard_gates/i.py +76 -0
- qiskit/circuit/library/standard_gates/iswap.py +133 -0
- qiskit/circuit/library/standard_gates/p.py +422 -0
- qiskit/circuit/library/standard_gates/r.py +114 -0
- qiskit/circuit/library/standard_gates/rx.py +293 -0
- qiskit/circuit/library/standard_gates/rxx.py +180 -0
- qiskit/circuit/library/standard_gates/ry.py +286 -0
- qiskit/circuit/library/standard_gates/ryy.py +180 -0
- qiskit/circuit/library/standard_gates/rz.py +307 -0
- qiskit/circuit/library/standard_gates/rzx.py +226 -0
- qiskit/circuit/library/standard_gates/rzz.py +193 -0
- qiskit/circuit/library/standard_gates/s.py +419 -0
- qiskit/circuit/library/standard_gates/swap.py +281 -0
- qiskit/circuit/library/standard_gates/sx.py +310 -0
- qiskit/circuit/library/standard_gates/t.py +178 -0
- qiskit/circuit/library/standard_gates/u.py +395 -0
- qiskit/circuit/library/standard_gates/u1.py +490 -0
- qiskit/circuit/library/standard_gates/u2.py +145 -0
- qiskit/circuit/library/standard_gates/u3.py +428 -0
- qiskit/circuit/library/standard_gates/x.py +1481 -0
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +202 -0
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +236 -0
- qiskit/circuit/library/standard_gates/y.py +257 -0
- qiskit/circuit/library/standard_gates/z.py +338 -0
- qiskit/circuit/library/templates/__init__.py +92 -0
- qiskit/circuit/library/templates/clifford/__init__.py +33 -0
- qiskit/circuit/library/templates/clifford/clifford_2_1.py +34 -0
- qiskit/circuit/library/templates/clifford/clifford_2_2.py +35 -0
- qiskit/circuit/library/templates/clifford/clifford_2_3.py +34 -0
- qiskit/circuit/library/templates/clifford/clifford_2_4.py +34 -0
- qiskit/circuit/library/templates/clifford/clifford_3_1.py +35 -0
- qiskit/circuit/library/templates/clifford/clifford_4_1.py +38 -0
- qiskit/circuit/library/templates/clifford/clifford_4_2.py +37 -0
- qiskit/circuit/library/templates/clifford/clifford_4_3.py +38 -0
- qiskit/circuit/library/templates/clifford/clifford_4_4.py +37 -0
- qiskit/circuit/library/templates/clifford/clifford_5_1.py +40 -0
- qiskit/circuit/library/templates/clifford/clifford_6_1.py +40 -0
- qiskit/circuit/library/templates/clifford/clifford_6_2.py +40 -0
- qiskit/circuit/library/templates/clifford/clifford_6_3.py +40 -0
- qiskit/circuit/library/templates/clifford/clifford_6_4.py +38 -0
- qiskit/circuit/library/templates/clifford/clifford_6_5.py +40 -0
- qiskit/circuit/library/templates/clifford/clifford_8_1.py +42 -0
- qiskit/circuit/library/templates/clifford/clifford_8_2.py +42 -0
- qiskit/circuit/library/templates/clifford/clifford_8_3.py +41 -0
- qiskit/circuit/library/templates/nct/__init__.py +67 -0
- qiskit/circuit/library/templates/nct/template_nct_2a_1.py +34 -0
- qiskit/circuit/library/templates/nct/template_nct_2a_2.py +35 -0
- qiskit/circuit/library/templates/nct/template_nct_2a_3.py +37 -0
- qiskit/circuit/library/templates/nct/template_nct_4a_1.py +43 -0
- qiskit/circuit/library/templates/nct/template_nct_4a_2.py +41 -0
- qiskit/circuit/library/templates/nct/template_nct_4a_3.py +39 -0
- qiskit/circuit/library/templates/nct/template_nct_4b_1.py +41 -0
- qiskit/circuit/library/templates/nct/template_nct_4b_2.py +39 -0
- qiskit/circuit/library/templates/nct/template_nct_5a_1.py +40 -0
- qiskit/circuit/library/templates/nct/template_nct_5a_2.py +40 -0
- qiskit/circuit/library/templates/nct/template_nct_5a_3.py +40 -0
- qiskit/circuit/library/templates/nct/template_nct_5a_4.py +39 -0
- qiskit/circuit/library/templates/nct/template_nct_6a_1.py +40 -0
- qiskit/circuit/library/templates/nct/template_nct_6a_2.py +41 -0
- qiskit/circuit/library/templates/nct/template_nct_6a_3.py +41 -0
- qiskit/circuit/library/templates/nct/template_nct_6a_4.py +41 -0
- qiskit/circuit/library/templates/nct/template_nct_6b_1.py +41 -0
- qiskit/circuit/library/templates/nct/template_nct_6b_2.py +41 -0
- qiskit/circuit/library/templates/nct/template_nct_6c_1.py +41 -0
- qiskit/circuit/library/templates/nct/template_nct_7a_1.py +43 -0
- qiskit/circuit/library/templates/nct/template_nct_7b_1.py +43 -0
- qiskit/circuit/library/templates/nct/template_nct_7c_1.py +43 -0
- qiskit/circuit/library/templates/nct/template_nct_7d_1.py +43 -0
- qiskit/circuit/library/templates/nct/template_nct_7e_1.py +43 -0
- qiskit/circuit/library/templates/nct/template_nct_9a_1.py +45 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_1.py +43 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_10.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_11.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_12.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_2.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_3.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_4.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_5.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_6.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_7.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_8.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9c_9.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_1.py +43 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_10.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_2.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_3.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_4.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_5.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_6.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_7.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_8.py +44 -0
- qiskit/circuit/library/templates/nct/template_nct_9d_9.py +44 -0
- qiskit/circuit/library/templates/rzx/__init__.py +25 -0
- qiskit/circuit/library/templates/rzx/rzx_cy.py +47 -0
- qiskit/circuit/library/templates/rzx/rzx_xz.py +54 -0
- qiskit/circuit/library/templates/rzx/rzx_yz.py +45 -0
- qiskit/circuit/library/templates/rzx/rzx_zz1.py +69 -0
- qiskit/circuit/library/templates/rzx/rzx_zz2.py +59 -0
- qiskit/circuit/library/templates/rzx/rzx_zz3.py +59 -0
- qiskit/circuit/measure.py +53 -0
- qiskit/circuit/operation.py +68 -0
- qiskit/circuit/parameter.py +179 -0
- qiskit/circuit/parameterexpression.py +703 -0
- qiskit/circuit/parametertable.py +119 -0
- qiskit/circuit/parametervector.py +140 -0
- qiskit/circuit/quantumcircuit.py +7540 -0
- qiskit/circuit/quantumcircuitdata.py +136 -0
- qiskit/circuit/random/__init__.py +15 -0
- qiskit/circuit/random/utils.py +366 -0
- qiskit/circuit/reset.py +37 -0
- qiskit/circuit/singleton.py +600 -0
- qiskit/circuit/store.py +89 -0
- qiskit/circuit/tools/__init__.py +16 -0
- qiskit/circuit/tools/pi_check.py +193 -0
- qiskit/circuit/twirling.py +145 -0
- qiskit/compiler/__init__.py +27 -0
- qiskit/compiler/transpiler.py +375 -0
- qiskit/converters/__init__.py +74 -0
- qiskit/converters/circuit_to_dag.py +80 -0
- qiskit/converters/circuit_to_dagdependency.py +49 -0
- qiskit/converters/circuit_to_dagdependency_v2.py +46 -0
- qiskit/converters/circuit_to_gate.py +107 -0
- qiskit/converters/circuit_to_instruction.py +142 -0
- qiskit/converters/dag_to_circuit.py +79 -0
- qiskit/converters/dag_to_dagdependency.py +54 -0
- qiskit/converters/dag_to_dagdependency_v2.py +43 -0
- qiskit/converters/dagdependency_to_circuit.py +40 -0
- qiskit/converters/dagdependency_to_dag.py +48 -0
- qiskit/dagcircuit/__init__.py +55 -0
- qiskit/dagcircuit/collect_blocks.py +407 -0
- qiskit/dagcircuit/dagcircuit.py +24 -0
- qiskit/dagcircuit/dagdependency.py +612 -0
- qiskit/dagcircuit/dagdependency_v2.py +566 -0
- qiskit/dagcircuit/dagdepnode.py +160 -0
- qiskit/dagcircuit/dagnode.py +188 -0
- qiskit/dagcircuit/exceptions.py +42 -0
- qiskit/exceptions.py +153 -0
- qiskit/passmanager/__init__.py +258 -0
- qiskit/passmanager/base_tasks.py +230 -0
- qiskit/passmanager/compilation_status.py +74 -0
- qiskit/passmanager/exceptions.py +19 -0
- qiskit/passmanager/flow_controllers.py +116 -0
- qiskit/passmanager/passmanager.py +353 -0
- qiskit/primitives/__init__.py +490 -0
- qiskit/primitives/backend_estimator_v2.py +530 -0
- qiskit/primitives/backend_sampler_v2.py +339 -0
- qiskit/primitives/base/__init__.py +20 -0
- qiskit/primitives/base/base_estimator.py +247 -0
- qiskit/primitives/base/base_primitive_job.py +78 -0
- qiskit/primitives/base/base_primitive_v1.py +45 -0
- qiskit/primitives/base/base_result_v1.py +65 -0
- qiskit/primitives/base/base_sampler.py +196 -0
- qiskit/primitives/base/estimator_result_v1.py +46 -0
- qiskit/primitives/base/sampler_result_v1.py +45 -0
- qiskit/primitives/base/validation_v1.py +250 -0
- qiskit/primitives/containers/__init__.py +26 -0
- qiskit/primitives/containers/bindings_array.py +391 -0
- qiskit/primitives/containers/bit_array.py +764 -0
- qiskit/primitives/containers/data_bin.py +175 -0
- qiskit/primitives/containers/estimator_pub.py +222 -0
- qiskit/primitives/containers/object_array.py +94 -0
- qiskit/primitives/containers/observables_array.py +296 -0
- qiskit/primitives/containers/primitive_result.py +53 -0
- qiskit/primitives/containers/pub_result.py +51 -0
- qiskit/primitives/containers/sampler_pub.py +193 -0
- qiskit/primitives/containers/sampler_pub_result.py +74 -0
- qiskit/primitives/containers/shape.py +129 -0
- qiskit/primitives/primitive_job.py +81 -0
- qiskit/primitives/statevector_estimator.py +175 -0
- qiskit/primitives/statevector_sampler.py +290 -0
- qiskit/primitives/utils.py +72 -0
- qiskit/providers/__init__.py +677 -0
- qiskit/providers/backend.py +364 -0
- qiskit/providers/basic_provider/__init__.py +47 -0
- qiskit/providers/basic_provider/basic_provider.py +121 -0
- qiskit/providers/basic_provider/basic_provider_job.py +65 -0
- qiskit/providers/basic_provider/basic_provider_tools.py +218 -0
- qiskit/providers/basic_provider/basic_simulator.py +693 -0
- qiskit/providers/basic_provider/exceptions.py +30 -0
- qiskit/providers/exceptions.py +33 -0
- qiskit/providers/fake_provider/__init__.py +69 -0
- qiskit/providers/fake_provider/generic_backend_v2.py +374 -0
- qiskit/providers/fake_provider/utils/__init__.py +15 -0
- qiskit/providers/job.py +147 -0
- qiskit/providers/jobstatus.py +30 -0
- qiskit/providers/options.py +273 -0
- qiskit/providers/providerutils.py +110 -0
- qiskit/qasm/libs/dummy/stdgates.inc +75 -0
- qiskit/qasm/libs/qelib1.inc +266 -0
- qiskit/qasm/libs/stdgates.inc +82 -0
- qiskit/qasm2/__init__.py +669 -0
- qiskit/qasm2/exceptions.py +27 -0
- qiskit/qasm2/export.py +364 -0
- qiskit/qasm2/parse.py +438 -0
- qiskit/qasm3/__init__.py +372 -0
- qiskit/qasm3/ast.py +782 -0
- qiskit/qasm3/exceptions.py +27 -0
- qiskit/qasm3/experimental.py +70 -0
- qiskit/qasm3/exporter.py +1340 -0
- qiskit/qasm3/printer.py +608 -0
- qiskit/qpy/__init__.py +1965 -0
- qiskit/qpy/binary_io/__init__.py +35 -0
- qiskit/qpy/binary_io/circuits.py +1455 -0
- qiskit/qpy/binary_io/parse_sympy_repr.py +121 -0
- qiskit/qpy/binary_io/schedules.py +308 -0
- qiskit/qpy/binary_io/value.py +1165 -0
- qiskit/qpy/common.py +353 -0
- qiskit/qpy/exceptions.py +53 -0
- qiskit/qpy/formats.py +442 -0
- qiskit/qpy/interface.py +344 -0
- qiskit/qpy/type_keys.py +409 -0
- qiskit/quantum_info/__init__.py +162 -0
- qiskit/quantum_info/analysis/__init__.py +17 -0
- qiskit/quantum_info/analysis/average.py +47 -0
- qiskit/quantum_info/analysis/distance.py +104 -0
- qiskit/quantum_info/analysis/make_observable.py +44 -0
- qiskit/quantum_info/analysis/z2_symmetries.py +484 -0
- qiskit/quantum_info/operators/__init__.py +28 -0
- qiskit/quantum_info/operators/base_operator.py +145 -0
- qiskit/quantum_info/operators/channel/__init__.py +29 -0
- qiskit/quantum_info/operators/channel/chi.py +191 -0
- qiskit/quantum_info/operators/channel/choi.py +218 -0
- qiskit/quantum_info/operators/channel/kraus.py +337 -0
- qiskit/quantum_info/operators/channel/ptm.py +204 -0
- qiskit/quantum_info/operators/channel/quantum_channel.py +348 -0
- qiskit/quantum_info/operators/channel/stinespring.py +296 -0
- qiskit/quantum_info/operators/channel/superop.py +373 -0
- qiskit/quantum_info/operators/channel/transformations.py +490 -0
- qiskit/quantum_info/operators/custom_iterator.py +48 -0
- qiskit/quantum_info/operators/dihedral/__init__.py +18 -0
- qiskit/quantum_info/operators/dihedral/dihedral.py +511 -0
- qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +216 -0
- qiskit/quantum_info/operators/dihedral/polynomial.py +313 -0
- qiskit/quantum_info/operators/dihedral/random.py +64 -0
- qiskit/quantum_info/operators/linear_op.py +25 -0
- qiskit/quantum_info/operators/measures.py +418 -0
- qiskit/quantum_info/operators/mixins/__init__.py +52 -0
- qiskit/quantum_info/operators/mixins/adjoint.py +52 -0
- qiskit/quantum_info/operators/mixins/group.py +171 -0
- qiskit/quantum_info/operators/mixins/linear.py +84 -0
- qiskit/quantum_info/operators/mixins/multiply.py +62 -0
- qiskit/quantum_info/operators/mixins/tolerances.py +72 -0
- qiskit/quantum_info/operators/op_shape.py +525 -0
- qiskit/quantum_info/operators/operator.py +869 -0
- qiskit/quantum_info/operators/operator_utils.py +76 -0
- qiskit/quantum_info/operators/predicates.py +183 -0
- qiskit/quantum_info/operators/random.py +154 -0
- qiskit/quantum_info/operators/scalar_op.py +254 -0
- qiskit/quantum_info/operators/symplectic/__init__.py +23 -0
- qiskit/quantum_info/operators/symplectic/base_pauli.py +719 -0
- qiskit/quantum_info/operators/symplectic/clifford.py +1032 -0
- qiskit/quantum_info/operators/symplectic/clifford_circuits.py +558 -0
- qiskit/quantum_info/operators/symplectic/pauli.py +755 -0
- qiskit/quantum_info/operators/symplectic/pauli_list.py +1242 -0
- qiskit/quantum_info/operators/symplectic/pauli_utils.py +40 -0
- qiskit/quantum_info/operators/symplectic/random.py +117 -0
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +1239 -0
- qiskit/quantum_info/operators/utils/__init__.py +20 -0
- qiskit/quantum_info/operators/utils/anti_commutator.py +36 -0
- qiskit/quantum_info/operators/utils/commutator.py +36 -0
- qiskit/quantum_info/operators/utils/double_commutator.py +76 -0
- qiskit/quantum_info/quaternion.py +156 -0
- qiskit/quantum_info/random.py +26 -0
- qiskit/quantum_info/states/__init__.py +28 -0
- qiskit/quantum_info/states/densitymatrix.py +857 -0
- qiskit/quantum_info/states/measures.py +288 -0
- qiskit/quantum_info/states/quantum_state.py +503 -0
- qiskit/quantum_info/states/random.py +157 -0
- qiskit/quantum_info/states/stabilizerstate.py +805 -0
- qiskit/quantum_info/states/statevector.py +977 -0
- qiskit/quantum_info/states/utils.py +247 -0
- qiskit/result/__init__.py +61 -0
- qiskit/result/counts.py +189 -0
- qiskit/result/distributions/__init__.py +17 -0
- qiskit/result/distributions/probability.py +100 -0
- qiskit/result/distributions/quasi.py +154 -0
- qiskit/result/exceptions.py +40 -0
- qiskit/result/models.py +241 -0
- qiskit/result/postprocess.py +239 -0
- qiskit/result/result.py +385 -0
- qiskit/result/sampled_expval.py +74 -0
- qiskit/result/utils.py +294 -0
- qiskit/synthesis/__init__.py +240 -0
- qiskit/synthesis/arithmetic/__init__.py +18 -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/comparators/__init__.py +16 -0
- qiskit/synthesis/arithmetic/comparators/compare_2s.py +112 -0
- qiskit/synthesis/arithmetic/comparators/compare_greedy.py +66 -0
- qiskit/synthesis/arithmetic/multipliers/__init__.py +16 -0
- qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +103 -0
- qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +100 -0
- qiskit/synthesis/arithmetic/weighted_sum.py +155 -0
- qiskit/synthesis/boolean/__init__.py +13 -0
- qiskit/synthesis/boolean/boolean_expression.py +231 -0
- qiskit/synthesis/boolean/boolean_expression_synth.py +124 -0
- qiskit/synthesis/boolean/boolean_expression_visitor.py +96 -0
- qiskit/synthesis/clifford/__init__.py +19 -0
- qiskit/synthesis/clifford/clifford_decompose_ag.py +178 -0
- qiskit/synthesis/clifford/clifford_decompose_bm.py +46 -0
- qiskit/synthesis/clifford/clifford_decompose_full.py +64 -0
- qiskit/synthesis/clifford/clifford_decompose_greedy.py +58 -0
- qiskit/synthesis/clifford/clifford_decompose_layers.py +447 -0
- qiskit/synthesis/cnotdihedral/__init__.py +17 -0
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +52 -0
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +141 -0
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_two_qubits.py +266 -0
- qiskit/synthesis/discrete_basis/__init__.py +16 -0
- qiskit/synthesis/discrete_basis/commutator_decompose.py +265 -0
- qiskit/synthesis/discrete_basis/gate_sequence.py +421 -0
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +165 -0
- qiskit/synthesis/discrete_basis/solovay_kitaev.py +240 -0
- qiskit/synthesis/evolution/__init__.py +21 -0
- qiskit/synthesis/evolution/evolution_synthesis.py +48 -0
- qiskit/synthesis/evolution/lie_trotter.py +120 -0
- qiskit/synthesis/evolution/matrix_synthesis.py +47 -0
- qiskit/synthesis/evolution/pauli_network.py +80 -0
- qiskit/synthesis/evolution/product_formula.py +313 -0
- qiskit/synthesis/evolution/qdrift.py +130 -0
- qiskit/synthesis/evolution/suzuki_trotter.py +224 -0
- qiskit/synthesis/linear/__init__.py +26 -0
- qiskit/synthesis/linear/cnot_synth.py +69 -0
- qiskit/synthesis/linear/linear_circuits_utils.py +128 -0
- qiskit/synthesis/linear/linear_depth_lnn.py +61 -0
- qiskit/synthesis/linear/linear_matrix_utils.py +27 -0
- qiskit/synthesis/linear_phase/__init__.py +17 -0
- qiskit/synthesis/linear_phase/cnot_phase_synth.py +206 -0
- qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +61 -0
- qiskit/synthesis/linear_phase/cz_depth_lnn.py +58 -0
- qiskit/synthesis/multi_controlled/__init__.py +25 -0
- qiskit/synthesis/multi_controlled/mcmt_vchain.py +52 -0
- qiskit/synthesis/multi_controlled/mcx_synthesis.py +359 -0
- qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +206 -0
- qiskit/synthesis/one_qubit/__init__.py +15 -0
- qiskit/synthesis/one_qubit/one_qubit_decompose.py +288 -0
- qiskit/synthesis/permutation/__init__.py +18 -0
- qiskit/synthesis/permutation/permutation_full.py +78 -0
- qiskit/synthesis/permutation/permutation_lnn.py +54 -0
- qiskit/synthesis/permutation/permutation_reverse_lnn.py +93 -0
- qiskit/synthesis/permutation/permutation_utils.py +16 -0
- qiskit/synthesis/qft/__init__.py +16 -0
- qiskit/synthesis/qft/qft_decompose_full.py +97 -0
- qiskit/synthesis/qft/qft_decompose_lnn.py +79 -0
- qiskit/synthesis/stabilizer/__init__.py +16 -0
- qiskit/synthesis/stabilizer/stabilizer_circuit.py +149 -0
- qiskit/synthesis/stabilizer/stabilizer_decompose.py +194 -0
- qiskit/synthesis/two_qubit/__init__.py +20 -0
- qiskit/synthesis/two_qubit/local_invariance.py +63 -0
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +583 -0
- qiskit/synthesis/two_qubit/xx_decompose/__init__.py +19 -0
- qiskit/synthesis/two_qubit/xx_decompose/circuits.py +300 -0
- qiskit/synthesis/two_qubit/xx_decompose/decomposer.py +324 -0
- qiskit/synthesis/two_qubit/xx_decompose/embodiments.py +163 -0
- qiskit/synthesis/two_qubit/xx_decompose/paths.py +412 -0
- qiskit/synthesis/two_qubit/xx_decompose/polytopes.py +262 -0
- qiskit/synthesis/two_qubit/xx_decompose/utilities.py +40 -0
- qiskit/synthesis/two_qubit/xx_decompose/weyl.py +133 -0
- qiskit/synthesis/unitary/__init__.py +13 -0
- qiskit/synthesis/unitary/aqc/__init__.py +177 -0
- qiskit/synthesis/unitary/aqc/approximate.py +116 -0
- qiskit/synthesis/unitary/aqc/aqc.py +175 -0
- qiskit/synthesis/unitary/aqc/cnot_structures.py +300 -0
- qiskit/synthesis/unitary/aqc/cnot_unit_circuit.py +103 -0
- qiskit/synthesis/unitary/aqc/cnot_unit_objective.py +299 -0
- qiskit/synthesis/unitary/aqc/elementary_operations.py +108 -0
- qiskit/synthesis/unitary/aqc/fast_gradient/__init__.py +164 -0
- qiskit/synthesis/unitary/aqc/fast_gradient/fast_grad_utils.py +237 -0
- qiskit/synthesis/unitary/aqc/fast_gradient/fast_gradient.py +226 -0
- qiskit/synthesis/unitary/aqc/fast_gradient/layer.py +370 -0
- qiskit/synthesis/unitary/aqc/fast_gradient/pmatrix.py +312 -0
- qiskit/synthesis/unitary/qsd.py +288 -0
- qiskit/transpiler/__init__.py +1345 -0
- qiskit/transpiler/basepasses.py +190 -0
- qiskit/transpiler/coupling.py +500 -0
- qiskit/transpiler/exceptions.py +59 -0
- qiskit/transpiler/instruction_durations.py +281 -0
- qiskit/transpiler/layout.py +740 -0
- qiskit/transpiler/passes/__init__.py +276 -0
- qiskit/transpiler/passes/analysis/__init__.py +23 -0
- qiskit/transpiler/passes/analysis/count_ops.py +30 -0
- qiskit/transpiler/passes/analysis/count_ops_longest_path.py +26 -0
- qiskit/transpiler/passes/analysis/dag_longest_path.py +24 -0
- qiskit/transpiler/passes/analysis/depth.py +33 -0
- qiskit/transpiler/passes/analysis/num_qubits.py +26 -0
- qiskit/transpiler/passes/analysis/num_tensor_factors.py +26 -0
- qiskit/transpiler/passes/analysis/resource_estimation.py +41 -0
- qiskit/transpiler/passes/analysis/size.py +36 -0
- qiskit/transpiler/passes/analysis/width.py +27 -0
- qiskit/transpiler/passes/basis/__init__.py +19 -0
- qiskit/transpiler/passes/basis/basis_translator.py +138 -0
- qiskit/transpiler/passes/basis/decompose.py +137 -0
- qiskit/transpiler/passes/basis/translate_parameterized.py +175 -0
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +84 -0
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +110 -0
- qiskit/transpiler/passes/layout/__init__.py +26 -0
- qiskit/transpiler/passes/layout/_csp_custom_solver.py +65 -0
- qiskit/transpiler/passes/layout/apply_layout.py +128 -0
- qiskit/transpiler/passes/layout/csp_layout.py +132 -0
- qiskit/transpiler/passes/layout/dense_layout.py +177 -0
- qiskit/transpiler/passes/layout/disjoint_utils.py +219 -0
- qiskit/transpiler/passes/layout/enlarge_with_ancilla.py +49 -0
- qiskit/transpiler/passes/layout/full_ancilla_allocation.py +116 -0
- qiskit/transpiler/passes/layout/layout_2q_distance.py +77 -0
- qiskit/transpiler/passes/layout/sabre_layout.py +506 -0
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +225 -0
- qiskit/transpiler/passes/layout/set_layout.py +69 -0
- qiskit/transpiler/passes/layout/trivial_layout.py +66 -0
- qiskit/transpiler/passes/layout/vf2_layout.py +256 -0
- qiskit/transpiler/passes/layout/vf2_post_layout.py +376 -0
- qiskit/transpiler/passes/layout/vf2_utils.py +235 -0
- qiskit/transpiler/passes/optimization/__init__.py +42 -0
- qiskit/transpiler/passes/optimization/_gate_extension.py +80 -0
- qiskit/transpiler/passes/optimization/collect_1q_runs.py +31 -0
- qiskit/transpiler/passes/optimization/collect_2q_blocks.py +35 -0
- qiskit/transpiler/passes/optimization/collect_and_collapse.py +117 -0
- qiskit/transpiler/passes/optimization/collect_cliffords.py +109 -0
- qiskit/transpiler/passes/optimization/collect_linear_functions.py +85 -0
- qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +242 -0
- qiskit/transpiler/passes/optimization/commutation_analysis.py +44 -0
- qiskit/transpiler/passes/optimization/commutative_cancellation.py +82 -0
- qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.py +140 -0
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +176 -0
- qiskit/transpiler/passes/optimization/contract_idle_wires_in_control_flow.py +104 -0
- qiskit/transpiler/passes/optimization/elide_permutations.py +91 -0
- qiskit/transpiler/passes/optimization/hoare_opt.py +420 -0
- qiskit/transpiler/passes/optimization/inverse_cancellation.py +95 -0
- qiskit/transpiler/passes/optimization/light_cone.py +135 -0
- qiskit/transpiler/passes/optimization/optimize_1q_commutation.py +267 -0
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +250 -0
- qiskit/transpiler/passes/optimization/optimize_1q_gates.py +384 -0
- qiskit/transpiler/passes/optimization/optimize_annotated.py +449 -0
- qiskit/transpiler/passes/optimization/optimize_cliffords.py +89 -0
- qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py +71 -0
- qiskit/transpiler/passes/optimization/remove_diagonal_gates_before_measure.py +41 -0
- qiskit/transpiler/passes/optimization/remove_final_reset.py +37 -0
- qiskit/transpiler/passes/optimization/remove_identity_equiv.py +70 -0
- qiskit/transpiler/passes/optimization/remove_reset_in_zero_state.py +37 -0
- qiskit/transpiler/passes/optimization/reset_after_measure_simplification.py +50 -0
- qiskit/transpiler/passes/optimization/split_2q_unitaries.py +63 -0
- qiskit/transpiler/passes/optimization/template_matching/__init__.py +19 -0
- qiskit/transpiler/passes/optimization/template_matching/backward_match.py +749 -0
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +452 -0
- qiskit/transpiler/passes/optimization/template_matching/maximal_matches.py +77 -0
- qiskit/transpiler/passes/optimization/template_matching/template_matching.py +370 -0
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +639 -0
- qiskit/transpiler/passes/optimization/template_optimization.py +158 -0
- qiskit/transpiler/passes/routing/__init__.py +21 -0
- qiskit/transpiler/passes/routing/algorithms/__init__.py +33 -0
- qiskit/transpiler/passes/routing/algorithms/token_swapper.py +105 -0
- qiskit/transpiler/passes/routing/algorithms/types.py +46 -0
- qiskit/transpiler/passes/routing/algorithms/util.py +103 -0
- qiskit/transpiler/passes/routing/basic_swap.py +166 -0
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/__init__.py +25 -0
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_block.py +60 -0
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +397 -0
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/pauli_2q_evolution_commutation.py +145 -0
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +306 -0
- qiskit/transpiler/passes/routing/layout_transformation.py +119 -0
- qiskit/transpiler/passes/routing/lookahead_swap.py +390 -0
- qiskit/transpiler/passes/routing/sabre_swap.py +463 -0
- qiskit/transpiler/passes/routing/star_prerouting.py +408 -0
- qiskit/transpiler/passes/routing/utils.py +35 -0
- qiskit/transpiler/passes/scheduling/__init__.py +21 -0
- qiskit/transpiler/passes/scheduling/alignments/__init__.py +79 -0
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +70 -0
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +251 -0
- qiskit/transpiler/passes/scheduling/padding/__init__.py +16 -0
- qiskit/transpiler/passes/scheduling/padding/base_padding.py +284 -0
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +415 -0
- qiskit/transpiler/passes/scheduling/padding/pad_delay.py +90 -0
- qiskit/transpiler/passes/scheduling/scheduling/__init__.py +17 -0
- qiskit/transpiler/passes/scheduling/scheduling/alap.py +93 -0
- qiskit/transpiler/passes/scheduling/scheduling/asap.py +100 -0
- qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +88 -0
- qiskit/transpiler/passes/scheduling/scheduling/set_io_latency.py +64 -0
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +237 -0
- qiskit/transpiler/passes/synthesis/__init__.py +20 -0
- qiskit/transpiler/passes/synthesis/aqc_plugin.py +153 -0
- qiskit/transpiler/passes/synthesis/default_unitary_synth_plugin.py +653 -0
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +429 -0
- qiskit/transpiler/passes/synthesis/hls_plugins.py +1963 -0
- qiskit/transpiler/passes/synthesis/linear_functions_synthesis.py +41 -0
- qiskit/transpiler/passes/synthesis/plugin.py +738 -0
- qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +313 -0
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +425 -0
- qiskit/transpiler/passes/utils/__init__.py +32 -0
- qiskit/transpiler/passes/utils/barrier_before_final_measurements.py +41 -0
- qiskit/transpiler/passes/utils/check_gate_direction.py +60 -0
- qiskit/transpiler/passes/utils/check_map.py +78 -0
- qiskit/transpiler/passes/utils/contains_instruction.py +45 -0
- qiskit/transpiler/passes/utils/control_flow.py +61 -0
- qiskit/transpiler/passes/utils/dag_fixed_point.py +36 -0
- qiskit/transpiler/passes/utils/error.py +69 -0
- qiskit/transpiler/passes/utils/filter_op_nodes.py +66 -0
- qiskit/transpiler/passes/utils/fixed_point.py +48 -0
- qiskit/transpiler/passes/utils/gate_direction.py +93 -0
- qiskit/transpiler/passes/utils/gates_basis.py +51 -0
- qiskit/transpiler/passes/utils/merge_adjacent_barriers.py +163 -0
- qiskit/transpiler/passes/utils/minimum_point.py +118 -0
- qiskit/transpiler/passes/utils/remove_barriers.py +50 -0
- qiskit/transpiler/passes/utils/remove_final_measurements.py +121 -0
- qiskit/transpiler/passes/utils/unroll_forloops.py +81 -0
- qiskit/transpiler/passmanager.py +503 -0
- qiskit/transpiler/passmanager_config.py +151 -0
- qiskit/transpiler/preset_passmanagers/__init__.py +93 -0
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +993 -0
- qiskit/transpiler/preset_passmanagers/common.py +672 -0
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +437 -0
- qiskit/transpiler/preset_passmanagers/level0.py +104 -0
- qiskit/transpiler/preset_passmanagers/level1.py +108 -0
- qiskit/transpiler/preset_passmanagers/level2.py +109 -0
- qiskit/transpiler/preset_passmanagers/level3.py +110 -0
- qiskit/transpiler/preset_passmanagers/plugin.py +346 -0
- qiskit/transpiler/target.py +905 -0
- qiskit/transpiler/timing_constraints.py +59 -0
- qiskit/user_config.py +266 -0
- qiskit/utils/__init__.py +90 -0
- qiskit/utils/classtools.py +146 -0
- qiskit/utils/deprecation.py +382 -0
- qiskit/utils/lazy_tester.py +363 -0
- qiskit/utils/optionals.py +354 -0
- qiskit/utils/parallel.py +318 -0
- qiskit/utils/units.py +146 -0
- qiskit/version.py +84 -0
- qiskit/visualization/__init__.py +290 -0
- qiskit/visualization/array.py +207 -0
- qiskit/visualization/bloch.py +778 -0
- qiskit/visualization/circuit/__init__.py +15 -0
- qiskit/visualization/circuit/_utils.py +675 -0
- qiskit/visualization/circuit/circuit_visualization.py +735 -0
- qiskit/visualization/circuit/latex.py +661 -0
- qiskit/visualization/circuit/matplotlib.py +2019 -0
- qiskit/visualization/circuit/qcstyle.py +278 -0
- qiskit/visualization/circuit/styles/__init__.py +13 -0
- qiskit/visualization/circuit/styles/bw.json +202 -0
- qiskit/visualization/circuit/styles/clifford.json +202 -0
- qiskit/visualization/circuit/styles/iqp-dark.json +214 -0
- qiskit/visualization/circuit/styles/iqp.json +214 -0
- qiskit/visualization/circuit/styles/textbook.json +202 -0
- qiskit/visualization/circuit/text.py +1849 -0
- qiskit/visualization/circuit_visualization.py +19 -0
- qiskit/visualization/counts_visualization.py +487 -0
- qiskit/visualization/dag_visualization.py +318 -0
- qiskit/visualization/exceptions.py +21 -0
- qiskit/visualization/gate_map.py +1424 -0
- qiskit/visualization/library.py +40 -0
- qiskit/visualization/pass_manager_visualization.py +312 -0
- qiskit/visualization/state_visualization.py +1546 -0
- qiskit/visualization/timeline/__init__.py +21 -0
- qiskit/visualization/timeline/core.py +495 -0
- qiskit/visualization/timeline/drawings.py +260 -0
- qiskit/visualization/timeline/generators.py +506 -0
- qiskit/visualization/timeline/interface.py +444 -0
- qiskit/visualization/timeline/layouts.py +115 -0
- qiskit/visualization/timeline/plotters/__init__.py +16 -0
- qiskit/visualization/timeline/plotters/base_plotter.py +58 -0
- qiskit/visualization/timeline/plotters/matplotlib.py +195 -0
- qiskit/visualization/timeline/stylesheet.py +301 -0
- qiskit/visualization/timeline/types.py +148 -0
- qiskit/visualization/transition_visualization.py +369 -0
- qiskit/visualization/utils.py +49 -0
- qiskit-2.0.3.dist-info/METADATA +220 -0
- qiskit-2.0.3.dist-info/RECORD +690 -0
- qiskit-2.0.3.dist-info/WHEEL +6 -0
- qiskit-2.0.3.dist-info/entry_points.txt +82 -0
- qiskit-2.0.3.dist-info/licenses/LICENSE.txt +203 -0
- qiskit-2.0.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,408 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2023.
|
4
|
+
#
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
+
#
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
11
|
+
# that they have been altered from the originals.
|
12
|
+
|
13
|
+
"""Search for star connectivity patterns and replace them with."""
|
14
|
+
import itertools
|
15
|
+
from typing import Iterable, Union, Optional, List, Tuple
|
16
|
+
from math import floor, log10
|
17
|
+
|
18
|
+
from qiskit.circuit import SwitchCaseOp, Clbit, ClassicalRegister, Barrier
|
19
|
+
from qiskit.circuit.controlflow import condition_resources, node_resources
|
20
|
+
from qiskit.dagcircuit import (
|
21
|
+
DAGOpNode,
|
22
|
+
DAGDepNode,
|
23
|
+
DAGDependency,
|
24
|
+
DAGCircuit,
|
25
|
+
DAGOutNode,
|
26
|
+
DAGInNode,
|
27
|
+
)
|
28
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
29
|
+
from qiskit.transpiler.layout import Layout
|
30
|
+
from qiskit.transpiler.passes.routing.sabre_swap import _build_sabre_dag, _apply_sabre_result
|
31
|
+
|
32
|
+
from qiskit._accelerate import star_prerouting
|
33
|
+
from qiskit._accelerate.nlayout import NLayout
|
34
|
+
|
35
|
+
|
36
|
+
class StarBlock:
|
37
|
+
"""Defines blocks representing star-shaped pieces of a circuit."""
|
38
|
+
|
39
|
+
def __init__(self, nodes=None, center=None, num2q=0):
|
40
|
+
self.center = center
|
41
|
+
self.num2q = num2q
|
42
|
+
self.nodes = [] if nodes is None else nodes
|
43
|
+
|
44
|
+
def get_nodes(self):
|
45
|
+
"""Returns the list of nodes used in the block."""
|
46
|
+
return self.nodes
|
47
|
+
|
48
|
+
def append_node(self, node):
|
49
|
+
"""
|
50
|
+
If node can be added to block while keeping the block star-shaped, and
|
51
|
+
return True. Otherwise, does not add node to block and returns False.
|
52
|
+
"""
|
53
|
+
|
54
|
+
added = False
|
55
|
+
|
56
|
+
if len(node.qargs) == 1:
|
57
|
+
self.nodes.append(node)
|
58
|
+
added = True
|
59
|
+
elif self.center is None:
|
60
|
+
self.center = set(node.qargs)
|
61
|
+
self.nodes.append(node)
|
62
|
+
self.num2q += 1
|
63
|
+
added = True
|
64
|
+
elif isinstance(self.center, set):
|
65
|
+
if node.qargs[0] in self.center:
|
66
|
+
self.center = node.qargs[0]
|
67
|
+
self.nodes.append(node)
|
68
|
+
self.num2q += 1
|
69
|
+
added = True
|
70
|
+
elif node.qargs[1] in self.center:
|
71
|
+
self.center = node.qargs[1]
|
72
|
+
self.nodes.append(node)
|
73
|
+
self.num2q += 1
|
74
|
+
added = True
|
75
|
+
else:
|
76
|
+
if self.center in node.qargs:
|
77
|
+
self.nodes.append(node)
|
78
|
+
self.num2q += 1
|
79
|
+
added = True
|
80
|
+
|
81
|
+
return added
|
82
|
+
|
83
|
+
def size(self):
|
84
|
+
"""
|
85
|
+
Returns the number of two-qubit quantum gates in this block.
|
86
|
+
"""
|
87
|
+
return self.num2q
|
88
|
+
|
89
|
+
|
90
|
+
class StarPreRouting(TransformationPass):
|
91
|
+
"""Run star to linear pre-routing
|
92
|
+
|
93
|
+
This pass is a logical optimization pass that rewrites any
|
94
|
+
solely 2q gate star connectivity subcircuit as a linear connectivity
|
95
|
+
equivalent with swaps.
|
96
|
+
|
97
|
+
For example:
|
98
|
+
|
99
|
+
.. plot::
|
100
|
+
:alt: Circuit diagram output by the previous code.
|
101
|
+
:include-source:
|
102
|
+
|
103
|
+
from qiskit.circuit import QuantumCircuit
|
104
|
+
from qiskit.transpiler.passes import StarPreRouting
|
105
|
+
|
106
|
+
qc = QuantumCircuit(10)
|
107
|
+
qc.h(0)
|
108
|
+
qc.cx(0, range(1, 5))
|
109
|
+
qc.h(9)
|
110
|
+
qc.cx(9, range(8, 4, -1))
|
111
|
+
qc.measure_all()
|
112
|
+
StarPreRouting()(qc).draw("mpl")
|
113
|
+
|
114
|
+
This pass was inspired by a similar pass described in Section IV of:
|
115
|
+
C. Campbell et al., "Superstaq: Deep Optimization of Quantum Programs,"
|
116
|
+
2023 IEEE International Conference on Quantum Computing and Engineering (QCE),
|
117
|
+
Bellevue, WA, USA, 2023, pp. 1020-1032, doi: 10.1109/QCE57702.2023.00116.
|
118
|
+
"""
|
119
|
+
|
120
|
+
def __init__(self):
|
121
|
+
"""StarPreRouting"""
|
122
|
+
|
123
|
+
self._pending_nodes: Optional[list[Union[DAGOpNode, DAGDepNode]]] = None
|
124
|
+
self._in_degree: Optional[dict[Union[DAGOpNode, DAGDepNode], int]] = None
|
125
|
+
super().__init__()
|
126
|
+
|
127
|
+
def _setup_in_degrees(self, dag):
|
128
|
+
"""For an efficient implementation, for every node we keep the number of its
|
129
|
+
unprocessed immediate predecessors (called ``_in_degree``). This ``_in_degree``
|
130
|
+
is set up at the start and updated throughout the algorithm.
|
131
|
+
A node is leaf (or input) node iff its ``_in_degree`` is 0.
|
132
|
+
When a node is (marked as) collected, the ``_in_degree`` of each of its immediate
|
133
|
+
successor is updated by subtracting 1.
|
134
|
+
Additionally, ``_pending_nodes`` explicitly keeps the list of nodes whose
|
135
|
+
``_in_degree`` is 0.
|
136
|
+
"""
|
137
|
+
self._pending_nodes = []
|
138
|
+
self._in_degree = {}
|
139
|
+
for node in self._op_nodes(dag):
|
140
|
+
deg = len(self._direct_preds(dag, node))
|
141
|
+
self._in_degree[node] = deg
|
142
|
+
if deg == 0:
|
143
|
+
self._pending_nodes.append(node)
|
144
|
+
|
145
|
+
def _op_nodes(self, dag) -> Iterable[Union[DAGOpNode, DAGDepNode]]:
|
146
|
+
"""Returns DAG nodes."""
|
147
|
+
if not isinstance(dag, DAGDependency):
|
148
|
+
return dag.op_nodes()
|
149
|
+
else:
|
150
|
+
return dag.get_nodes()
|
151
|
+
|
152
|
+
def _direct_preds(self, dag, node):
|
153
|
+
"""Returns direct predecessors of a node. This function takes into account the
|
154
|
+
direction of collecting blocks, that is node's predecessors when collecting
|
155
|
+
backwards are the direct successors of a node in the DAG.
|
156
|
+
"""
|
157
|
+
if not isinstance(dag, DAGDependency):
|
158
|
+
return [pred for pred in dag.predecessors(node) if isinstance(pred, DAGOpNode)]
|
159
|
+
else:
|
160
|
+
return [dag.get_node(pred_id) for pred_id in dag.direct_predecessors(node.node_id)]
|
161
|
+
|
162
|
+
def _direct_succs(self, dag, node):
|
163
|
+
"""Returns direct successors of a node. This function takes into account the
|
164
|
+
direction of collecting blocks, that is node's successors when collecting
|
165
|
+
backwards are the direct predecessors of a node in the DAG.
|
166
|
+
"""
|
167
|
+
if not isinstance(dag, DAGDependency):
|
168
|
+
return [succ for succ in dag.successors(node) if isinstance(succ, DAGOpNode)]
|
169
|
+
else:
|
170
|
+
return [dag.get_node(succ_id) for succ_id in dag.direct_successors(node.node_id)]
|
171
|
+
|
172
|
+
def _have_uncollected_nodes(self):
|
173
|
+
"""Returns whether there are uncollected (pending) nodes"""
|
174
|
+
return len(self._pending_nodes) > 0
|
175
|
+
|
176
|
+
def collect_matching_block(self, dag, filter_fn):
|
177
|
+
"""Iteratively collects the largest block of input nodes (that is, nodes with
|
178
|
+
``_in_degree`` equal to 0) that match a given filtering function.
|
179
|
+
Examples of this include collecting blocks of swap gates,
|
180
|
+
blocks of linear gates (CXs and SWAPs), blocks of Clifford gates, blocks of single-qubit gates,
|
181
|
+
blocks of two-qubit gates, etc. Here 'iteratively' means that once a node is collected,
|
182
|
+
the ``_in_degree`` of each of its immediate successor is decreased by 1, allowing more nodes
|
183
|
+
to become input and to be eligible for collecting into the current block.
|
184
|
+
Returns the block of collected nodes.
|
185
|
+
"""
|
186
|
+
unprocessed_pending_nodes = self._pending_nodes
|
187
|
+
self._pending_nodes = []
|
188
|
+
|
189
|
+
current_block = StarBlock()
|
190
|
+
|
191
|
+
# Iteratively process unprocessed_pending_nodes:
|
192
|
+
# - any node that does not match filter_fn is added to pending_nodes
|
193
|
+
# - any node that match filter_fn is added to the current_block,
|
194
|
+
# and some of its successors may be moved to unprocessed_pending_nodes.
|
195
|
+
while unprocessed_pending_nodes:
|
196
|
+
new_pending_nodes = []
|
197
|
+
for node in unprocessed_pending_nodes:
|
198
|
+
added = filter_fn(node) and current_block.append_node(node)
|
199
|
+
if added:
|
200
|
+
# update the _in_degree of node's successors
|
201
|
+
for suc in self._direct_succs(dag, node):
|
202
|
+
self._in_degree[suc] -= 1
|
203
|
+
if self._in_degree[suc] == 0:
|
204
|
+
new_pending_nodes.append(suc)
|
205
|
+
else:
|
206
|
+
self._pending_nodes.append(node)
|
207
|
+
unprocessed_pending_nodes = new_pending_nodes
|
208
|
+
|
209
|
+
return current_block
|
210
|
+
|
211
|
+
def collect_all_matching_blocks(
|
212
|
+
self,
|
213
|
+
dag,
|
214
|
+
min_block_size=2,
|
215
|
+
):
|
216
|
+
"""Collects all blocks that match a given filtering function filter_fn.
|
217
|
+
This iteratively finds the largest block that does not match filter_fn,
|
218
|
+
then the largest block that matches filter_fn, and so on, until no more uncollected
|
219
|
+
nodes remain. Intuitively, finding larger blocks of non-matching nodes helps to
|
220
|
+
find larger blocks of matching nodes later on. The option ``min_block_size``
|
221
|
+
specifies the minimum number of gates in the block for the block to be collected.
|
222
|
+
|
223
|
+
By default, blocks are collected in the direction from the inputs towards the outputs
|
224
|
+
of the circuit. The option ``collect_from_back`` allows to change this direction,
|
225
|
+
that is collect blocks from the outputs towards the inputs of the circuit.
|
226
|
+
|
227
|
+
Returns the list of matching blocks only.
|
228
|
+
"""
|
229
|
+
|
230
|
+
def filter_fn(node):
|
231
|
+
"""Specifies which nodes can be collected into star blocks."""
|
232
|
+
return (
|
233
|
+
len(node.qargs) <= 2
|
234
|
+
and len(node.cargs) == 0
|
235
|
+
and getattr(node, "condition", None) is None
|
236
|
+
and not isinstance(node.op, Barrier)
|
237
|
+
)
|
238
|
+
|
239
|
+
def not_filter_fn(node):
|
240
|
+
"""Returns the opposite of filter_fn."""
|
241
|
+
return not filter_fn(node)
|
242
|
+
|
243
|
+
# Note: the collection direction must be specified before setting in-degrees
|
244
|
+
self._setup_in_degrees(dag)
|
245
|
+
|
246
|
+
# Iteratively collect non-matching and matching blocks.
|
247
|
+
matching_blocks: list[StarBlock] = []
|
248
|
+
processing_order = []
|
249
|
+
while self._have_uncollected_nodes():
|
250
|
+
self.collect_matching_block(dag, filter_fn=not_filter_fn)
|
251
|
+
matching_block = self.collect_matching_block(dag, filter_fn=filter_fn)
|
252
|
+
if matching_block.size() >= min_block_size:
|
253
|
+
matching_blocks.append(matching_block)
|
254
|
+
processing_order.append(matching_block)
|
255
|
+
|
256
|
+
processing_order = [n for p in processing_order for n in p.nodes]
|
257
|
+
|
258
|
+
return matching_blocks, processing_order
|
259
|
+
|
260
|
+
def run(self, dag):
|
261
|
+
# Extract StarBlocks from DAGCircuit / DAGDependency / DAGDependencyV2
|
262
|
+
star_blocks, processing_order = self.determine_star_blocks_processing(dag, min_block_size=2)
|
263
|
+
|
264
|
+
if not star_blocks:
|
265
|
+
return dag
|
266
|
+
|
267
|
+
if all(b.size() < 3 for b in star_blocks):
|
268
|
+
# we only process blocks with less than 3 two-qubit gates in this pre-routing pass
|
269
|
+
# if they occur in a collection of larger stars, otherwise we consider them to be 'lines'
|
270
|
+
return dag
|
271
|
+
|
272
|
+
# Create a new DAGCircuit / DAGDependency / DAGDependencyV2, replacing each
|
273
|
+
# star block by a linear sequence of gates
|
274
|
+
new_dag, qubit_mapping = self.star_preroute(dag, star_blocks, processing_order)
|
275
|
+
|
276
|
+
# Fix output permutation -- copied from ElidePermutations
|
277
|
+
input_qubit_mapping = {qubit: index for index, qubit in enumerate(dag.qubits)}
|
278
|
+
self.property_set["original_layout"] = Layout(input_qubit_mapping)
|
279
|
+
if self.property_set["original_qubit_indices"] is None:
|
280
|
+
self.property_set["original_qubit_indices"] = input_qubit_mapping
|
281
|
+
|
282
|
+
new_layout = Layout({dag.qubits[out]: idx for idx, out in enumerate(qubit_mapping)})
|
283
|
+
if current_layout := self.property_set["virtual_permutation_layout"]:
|
284
|
+
self.property_set["virtual_permutation_layout"] = new_layout.compose(
|
285
|
+
current_layout.inverse(dag.qubits, dag.qubits), dag.qubits
|
286
|
+
)
|
287
|
+
else:
|
288
|
+
self.property_set["virtual_permutation_layout"] = new_layout
|
289
|
+
|
290
|
+
return new_dag
|
291
|
+
|
292
|
+
def determine_star_blocks_processing(
|
293
|
+
self, dag: Union[DAGCircuit, DAGDependency], min_block_size: int
|
294
|
+
) -> Tuple[List[StarBlock], Union[List[DAGOpNode], List[DAGDepNode]]]:
|
295
|
+
"""Returns star blocks in dag and the processing order of nodes within these star blocks
|
296
|
+
Args:
|
297
|
+
dag (DAGCircuit or DAGDependency): a dag on which star blocks should be determined.
|
298
|
+
min_block_size (int): minimum number of two-qubit gates in a star block.
|
299
|
+
|
300
|
+
Returns:
|
301
|
+
List[StarBlock]: a list of star blocks in the given dag
|
302
|
+
Union[List[DAGOpNode], List[DAGDepNode]]: a list of operations specifying processing order
|
303
|
+
"""
|
304
|
+
blocks, processing_order = self.collect_all_matching_blocks(
|
305
|
+
dag, min_block_size=min_block_size
|
306
|
+
)
|
307
|
+
return blocks, processing_order
|
308
|
+
|
309
|
+
def star_preroute(self, dag, blocks, processing_order):
|
310
|
+
"""Returns star blocks in dag and the processing order of nodes within these star blocks
|
311
|
+
Args:
|
312
|
+
dag (DAGCircuit or DAGDependency): a dag on which star prerouting should be performed.
|
313
|
+
blocks (List[StarBlock]): a list of star blocks in the given dag.
|
314
|
+
processing_order (Union[List[DAGOpNode], List[DAGDepNode]]): a list of operations specifying
|
315
|
+
processing order
|
316
|
+
|
317
|
+
Returns:
|
318
|
+
new_dag: a dag specifying the pre-routed circuit
|
319
|
+
qubit_mapping: the final qubit mapping after pre-routing
|
320
|
+
"""
|
321
|
+
# Convert the DAG to a SabreDAG
|
322
|
+
num_qubits = len(dag.qubits)
|
323
|
+
canonical_register = dag.qregs["q"]
|
324
|
+
current_layout = Layout.generate_trivial_layout(canonical_register)
|
325
|
+
qubit_indices = {bit: idx for idx, bit in enumerate(canonical_register)}
|
326
|
+
layout_mapping = {qubit_indices[k]: v for k, v in current_layout.get_virtual_bits().items()}
|
327
|
+
initial_layout = NLayout(layout_mapping, num_qubits, num_qubits)
|
328
|
+
sabre_dag, circuit_to_dag_dict = _build_sabre_dag(dag, num_qubits, qubit_indices)
|
329
|
+
|
330
|
+
# Extract the nodes from the blocks for the Rust representation
|
331
|
+
rust_blocks = [
|
332
|
+
(block.center is not None, _extract_nodes(block.get_nodes(), dag)) for block in blocks
|
333
|
+
]
|
334
|
+
|
335
|
+
# Determine the processing order of the nodes in the DAG for the Rust representation
|
336
|
+
int_digits = floor(log10(len(processing_order))) + 1
|
337
|
+
processing_order_index_map = {
|
338
|
+
node: f"a{index:0{int_digits}}" for index, node in enumerate(processing_order)
|
339
|
+
}
|
340
|
+
|
341
|
+
def tie_breaker_key(node):
|
342
|
+
processing_order = processing_order_index_map.get(node, None)
|
343
|
+
if processing_order is not None:
|
344
|
+
return processing_order
|
345
|
+
if isinstance(node, (DAGInNode, DAGOutNode)):
|
346
|
+
return str(node.wire)
|
347
|
+
return ",".join(
|
348
|
+
f"{dag.find_bit(q).index:04d}" for q in itertools.chain(node.qargs, node.cargs)
|
349
|
+
)
|
350
|
+
|
351
|
+
rust_processing_order = _extract_nodes(dag.topological_op_nodes(key=tie_breaker_key), dag)
|
352
|
+
|
353
|
+
# Run the star prerouting algorithm to obtain the new DAG and qubit mapping
|
354
|
+
*sabre_result, qubit_mapping = star_prerouting.star_preroute(
|
355
|
+
sabre_dag, rust_blocks, rust_processing_order
|
356
|
+
)
|
357
|
+
|
358
|
+
res_dag = _apply_sabre_result(
|
359
|
+
dag.copy_empty_like(),
|
360
|
+
dag,
|
361
|
+
sabre_result,
|
362
|
+
initial_layout,
|
363
|
+
dag.qubits,
|
364
|
+
circuit_to_dag_dict,
|
365
|
+
)
|
366
|
+
|
367
|
+
return res_dag, qubit_mapping
|
368
|
+
|
369
|
+
|
370
|
+
def _extract_nodes(nodes, dag):
|
371
|
+
"""Extract and format node information for Rust representation used in SabreDAG.
|
372
|
+
|
373
|
+
Each node is represented as a tuple containing:
|
374
|
+
- Node ID (int): The unique identifier of the node in the DAG.
|
375
|
+
- Qubit indices (list of int): Indices of qubits involved in the node's operation.
|
376
|
+
- Classical bit indices (set of int): Indices of classical bits involved in the node's operation.
|
377
|
+
- Directive flag (bool): Indicates whether the operation is a directive (True) or not (False).
|
378
|
+
|
379
|
+
Args:
|
380
|
+
nodes (list[DAGOpNode]): List of DAGOpNode objects to extract information from.
|
381
|
+
dag (DAGCircuit): DAGCircuit object containing the circuit structure.
|
382
|
+
|
383
|
+
Returns:
|
384
|
+
list of tuples: Each tuple contains information about a node in the format described above.
|
385
|
+
"""
|
386
|
+
extracted_node_info = []
|
387
|
+
for node in nodes:
|
388
|
+
qubit_indices = [dag.find_bit(qubit).index for qubit in node.qargs]
|
389
|
+
classical_bit_indices = set()
|
390
|
+
|
391
|
+
if getattr(node, "condition", None) is not None:
|
392
|
+
classical_bit_indices.update(condition_resources(node.op.condition).clbits)
|
393
|
+
|
394
|
+
if isinstance(node.op, SwitchCaseOp):
|
395
|
+
switch_case_target = node.op.target
|
396
|
+
if isinstance(switch_case_target, Clbit):
|
397
|
+
classical_bit_indices.add(switch_case_target)
|
398
|
+
elif isinstance(switch_case_target, ClassicalRegister):
|
399
|
+
classical_bit_indices.update(switch_case_target)
|
400
|
+
else: # Assume target is an expression involving classical bits
|
401
|
+
classical_bit_indices.update(node_resources(switch_case_target).clbits)
|
402
|
+
|
403
|
+
is_directive = getattr(node.op, "_directive", False)
|
404
|
+
extracted_node_info.append(
|
405
|
+
(node._node_id, qubit_indices, classical_bit_indices, is_directive)
|
406
|
+
)
|
407
|
+
|
408
|
+
return extracted_node_info
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2017, 2018.
|
4
|
+
#
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
+
#
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
11
|
+
# that they have been altered from the originals.
|
12
|
+
|
13
|
+
"""Utility functions for routing"""
|
14
|
+
|
15
|
+
from qiskit.transpiler.exceptions import TranspilerError
|
16
|
+
from .algorithms import ApproximateTokenSwapper
|
17
|
+
|
18
|
+
|
19
|
+
def get_swap_map_dag(dag, coupling_map, from_layout, to_layout, seed, trials=4):
|
20
|
+
"""Get the circuit of swaps to go from from_layout to to_layout, and the physical qubits
|
21
|
+
(integers) that the swap circuit should be applied on."""
|
22
|
+
if len(dag.qregs) != 1 or dag.qregs.get("q", None) is None:
|
23
|
+
raise TranspilerError("layout transformation runs on physical circuits only")
|
24
|
+
if len(dag.qubits) > len(coupling_map.physical_qubits):
|
25
|
+
raise TranspilerError("The layout does not match the amount of qubits in the DAG")
|
26
|
+
token_swapper = ApproximateTokenSwapper(coupling_map.graph.to_undirected(), seed)
|
27
|
+
# Find the permutation between the initial physical qubits and final physical qubits.
|
28
|
+
permutation = {
|
29
|
+
pqubit: to_layout[vqubit] for vqubit, pqubit in from_layout.get_virtual_bits().items()
|
30
|
+
}
|
31
|
+
# The mapping produced here maps physical qubit indices of the outer dag to the bits used to
|
32
|
+
# represent them in the inner map. For later composing, we actually want the opposite map.
|
33
|
+
swap_circuit, phys_to_circuit_qubits = token_swapper.permutation_circuit(permutation, trials)
|
34
|
+
circuit_to_phys = {inner: outer for outer, inner in phys_to_circuit_qubits.items()}
|
35
|
+
return swap_circuit, [circuit_to_phys[bit] for bit in swap_circuit.qubits]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2020.
|
4
|
+
#
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
+
#
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
11
|
+
# that they have been altered from the originals.
|
12
|
+
|
13
|
+
"""Module containing circuit scheduling passes."""
|
14
|
+
|
15
|
+
from .scheduling import ALAPScheduleAnalysis, ASAPScheduleAnalysis, SetIOLatency
|
16
|
+
from .time_unit_conversion import TimeUnitConversion
|
17
|
+
from .padding import PadDelay, PadDynamicalDecoupling
|
18
|
+
from .alignments import InstructionDurationCheck, ConstrainedReschedule
|
19
|
+
|
20
|
+
# For backward compatibility
|
21
|
+
from . import alignments as instruction_alignments
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2022.
|
4
|
+
#
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
+
#
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
11
|
+
# that they have been altered from the originals.
|
12
|
+
|
13
|
+
"""Validation and optimization for hardware instruction alignment constraints.
|
14
|
+
|
15
|
+
This is a control electronics aware analysis pass group.
|
16
|
+
|
17
|
+
In many quantum computing architectures gates (instructions) are implemented with
|
18
|
+
shaped analog stimulus signals. These signals are digitally stored in the
|
19
|
+
waveform memory of the control electronics and converted into analog voltage signals
|
20
|
+
by electronic components called digital to analog converters (DAC).
|
21
|
+
|
22
|
+
In a typical hardware implementation of superconducting quantum processors,
|
23
|
+
a single qubit instruction is implemented by a
|
24
|
+
microwave signal with the duration of around several tens of ns with a per-sample
|
25
|
+
time resolution of ~0.1-10ns, as reported by ``backend.configuration().dt``.
|
26
|
+
In such systems requiring higher DAC bandwidth, control electronics often
|
27
|
+
defines a `pulse granularity`, in other words a data chunk, to allow the DAC to
|
28
|
+
perform the signal conversion in parallel to gain the bandwidth.
|
29
|
+
|
30
|
+
A control electronics, i.e. micro-architecture, of the real quantum backend may
|
31
|
+
impose some constraints on the start time of microinstructions.
|
32
|
+
In Qiskit SDK, the duration of :class:`qiskit.circuit.Delay` can take arbitrary
|
33
|
+
value in units of dt, thus circuits involving delays may violate the constraints,
|
34
|
+
which may result in failure in the circuit execution on the backend.
|
35
|
+
|
36
|
+
There are two alignment constraint values reported by your quantum backend.
|
37
|
+
In addition, if you want to define a custom instruction as a pulse gate, i.e. calibration,
|
38
|
+
the underlying pulse instruction should satisfy other two waveform constraints.
|
39
|
+
|
40
|
+
Pulse alignment constraint
|
41
|
+
|
42
|
+
This value is reported by ``timing_constraints["pulse_alignment"]`` in the backend
|
43
|
+
configuration in units of dt. The start time of the all pulse instruction should be
|
44
|
+
multiple of this value. Violation of this constraint may result in the
|
45
|
+
backend execution failure.
|
46
|
+
|
47
|
+
In most of the scenarios, the scheduled start time of ``DAGOpNode`` corresponds to the
|
48
|
+
start time of the underlying pulse instruction composing the node operation.
|
49
|
+
However, this assumption can be intentionally broken by defining a pulse gate,
|
50
|
+
i.e. calibration, with the schedule involving pre-buffer, i.e. some random pulse delay
|
51
|
+
followed by a pulse instruction. Because this pass is not aware of such edge case,
|
52
|
+
the user must take special care of pulse gates if any.
|
53
|
+
|
54
|
+
Acquire alignment constraint
|
55
|
+
|
56
|
+
This value is reported by ``timing_constraints["acquire_alignment"]`` in the backend
|
57
|
+
configuration in units of dt. The start time of the :class:`~qiskit.circuit.Measure`
|
58
|
+
instruction should be multiple of this value.
|
59
|
+
|
60
|
+
Granularity constraint
|
61
|
+
|
62
|
+
This value is reported by ``timing_constraints["granularity"]`` in the backend
|
63
|
+
configuration in units of dt. This is the constraint for a single pulse :class:`Play`
|
64
|
+
instruction that may constitute your pulse gate.
|
65
|
+
The length of waveform samples should be multiple of this constraint value.
|
66
|
+
Violation of this constraint may result in failure in backend execution.
|
67
|
+
|
68
|
+
Minimum pulse length constraint
|
69
|
+
|
70
|
+
This value is reported by ``timing_constraints["min_length"]`` in the backend
|
71
|
+
configuration in units of dt. This is the constraint for a single pulse :class:`Play`
|
72
|
+
instruction that may constitute your pulse gate.
|
73
|
+
The length of waveform samples should be greater than this constraint value.
|
74
|
+
Violation of this constraint may result in failure in backend execution.
|
75
|
+
|
76
|
+
"""
|
77
|
+
|
78
|
+
from .check_durations import InstructionDurationCheck
|
79
|
+
from .reschedule import ConstrainedReschedule
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2021, 2024.
|
4
|
+
#
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
+
#
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
11
|
+
# that they have been altered from the originals.
|
12
|
+
"""A pass to check if input circuit requires reschedule."""
|
13
|
+
|
14
|
+
from qiskit.circuit.delay import Delay
|
15
|
+
from qiskit.dagcircuit import DAGCircuit
|
16
|
+
from qiskit.transpiler.basepasses import AnalysisPass
|
17
|
+
from qiskit.transpiler.target import Target
|
18
|
+
|
19
|
+
|
20
|
+
class InstructionDurationCheck(AnalysisPass):
|
21
|
+
"""Duration validation pass for reschedule.
|
22
|
+
|
23
|
+
This pass investigates the input quantum circuit and checks if the circuit requires
|
24
|
+
rescheduling for execution. Note that this pass can be triggered without scheduling.
|
25
|
+
This pass only checks the duration of delay instructions,
|
26
|
+
which report duration values without pre-scheduling.
|
27
|
+
|
28
|
+
This pass assumes backend supported instructions, i.e. basis gates, have no violation
|
29
|
+
of the hardware alignment constraints, which is true in general.
|
30
|
+
"""
|
31
|
+
|
32
|
+
def __init__(self, acquire_alignment: int = 1, pulse_alignment: int = 1, target: Target = None):
|
33
|
+
"""Create new duration validation pass.
|
34
|
+
|
35
|
+
The alignment values depend on the control electronics of your quantum processor.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
acquire_alignment: Integer number representing the minimum time resolution to
|
39
|
+
trigger acquisition instruction in units of ``dt``.
|
40
|
+
pulse_alignment: Integer number representing the minimum time resolution to
|
41
|
+
trigger gate instruction in units of ``dt``.
|
42
|
+
target: The :class:`~.Target` representing the target backend, if
|
43
|
+
``target`` is specified then this argument will take
|
44
|
+
precedence and ``acquire_alignment`` and ``pulse_alignment`` will be ignored.
|
45
|
+
"""
|
46
|
+
super().__init__()
|
47
|
+
self.acquire_align = acquire_alignment
|
48
|
+
self.pulse_align = pulse_alignment
|
49
|
+
if target is not None:
|
50
|
+
self.acquire_align = target.acquire_alignment
|
51
|
+
self.pulse_align = target.pulse_alignment
|
52
|
+
|
53
|
+
def run(self, dag: DAGCircuit):
|
54
|
+
"""Run duration validation passes.
|
55
|
+
|
56
|
+
Args:
|
57
|
+
dag: DAG circuit to check instruction durations.
|
58
|
+
"""
|
59
|
+
self.property_set["reschedule_required"] = False
|
60
|
+
|
61
|
+
# Rescheduling is not necessary
|
62
|
+
if (self.acquire_align == 1 and self.pulse_align == 1) or dag._num_stretches != 0:
|
63
|
+
return
|
64
|
+
|
65
|
+
# Check delay durations
|
66
|
+
for delay_node in dag.op_nodes(Delay):
|
67
|
+
dur = delay_node.op.duration
|
68
|
+
if not (dur % self.acquire_align == 0 and dur % self.pulse_align == 0):
|
69
|
+
self.property_set["reschedule_required"] = True
|
70
|
+
return
|