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,449 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 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
|
+
|
13
|
+
"""Optimize annotated operations on a circuit."""
|
14
|
+
|
15
|
+
from typing import Optional, List, Tuple, Union
|
16
|
+
|
17
|
+
from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES
|
18
|
+
from qiskit.converters import circuit_to_dag, dag_to_circuit
|
19
|
+
from qiskit.circuit.annotated_operation import AnnotatedOperation, _canonicalize_modifiers
|
20
|
+
from qiskit.circuit import (
|
21
|
+
QuantumCircuit,
|
22
|
+
Instruction,
|
23
|
+
EquivalenceLibrary,
|
24
|
+
ControlledGate,
|
25
|
+
Operation,
|
26
|
+
ControlFlowOp,
|
27
|
+
)
|
28
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
29
|
+
from qiskit.transpiler.passes.utils import control_flow
|
30
|
+
from qiskit.transpiler.target import Target
|
31
|
+
from qiskit.dagcircuit import DAGCircuit
|
32
|
+
from qiskit.transpiler.exceptions import TranspilerError
|
33
|
+
|
34
|
+
|
35
|
+
class OptimizeAnnotated(TransformationPass):
|
36
|
+
"""Optimization pass on circuits with annotated operations.
|
37
|
+
|
38
|
+
Implemented optimizations:
|
39
|
+
|
40
|
+
* For each annotated operation, converting the list of its modifiers to a canonical form.
|
41
|
+
For example, consecutively applying ``inverse()``, ``control(2)`` and ``inverse()``
|
42
|
+
is equivalent to applying ``control(2)``.
|
43
|
+
|
44
|
+
* Removing annotations when possible.
|
45
|
+
For example, ``AnnotatedOperation(SwapGate(), [InverseModifier(), InverseModifier()])``
|
46
|
+
is equivalent to ``SwapGate()``.
|
47
|
+
|
48
|
+
* Recursively combining annotations.
|
49
|
+
For example, if ``g1 = AnnotatedOperation(SwapGate(), InverseModifier())`` and
|
50
|
+
``g2 = AnnotatedOperation(g1, ControlModifier(2))``, then ``g2`` can be replaced with
|
51
|
+
``AnnotatedOperation(SwapGate(), [InverseModifier(), ControlModifier(2)])``.
|
52
|
+
|
53
|
+
* Applies conjugate reduction to annotated operations. As an example,
|
54
|
+
``control - [P -- Q -- P^{-1}]`` can be rewritten as ``P -- control - [Q] -- P^{-1}``,
|
55
|
+
that is, only the middle part needs to be controlled. This also works for inverse
|
56
|
+
and power modifiers.
|
57
|
+
|
58
|
+
"""
|
59
|
+
|
60
|
+
def __init__(
|
61
|
+
self,
|
62
|
+
target: Optional[Target] = None,
|
63
|
+
equivalence_library: Optional[EquivalenceLibrary] = None,
|
64
|
+
basis_gates: Optional[List[str]] = None,
|
65
|
+
recurse: bool = True,
|
66
|
+
do_conjugate_reduction: bool = True,
|
67
|
+
):
|
68
|
+
"""
|
69
|
+
OptimizeAnnotated initializer.
|
70
|
+
|
71
|
+
Args:
|
72
|
+
target: Optional, the backend target to use for this pass.
|
73
|
+
equivalence_library: The equivalence library used
|
74
|
+
(instructions in this library will not be optimized by this pass).
|
75
|
+
basis_gates: Optional, target basis names to unroll to, e.g. `['u3', 'cx']`
|
76
|
+
(instructions in this list will not be optimized by this pass).
|
77
|
+
Ignored if ``target`` is also specified.
|
78
|
+
recurse: By default, when either ``target`` or ``basis_gates`` is specified,
|
79
|
+
the pass recursively descends into gate definitions (and the recursion is
|
80
|
+
not applied when neither is specified since such objects do not need to
|
81
|
+
be synthesized). Setting this value to ``False`` precludes the recursion in
|
82
|
+
every case.
|
83
|
+
do_conjugate_reduction: controls whether conjugate reduction should be performed.
|
84
|
+
"""
|
85
|
+
super().__init__()
|
86
|
+
|
87
|
+
self._target = target
|
88
|
+
self._equiv_lib = equivalence_library
|
89
|
+
self._basis_gates = basis_gates
|
90
|
+
self._do_conjugate_reduction = do_conjugate_reduction
|
91
|
+
|
92
|
+
self._top_level_only = not recurse or (self._basis_gates is None and self._target is None)
|
93
|
+
|
94
|
+
if not self._top_level_only and self._target is None:
|
95
|
+
basic_insts = {"measure", "reset", "barrier", "snapshot", "delay", "store"}
|
96
|
+
self._device_insts = basic_insts | set(self._basis_gates)
|
97
|
+
|
98
|
+
def run(self, dag: DAGCircuit):
|
99
|
+
"""Run the OptimizeAnnotated pass on `dag`.
|
100
|
+
|
101
|
+
Args:
|
102
|
+
dag: input dag.
|
103
|
+
|
104
|
+
Returns:
|
105
|
+
Output dag with higher-level operations optimized.
|
106
|
+
|
107
|
+
Raises:
|
108
|
+
TranspilerError: when something goes wrong.
|
109
|
+
|
110
|
+
"""
|
111
|
+
dag, _ = self._run_inner(dag)
|
112
|
+
return dag
|
113
|
+
|
114
|
+
def _run_inner(self, dag) -> Tuple[DAGCircuit, bool]:
|
115
|
+
"""
|
116
|
+
Optimizes annotated operations.
|
117
|
+
Returns True if did something.
|
118
|
+
"""
|
119
|
+
# Fast return
|
120
|
+
if self._top_level_only:
|
121
|
+
op_names = dag.count_ops(recurse=False)
|
122
|
+
if "annotated" not in op_names and not CONTROL_FLOW_OP_NAMES.intersection(op_names):
|
123
|
+
return dag, False
|
124
|
+
|
125
|
+
# Handle control-flow
|
126
|
+
for node in dag.op_nodes():
|
127
|
+
if isinstance(node.op, ControlFlowOp):
|
128
|
+
dag.substitute_node(
|
129
|
+
node,
|
130
|
+
control_flow.map_blocks(self.run, node.op),
|
131
|
+
)
|
132
|
+
|
133
|
+
# First, optimize every node in the DAG.
|
134
|
+
dag, opt1 = self._canonicalize(dag)
|
135
|
+
|
136
|
+
opt2 = False
|
137
|
+
if not self._top_level_only:
|
138
|
+
# Second, recursively descend into definitions.
|
139
|
+
# Note that it is important to recurse only after the optimization methods have been run,
|
140
|
+
# as they may remove annotated gates.
|
141
|
+
dag, opt2 = self._recurse(dag)
|
142
|
+
|
143
|
+
opt3 = False
|
144
|
+
if not self._top_level_only and self._do_conjugate_reduction:
|
145
|
+
dag, opt3 = self._conjugate_reduction(dag)
|
146
|
+
|
147
|
+
return dag, opt1 or opt2 or opt3
|
148
|
+
|
149
|
+
def _canonicalize(self, dag) -> Tuple[DAGCircuit, bool]:
|
150
|
+
"""
|
151
|
+
Combines recursive annotated operations and canonicalizes modifiers.
|
152
|
+
Returns True if did something.
|
153
|
+
"""
|
154
|
+
|
155
|
+
did_something = False
|
156
|
+
for node in dag.op_nodes(op=AnnotatedOperation):
|
157
|
+
modifiers = []
|
158
|
+
cur = node.op
|
159
|
+
while isinstance(cur, AnnotatedOperation):
|
160
|
+
modifiers.extend(cur.modifiers)
|
161
|
+
cur = cur.base_op
|
162
|
+
canonical_modifiers = _canonicalize_modifiers(modifiers)
|
163
|
+
if len(canonical_modifiers) > 0:
|
164
|
+
# this is still an annotated operation
|
165
|
+
node.op.base_op = cur
|
166
|
+
node.op.modifiers = canonical_modifiers
|
167
|
+
else:
|
168
|
+
# no need for annotated operations
|
169
|
+
dag.substitute_node(node, cur)
|
170
|
+
did_something = True
|
171
|
+
return dag, did_something
|
172
|
+
|
173
|
+
def _conjugate_decomposition(
|
174
|
+
self, dag: DAGCircuit
|
175
|
+
) -> Union[Tuple[DAGCircuit, DAGCircuit, DAGCircuit], None]:
|
176
|
+
"""
|
177
|
+
Decomposes a circuit ``A`` into 3 sub-circuits ``P``, ``Q``, ``R`` such that
|
178
|
+
``A = P -- Q -- R`` and ``R = P^{-1}``.
|
179
|
+
|
180
|
+
This is accomplished by iteratively finding inverse nodes at the front and at the back of the
|
181
|
+
circuit.
|
182
|
+
"""
|
183
|
+
|
184
|
+
front_block = [] # nodes collected from the front of the circuit (aka P)
|
185
|
+
back_block = [] # nodes collected from the back of the circuit (aka R)
|
186
|
+
|
187
|
+
# Stores in- and out- degree for each node. These degrees are computed at the start of this
|
188
|
+
# function and are updated when nodes are collected into front_block or into back_block.
|
189
|
+
in_degree = {}
|
190
|
+
out_degree = {}
|
191
|
+
|
192
|
+
# We use dicts to track for each qubit a DAG node at the front of the circuit that involves
|
193
|
+
# this qubit and a DAG node at the end of the circuit that involves this qubit (when exist).
|
194
|
+
# Note that for the DAGCircuit structure for each qubit there can be at most one such front
|
195
|
+
# and such back node.
|
196
|
+
# This allows for an efficient way to find an inverse pair of gates (one from the front and
|
197
|
+
# one from the back of the circuit).
|
198
|
+
# A qubit that was never examined does not appear in these dicts, and a qubit that was examined
|
199
|
+
# but currently is not involved at the front (resp. at the back) of the circuit has the value of
|
200
|
+
# None.
|
201
|
+
front_node_for_qubit = {}
|
202
|
+
back_node_for_qubit = {}
|
203
|
+
|
204
|
+
# Keep the set of nodes that have been moved either to front_block or to back_block
|
205
|
+
processed_nodes = set()
|
206
|
+
|
207
|
+
# Keep the set of qubits that are involved in nodes at the front or at the back of the circuit.
|
208
|
+
# When looking for inverse pairs of gates we will only iterate over these qubits.
|
209
|
+
active_qubits = set()
|
210
|
+
|
211
|
+
# Keep pairs of nodes for which the inverse check was performed and the nodes
|
212
|
+
# were found to be not inverse to each other (memoization).
|
213
|
+
checked_node_pairs = set()
|
214
|
+
|
215
|
+
# compute in- and out- degree for every node
|
216
|
+
# also update information for nodes at the start and at the end of the circuit
|
217
|
+
for node in dag.op_nodes():
|
218
|
+
preds = list(dag.op_predecessors(node))
|
219
|
+
in_degree[node] = len(preds)
|
220
|
+
if len(preds) == 0:
|
221
|
+
for q in node.qargs:
|
222
|
+
front_node_for_qubit[q] = node
|
223
|
+
active_qubits.add(q)
|
224
|
+
succs = list(dag.op_successors(node))
|
225
|
+
out_degree[node] = len(succs)
|
226
|
+
if len(succs) == 0:
|
227
|
+
for q in node.qargs:
|
228
|
+
back_node_for_qubit[q] = node
|
229
|
+
active_qubits.add(q)
|
230
|
+
|
231
|
+
# iterate while there is a possibility to find more inverse pairs
|
232
|
+
while len(active_qubits) > 0:
|
233
|
+
to_check = active_qubits.copy()
|
234
|
+
active_qubits.clear()
|
235
|
+
|
236
|
+
# For each qubit q, check whether the gate at the front of the circuit that involves q
|
237
|
+
# and the gate at the end of the circuit that involves q are inverse
|
238
|
+
for q in to_check:
|
239
|
+
|
240
|
+
if (front_node := front_node_for_qubit.get(q, None)) is None:
|
241
|
+
continue
|
242
|
+
if (back_node := back_node_for_qubit.get(q, None)) is None:
|
243
|
+
continue
|
244
|
+
|
245
|
+
# front_node or back_node could be already collected when considering other qubits
|
246
|
+
if front_node in processed_nodes or back_node in processed_nodes:
|
247
|
+
continue
|
248
|
+
|
249
|
+
# it is possible that the same node is both at the front and at the back,
|
250
|
+
# it should not be collected
|
251
|
+
if front_node == back_node:
|
252
|
+
continue
|
253
|
+
|
254
|
+
# have been checked before
|
255
|
+
if (front_node, back_node) in checked_node_pairs:
|
256
|
+
continue
|
257
|
+
|
258
|
+
# fast check based on the arguments
|
259
|
+
if front_node.qargs != back_node.qargs or front_node.cargs != back_node.cargs:
|
260
|
+
continue
|
261
|
+
|
262
|
+
# in the future we want to include a more precise check whether a pair
|
263
|
+
# of nodes are inverse
|
264
|
+
if front_node.op == back_node.op.inverse():
|
265
|
+
# update front_node_for_qubit and back_node_for_qubit
|
266
|
+
for q in front_node.qargs:
|
267
|
+
front_node_for_qubit[q] = None
|
268
|
+
for q in back_node.qargs:
|
269
|
+
back_node_for_qubit[q] = None
|
270
|
+
|
271
|
+
# see which other nodes become at the front and update information
|
272
|
+
for node in dag.op_successors(front_node):
|
273
|
+
if node not in processed_nodes:
|
274
|
+
in_degree[node] -= 1
|
275
|
+
if in_degree[node] == 0:
|
276
|
+
for q in node.qargs:
|
277
|
+
front_node_for_qubit[q] = node
|
278
|
+
active_qubits.add(q)
|
279
|
+
|
280
|
+
# see which other nodes become at the back and update information
|
281
|
+
for node in dag.op_predecessors(back_node):
|
282
|
+
if node not in processed_nodes:
|
283
|
+
out_degree[node] -= 1
|
284
|
+
if out_degree[node] == 0:
|
285
|
+
for q in node.qargs:
|
286
|
+
back_node_for_qubit[q] = node
|
287
|
+
active_qubits.add(q)
|
288
|
+
|
289
|
+
# collect and mark as processed
|
290
|
+
front_block.append(front_node)
|
291
|
+
back_block.append(back_node)
|
292
|
+
processed_nodes.add(front_node)
|
293
|
+
processed_nodes.add(back_node)
|
294
|
+
|
295
|
+
else:
|
296
|
+
checked_node_pairs.add((front_node, back_node))
|
297
|
+
|
298
|
+
# if nothing is found, return None
|
299
|
+
if len(front_block) == 0:
|
300
|
+
return None
|
301
|
+
|
302
|
+
# create the output DAGs
|
303
|
+
front_circuit = dag.copy_empty_like()
|
304
|
+
middle_circuit = dag.copy_empty_like()
|
305
|
+
back_circuit = dag.copy_empty_like()
|
306
|
+
front_circuit.global_phase = 0
|
307
|
+
back_circuit.global_phase = 0
|
308
|
+
|
309
|
+
for node in front_block:
|
310
|
+
front_circuit.apply_operation_back(node.op, node.qargs, node.cargs)
|
311
|
+
|
312
|
+
for node in back_block:
|
313
|
+
back_circuit.apply_operation_front(node.op, node.qargs, node.cargs)
|
314
|
+
|
315
|
+
for node in dag.op_nodes():
|
316
|
+
if node not in processed_nodes:
|
317
|
+
middle_circuit.apply_operation_back(node.op, node.qargs, node.cargs)
|
318
|
+
|
319
|
+
return front_circuit, middle_circuit, back_circuit
|
320
|
+
|
321
|
+
def _conjugate_reduce_op(
|
322
|
+
self, op: AnnotatedOperation, base_decomposition: Tuple[DAGCircuit, DAGCircuit, DAGCircuit]
|
323
|
+
) -> Operation:
|
324
|
+
"""
|
325
|
+
We are given an annotated-operation ``op = M [ B ]`` (where ``B`` is the base operation and
|
326
|
+
``M`` is the list of modifiers) and the "conjugate decomposition" of the definition of ``B``,
|
327
|
+
i.e. ``B = P * Q * R``, with ``R = P^{-1}`` (with ``P``, ``Q`` and ``R`` represented as
|
328
|
+
``DAGCircuit`` objects).
|
329
|
+
|
330
|
+
Let ``IQ`` denote a new custom instruction with definitions ``Q``.
|
331
|
+
|
332
|
+
We return the operation ``op_new`` which a new custom instruction with definition
|
333
|
+
``P * A * R``, where ``A`` is a new annotated-operation with modifiers ``M`` and
|
334
|
+
base gate ``IQ``.
|
335
|
+
"""
|
336
|
+
p_dag, q_dag, r_dag = base_decomposition
|
337
|
+
|
338
|
+
q_instr = Instruction(
|
339
|
+
name="iq", num_qubits=op.base_op.num_qubits, num_clbits=op.base_op.num_clbits, params=[]
|
340
|
+
)
|
341
|
+
q_instr.definition = dag_to_circuit(q_dag)
|
342
|
+
|
343
|
+
op_new = Instruction(
|
344
|
+
"optimized", num_qubits=op.num_qubits, num_clbits=op.num_clbits, params=[]
|
345
|
+
)
|
346
|
+
num_control_qubits = op.num_qubits - op.base_op.num_qubits
|
347
|
+
|
348
|
+
circ = QuantumCircuit(op.num_qubits, op.num_clbits)
|
349
|
+
qubits = circ.qubits
|
350
|
+
circ.compose(
|
351
|
+
dag_to_circuit(p_dag), qubits[num_control_qubits : op.num_qubits], inplace=True
|
352
|
+
)
|
353
|
+
circ.append(
|
354
|
+
AnnotatedOperation(base_op=q_instr, modifiers=op.modifiers), range(op.num_qubits)
|
355
|
+
)
|
356
|
+
circ.compose(
|
357
|
+
dag_to_circuit(r_dag), qubits[num_control_qubits : op.num_qubits], inplace=True
|
358
|
+
)
|
359
|
+
op_new.definition = circ
|
360
|
+
return op_new
|
361
|
+
|
362
|
+
def _conjugate_reduction(self, dag) -> Tuple[DAGCircuit, bool]:
|
363
|
+
"""
|
364
|
+
Looks for annotated operations whose base operation has a nontrivial conjugate decomposition.
|
365
|
+
In such cases, the modifiers of the annotated operation can be moved to the "middle" part of
|
366
|
+
the decomposition.
|
367
|
+
|
368
|
+
Returns the modified DAG and whether it did something.
|
369
|
+
"""
|
370
|
+
did_something = False
|
371
|
+
for node in dag.op_nodes(op=AnnotatedOperation):
|
372
|
+
base_op = node.op.base_op
|
373
|
+
if not self._skip_definition(base_op):
|
374
|
+
base_dag = circuit_to_dag(base_op.definition, copy_operations=False)
|
375
|
+
base_decomposition = self._conjugate_decomposition(base_dag)
|
376
|
+
if base_decomposition is not None:
|
377
|
+
new_op = self._conjugate_reduce_op(node.op, base_decomposition)
|
378
|
+
dag.substitute_node(node, new_op)
|
379
|
+
did_something = True
|
380
|
+
return dag, did_something
|
381
|
+
|
382
|
+
def _skip_definition(self, op: Operation) -> bool:
|
383
|
+
"""
|
384
|
+
Returns True if we should not recurse into a gate's definition.
|
385
|
+
"""
|
386
|
+
# Similar to HighLevelSynthesis transpiler pass, we do not recurse into a gate's
|
387
|
+
# `definition` for a gate that is supported by the target or in equivalence library.
|
388
|
+
|
389
|
+
controlled_gate_open_ctrl = isinstance(op, ControlledGate) and op._open_ctrl
|
390
|
+
if not controlled_gate_open_ctrl:
|
391
|
+
inst_supported = (
|
392
|
+
self._target.instruction_supported(operation_name=op.name)
|
393
|
+
if self._target is not None
|
394
|
+
else op.name in self._device_insts
|
395
|
+
)
|
396
|
+
if inst_supported or (self._equiv_lib is not None and self._equiv_lib.has_entry(op)):
|
397
|
+
return True
|
398
|
+
return False
|
399
|
+
|
400
|
+
def _recursively_process_definitions(self, op: Operation) -> bool:
|
401
|
+
"""
|
402
|
+
Recursively applies optimizations to op's definition (or to op.base_op's
|
403
|
+
definition if op is an annotated operation).
|
404
|
+
Returns True if did something.
|
405
|
+
"""
|
406
|
+
|
407
|
+
# If op is an annotated operation, we descend into its base_op
|
408
|
+
if isinstance(op, AnnotatedOperation):
|
409
|
+
return self._recursively_process_definitions(op.base_op)
|
410
|
+
|
411
|
+
if self._skip_definition(op):
|
412
|
+
return False
|
413
|
+
|
414
|
+
try:
|
415
|
+
# extract definition
|
416
|
+
definition = op.definition
|
417
|
+
except TypeError as err:
|
418
|
+
raise TranspilerError(
|
419
|
+
f"OptimizeAnnotated was unable to extract definition for {op.name}: {err}"
|
420
|
+
) from err
|
421
|
+
except AttributeError:
|
422
|
+
# definition is None
|
423
|
+
definition = None
|
424
|
+
|
425
|
+
if definition is None:
|
426
|
+
raise TranspilerError(f"OptimizeAnnotated was unable to optimize {op}.")
|
427
|
+
|
428
|
+
definition_dag = circuit_to_dag(definition, copy_operations=False)
|
429
|
+
definition_dag, opt = self._run_inner(definition_dag)
|
430
|
+
|
431
|
+
if opt:
|
432
|
+
# We only update a gate's definition if it was actually changed.
|
433
|
+
# This is important to preserve non-annotated singleton gates.
|
434
|
+
op.definition = dag_to_circuit(definition_dag)
|
435
|
+
|
436
|
+
return opt
|
437
|
+
|
438
|
+
def _recurse(self, dag) -> Tuple[DAGCircuit, bool]:
|
439
|
+
"""
|
440
|
+
Recursively handles gate definitions.
|
441
|
+
Returns True if did something.
|
442
|
+
"""
|
443
|
+
did_something = False
|
444
|
+
|
445
|
+
for node in dag.op_nodes():
|
446
|
+
opt = self._recursively_process_definitions(node.op)
|
447
|
+
did_something = did_something or opt
|
448
|
+
|
449
|
+
return dag, did_something
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2017, 2021.
|
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
|
+
"""Combine consecutive Cliffords over the same qubits."""
|
14
|
+
|
15
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
16
|
+
from qiskit.transpiler.passes.utils import control_flow
|
17
|
+
from qiskit.quantum_info.operators import Clifford
|
18
|
+
|
19
|
+
|
20
|
+
class OptimizeCliffords(TransformationPass):
|
21
|
+
"""Combine consecutive Cliffords over the same qubits.
|
22
|
+
This serves as an example of extra capabilities enabled by storing
|
23
|
+
Cliffords natively on the circuit.
|
24
|
+
"""
|
25
|
+
|
26
|
+
@control_flow.trivial_recurse
|
27
|
+
def run(self, dag):
|
28
|
+
"""Run the OptimizeCliffords pass on `dag`.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
dag (DAGCircuit): the DAG to be optimized.
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
DAGCircuit: the optimized DAG.
|
35
|
+
"""
|
36
|
+
|
37
|
+
blocks = []
|
38
|
+
prev_node = None
|
39
|
+
cur_block = []
|
40
|
+
|
41
|
+
# Iterate over all nodes and collect consecutive Cliffords over the
|
42
|
+
# same qubits. In this very first proof-of-concept implementation
|
43
|
+
# we require the same ordering of qubits, but this restriction will
|
44
|
+
# be shortly removed. An interesting question is whether we may also
|
45
|
+
# want to compose Cliffords over different sets of qubits, such as
|
46
|
+
# cliff1 over qubits [1, 2, 3] and cliff2 over [2, 3, 4].
|
47
|
+
for node in dag.topological_op_nodes():
|
48
|
+
if isinstance(node.op, Clifford):
|
49
|
+
if prev_node is None:
|
50
|
+
blocks.append(cur_block)
|
51
|
+
cur_block = [node]
|
52
|
+
else:
|
53
|
+
if prev_node.qargs == node.qargs:
|
54
|
+
cur_block.append(node)
|
55
|
+
else:
|
56
|
+
blocks.append(cur_block)
|
57
|
+
cur_block = [node]
|
58
|
+
|
59
|
+
prev_node = node
|
60
|
+
|
61
|
+
else:
|
62
|
+
# not a clifford
|
63
|
+
if cur_block:
|
64
|
+
blocks.append(cur_block)
|
65
|
+
prev_node = None
|
66
|
+
cur_block = []
|
67
|
+
|
68
|
+
if cur_block:
|
69
|
+
blocks.append(cur_block)
|
70
|
+
|
71
|
+
# Replace every discovered block of cliffords by a single clifford
|
72
|
+
# based on the Cliffords' compose function.
|
73
|
+
for cur_nodes in blocks:
|
74
|
+
# Create clifford functions only out of blocks with at least 2 gates
|
75
|
+
if len(cur_nodes) <= 1:
|
76
|
+
continue
|
77
|
+
|
78
|
+
wire_pos_map = {qb: ix for ix, qb in enumerate(cur_nodes[0].qargs)}
|
79
|
+
|
80
|
+
# Construct a linear circuit
|
81
|
+
cliff = cur_nodes[0].op
|
82
|
+
for i, node in enumerate(cur_nodes):
|
83
|
+
if i > 0:
|
84
|
+
cliff = Clifford.compose(node.op, cliff, front=True)
|
85
|
+
|
86
|
+
# Replace the block by the composed clifford
|
87
|
+
dag.replace_block_with_op(cur_nodes, cliff, wire_pos_map, cycle_check=False)
|
88
|
+
|
89
|
+
return dag
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2017, 2019.
|
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
|
+
|
14
|
+
"""Remove the swaps followed by measurement (and adapt the measurement)."""
|
15
|
+
|
16
|
+
from qiskit.circuit import Measure
|
17
|
+
from qiskit.circuit.library.standard_gates import SwapGate
|
18
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
19
|
+
from qiskit.transpiler.passes.utils import control_flow
|
20
|
+
from qiskit.dagcircuit import DAGCircuit, DAGOpNode, DAGOutNode
|
21
|
+
|
22
|
+
|
23
|
+
class OptimizeSwapBeforeMeasure(TransformationPass):
|
24
|
+
"""Remove the swaps followed by measurement (and adapt the measurement).
|
25
|
+
|
26
|
+
Transpiler pass to remove swaps in front of measurements by re-targeting
|
27
|
+
the classical bit of the measure instruction.
|
28
|
+
"""
|
29
|
+
|
30
|
+
@control_flow.trivial_recurse
|
31
|
+
def run(self, dag):
|
32
|
+
"""Run the OptimizeSwapBeforeMeasure pass on `dag`.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
dag (DAGCircuit): the DAG to be optimized.
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
DAGCircuit: the optimized DAG.
|
39
|
+
"""
|
40
|
+
|
41
|
+
swaps = dag.op_nodes(SwapGate)
|
42
|
+
for swap in swaps[::-1]:
|
43
|
+
if getattr(swap.op, "_condition", None) is not None:
|
44
|
+
continue
|
45
|
+
final_successor = []
|
46
|
+
for successor in dag.descendants(swap):
|
47
|
+
final_successor.append(
|
48
|
+
isinstance(successor, DAGOutNode)
|
49
|
+
or (isinstance(successor, DAGOpNode) and isinstance(successor.op, Measure))
|
50
|
+
)
|
51
|
+
if all(final_successor):
|
52
|
+
# the node swap needs to be removed and, if a measure follows, needs to be adapted
|
53
|
+
swap_qargs = swap.qargs
|
54
|
+
measure_layer = DAGCircuit()
|
55
|
+
for qreg in dag.qregs.values():
|
56
|
+
measure_layer.add_qreg(qreg)
|
57
|
+
for creg in dag.cregs.values():
|
58
|
+
measure_layer.add_creg(creg)
|
59
|
+
for successor in list(dag.descendants(swap)):
|
60
|
+
if isinstance(successor, DAGOpNode) and isinstance(successor.op, Measure):
|
61
|
+
# replace measure node with a new one, where qargs is set with the "other"
|
62
|
+
# swap qarg.
|
63
|
+
dag.remove_op_node(successor)
|
64
|
+
old_measure_qarg = successor.qargs[0]
|
65
|
+
new_measure_qarg = swap_qargs[swap_qargs.index(old_measure_qarg) - 1]
|
66
|
+
measure_layer.apply_operation_back(
|
67
|
+
Measure(), (new_measure_qarg,), (successor.cargs[0],), check=False
|
68
|
+
)
|
69
|
+
dag.compose(measure_layer)
|
70
|
+
dag.remove_op_node(swap)
|
71
|
+
return dag
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2017, 2019.
|
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
|
+
"""Remove diagonal gates (including diagonal 2Q gates) before a measurement."""
|
14
|
+
|
15
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
16
|
+
from qiskit.transpiler.passes.utils import control_flow
|
17
|
+
|
18
|
+
from qiskit._accelerate.remove_diagonal_gates_before_measure import (
|
19
|
+
remove_diagonal_gates_before_measure,
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
class RemoveDiagonalGatesBeforeMeasure(TransformationPass):
|
24
|
+
"""Remove diagonal gates (including diagonal 2Q gates) before a measurement.
|
25
|
+
|
26
|
+
Transpiler pass to remove diagonal gates (like RZ, T, Z, etc) before
|
27
|
+
a measurement. Including diagonal 2Q gates.
|
28
|
+
"""
|
29
|
+
|
30
|
+
@control_flow.trivial_recurse
|
31
|
+
def run(self, dag):
|
32
|
+
"""Run the RemoveDiagonalGatesBeforeMeasure pass on `dag`.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
dag (DAGCircuit): the DAG to be optimized.
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
DAGCircuit: the optimized DAG.
|
39
|
+
"""
|
40
|
+
remove_diagonal_gates_before_measure(dag)
|
41
|
+
return dag
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2017, 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
|
+
"""Remove reset when it is the final instruction on a qubit."""
|
14
|
+
|
15
|
+
from qiskit.circuit import Reset, Qubit
|
16
|
+
from qiskit.dagcircuit import DAGOpNode
|
17
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
18
|
+
|
19
|
+
|
20
|
+
class RemoveFinalReset(TransformationPass):
|
21
|
+
"""Remove reset when it is the final instruction on a qubit wire."""
|
22
|
+
|
23
|
+
def run(self, dag):
|
24
|
+
"""Run the RemoveFinalReset pass on `dag`.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
dag (DAGCircuit): the DAG to be optimized.
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
DAGCircuit: the optimized DAG.
|
31
|
+
"""
|
32
|
+
for output_node in dag.output_map.values():
|
33
|
+
if isinstance(output_node.wire, Qubit):
|
34
|
+
pred = next(dag.predecessors(output_node))
|
35
|
+
if isinstance(pred, DAGOpNode) and isinstance(pred.op, Reset):
|
36
|
+
dag.remove_op_node(pred)
|
37
|
+
return dag
|