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,566 @@
|
|
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
|
+
"""_DAGDependencyV2 class for representing non-commutativity in a circuit.
|
14
|
+
"""
|
15
|
+
|
16
|
+
import itertools
|
17
|
+
import math
|
18
|
+
from collections import OrderedDict, namedtuple
|
19
|
+
from typing import Dict, List, Generator, Any
|
20
|
+
|
21
|
+
import rustworkx as rx
|
22
|
+
|
23
|
+
from qiskit.circuit import (
|
24
|
+
QuantumRegister,
|
25
|
+
ClassicalRegister,
|
26
|
+
Qubit,
|
27
|
+
Clbit,
|
28
|
+
ParameterExpression,
|
29
|
+
)
|
30
|
+
from qiskit.circuit.controlflow import condition_resources
|
31
|
+
from qiskit.circuit import Bit
|
32
|
+
from qiskit.dagcircuit.dagnode import DAGOpNode
|
33
|
+
from qiskit.dagcircuit.exceptions import DAGDependencyError
|
34
|
+
from qiskit.circuit.commutation_checker import CommutationChecker
|
35
|
+
|
36
|
+
|
37
|
+
BitLocations = namedtuple("BitLocations", ("index", "registers"))
|
38
|
+
|
39
|
+
|
40
|
+
class _DAGDependencyV2:
|
41
|
+
"""Object to represent a quantum circuit as a Directed Acyclic Graph (DAG)
|
42
|
+
via operation dependencies (i.e. lack of commutation).
|
43
|
+
|
44
|
+
.. warning::
|
45
|
+
|
46
|
+
This is not part of the public API.
|
47
|
+
|
48
|
+
The nodes in the graph are operations represented by quantum gates.
|
49
|
+
The edges correspond to non-commutation between two operations
|
50
|
+
(i.e. a dependency). A directed edge from node A to node B means that
|
51
|
+
operation A does not commute with operation B.
|
52
|
+
The object's methods allow circuits to be constructed.
|
53
|
+
|
54
|
+
**Example:**
|
55
|
+
|
56
|
+
Bell circuit with no measurement.
|
57
|
+
|
58
|
+
.. code-block:: text
|
59
|
+
|
60
|
+
┌───┐
|
61
|
+
qr_0: ┤ H ├──■──
|
62
|
+
└───┘┌─┴─┐
|
63
|
+
qr_1: ─────┤ X ├
|
64
|
+
└───┘
|
65
|
+
|
66
|
+
The dependency DAG for the above circuit is represented by two nodes.
|
67
|
+
The first one corresponds to Hadamard gate, the second one to the CNOT gate
|
68
|
+
as the gates do not commute there is an edge between the two nodes.
|
69
|
+
|
70
|
+
**Reference:**
|
71
|
+
|
72
|
+
[1] Iten, R., Moyard, R., Metger, T., Sutter, D. and Woerner, S., 2020.
|
73
|
+
Exact and practical pattern matching for quantum circuit optimization.
|
74
|
+
`arXiv:1909.05270 <https://arxiv.org/abs/1909.05270>`_
|
75
|
+
|
76
|
+
"""
|
77
|
+
|
78
|
+
def __init__(self):
|
79
|
+
"""
|
80
|
+
Create an empty _DAGDependencyV2.
|
81
|
+
"""
|
82
|
+
# Circuit name
|
83
|
+
self.name = None
|
84
|
+
|
85
|
+
# Circuit metadata
|
86
|
+
self.metadata = {}
|
87
|
+
|
88
|
+
# Cache of dag op node sort keys
|
89
|
+
self._key_cache = {}
|
90
|
+
|
91
|
+
# Directed multigraph whose nodes are operations(gates) and edges
|
92
|
+
# represent non-commutativity between two gates.
|
93
|
+
self._multi_graph = rx.PyDAG()
|
94
|
+
|
95
|
+
# Map of qreg/creg name to Register object.
|
96
|
+
self.qregs = OrderedDict()
|
97
|
+
self.cregs = OrderedDict()
|
98
|
+
|
99
|
+
# List of Qubit/Clbit wires that the DAG acts on.
|
100
|
+
self.qubits: List[Qubit] = []
|
101
|
+
self.clbits: List[Clbit] = []
|
102
|
+
|
103
|
+
# Dictionary mapping of Qubit and Clbit instances to a tuple comprised of
|
104
|
+
# 0) corresponding index in dag.{qubits,clbits} and
|
105
|
+
# 1) a list of Register-int pairs for each Register containing the Bit and
|
106
|
+
# its index within that register.
|
107
|
+
self._qubit_indices: Dict[Qubit, BitLocations] = {}
|
108
|
+
self._clbit_indices: Dict[Clbit, BitLocations] = {}
|
109
|
+
|
110
|
+
self._global_phase = 0
|
111
|
+
|
112
|
+
# Map of number of each kind of op, keyed on op name
|
113
|
+
self._op_names = {}
|
114
|
+
|
115
|
+
self.duration = None
|
116
|
+
self.unit = "dt"
|
117
|
+
|
118
|
+
self.comm_checker = CommutationChecker()
|
119
|
+
|
120
|
+
@property
|
121
|
+
def global_phase(self):
|
122
|
+
"""Return the global phase of the circuit."""
|
123
|
+
return self._global_phase
|
124
|
+
|
125
|
+
@global_phase.setter
|
126
|
+
def global_phase(self, angle):
|
127
|
+
"""Set the global phase of the circuit.
|
128
|
+
|
129
|
+
Args:
|
130
|
+
angle (float, ParameterExpression)
|
131
|
+
"""
|
132
|
+
if isinstance(angle, ParameterExpression):
|
133
|
+
self._global_phase = angle
|
134
|
+
else:
|
135
|
+
# Set the phase to the [0, 2π) interval
|
136
|
+
angle = float(angle)
|
137
|
+
if not angle:
|
138
|
+
self._global_phase = 0
|
139
|
+
else:
|
140
|
+
self._global_phase = angle % (2 * math.pi)
|
141
|
+
|
142
|
+
def size(self):
|
143
|
+
"""Returns the number of gates in the circuit"""
|
144
|
+
return len(self._multi_graph)
|
145
|
+
|
146
|
+
def depth(self):
|
147
|
+
"""Return the circuit depth.
|
148
|
+
Returns:
|
149
|
+
int: the circuit depth
|
150
|
+
"""
|
151
|
+
depth = rx.dag_longest_path_length(self._multi_graph)
|
152
|
+
return depth if depth >= 0 else 0
|
153
|
+
|
154
|
+
def width(self):
|
155
|
+
"""Return the total number of qubits + clbits used by the circuit."""
|
156
|
+
return len(self.qubits) + len(self.clbits)
|
157
|
+
|
158
|
+
def num_qubits(self):
|
159
|
+
"""Return the total number of qubits used by the circuit."""
|
160
|
+
return len(self.qubits)
|
161
|
+
|
162
|
+
def num_clbits(self):
|
163
|
+
"""Return the total number of classical bits used by the circuit."""
|
164
|
+
return len(self.clbits)
|
165
|
+
|
166
|
+
def add_qubits(self, qubits):
|
167
|
+
"""Add individual qubit wires."""
|
168
|
+
if any(not isinstance(qubit, Qubit) for qubit in qubits):
|
169
|
+
raise DAGDependencyError("not a Qubit instance.")
|
170
|
+
|
171
|
+
duplicate_qubits = set(self.qubits).intersection(qubits)
|
172
|
+
if duplicate_qubits:
|
173
|
+
raise DAGDependencyError(f"duplicate qubits {duplicate_qubits}")
|
174
|
+
|
175
|
+
for qubit in qubits:
|
176
|
+
self.qubits.append(qubit)
|
177
|
+
self._qubit_indices[qubit] = BitLocations(len(self.qubits) - 1, [])
|
178
|
+
|
179
|
+
def add_clbits(self, clbits):
|
180
|
+
"""Add individual clbit wires."""
|
181
|
+
if any(not isinstance(clbit, Clbit) for clbit in clbits):
|
182
|
+
raise DAGDependencyError("not a Clbit instance.")
|
183
|
+
|
184
|
+
duplicate_clbits = set(self.clbits).intersection(clbits)
|
185
|
+
if duplicate_clbits:
|
186
|
+
raise DAGDependencyError(f"duplicate clbits {duplicate_clbits}")
|
187
|
+
|
188
|
+
for clbit in clbits:
|
189
|
+
self.clbits.append(clbit)
|
190
|
+
self._clbit_indices[clbit] = BitLocations(len(self.clbits) - 1, [])
|
191
|
+
|
192
|
+
def add_qreg(self, qreg):
|
193
|
+
"""Add qubits in a quantum register."""
|
194
|
+
if not isinstance(qreg, QuantumRegister):
|
195
|
+
raise DAGDependencyError("not a QuantumRegister instance.")
|
196
|
+
if qreg.name in self.qregs:
|
197
|
+
raise DAGDependencyError(f"duplicate register {qreg.name}")
|
198
|
+
self.qregs[qreg.name] = qreg
|
199
|
+
existing_qubits = set(self.qubits)
|
200
|
+
for j in range(qreg.size):
|
201
|
+
if qreg[j] in self._qubit_indices:
|
202
|
+
self._qubit_indices[qreg[j]].registers.append((qreg, j))
|
203
|
+
if qreg[j] not in existing_qubits:
|
204
|
+
self.qubits.append(qreg[j])
|
205
|
+
self._qubit_indices[qreg[j]] = BitLocations(
|
206
|
+
len(self.qubits) - 1, registers=[(qreg, j)]
|
207
|
+
)
|
208
|
+
|
209
|
+
def add_creg(self, creg):
|
210
|
+
"""Add clbits in a classical register."""
|
211
|
+
if not isinstance(creg, ClassicalRegister):
|
212
|
+
raise DAGDependencyError("not a ClassicalRegister instance.")
|
213
|
+
if creg.name in self.cregs:
|
214
|
+
raise DAGDependencyError(f"duplicate register {creg.name}")
|
215
|
+
self.cregs[creg.name] = creg
|
216
|
+
existing_clbits = set(self.clbits)
|
217
|
+
for j in range(creg.size):
|
218
|
+
if creg[j] in self._clbit_indices:
|
219
|
+
self._clbit_indices[creg[j]].registers.append((creg, j))
|
220
|
+
if creg[j] not in existing_clbits:
|
221
|
+
self.clbits.append(creg[j])
|
222
|
+
self._clbit_indices[creg[j]] = BitLocations(
|
223
|
+
len(self.clbits) - 1, registers=[(creg, j)]
|
224
|
+
)
|
225
|
+
|
226
|
+
def find_bit(self, bit: Bit) -> BitLocations:
|
227
|
+
"""
|
228
|
+
Finds locations in the _DAGDependencyV2, by mapping the Qubit and Clbit to positional index
|
229
|
+
BitLocations is defined as: BitLocations = namedtuple("BitLocations", ("index", "registers"))
|
230
|
+
|
231
|
+
Args:
|
232
|
+
bit (Bit): The bit to locate.
|
233
|
+
|
234
|
+
Returns:
|
235
|
+
namedtuple(int, List[Tuple(Register, int)]): A 2-tuple. The first element (``index``)
|
236
|
+
contains the index at which the ``Bit`` can be found (in either
|
237
|
+
:obj:`~_DAGDependencyV2.qubits`, :obj:`~_DAGDependencyV2.clbits`, depending on its
|
238
|
+
type). The second element (``registers``) is a list of ``(register, index)``
|
239
|
+
pairs with an entry for each :obj:`~Register` in the circuit which contains the
|
240
|
+
:obj:`~Bit` (and the index in the :obj:`~Register` at which it can be found).
|
241
|
+
|
242
|
+
Raises:
|
243
|
+
DAGDependencyError: If the supplied :obj:`~Bit` was of an unknown type.
|
244
|
+
DAGDependencyError: If the supplied :obj:`~Bit` could not be found on the circuit.
|
245
|
+
"""
|
246
|
+
try:
|
247
|
+
if isinstance(bit, Qubit):
|
248
|
+
return self._qubit_indices[bit]
|
249
|
+
elif isinstance(bit, Clbit):
|
250
|
+
return self._clbit_indices[bit]
|
251
|
+
else:
|
252
|
+
raise DAGDependencyError(f"Could not locate bit of unknown type: {type(bit)}")
|
253
|
+
except KeyError as err:
|
254
|
+
raise DAGDependencyError(
|
255
|
+
f"Could not locate provided bit: {bit}. Has it been added to the DAGDependency?"
|
256
|
+
) from err
|
257
|
+
|
258
|
+
def apply_operation_back(self, operation, qargs=(), cargs=()):
|
259
|
+
"""Add a DAGOpNode to the graph and update the edges.
|
260
|
+
|
261
|
+
Args:
|
262
|
+
operation (qiskit.circuit.Operation): operation as a quantum gate
|
263
|
+
qargs (list[~qiskit.circuit.Qubit]): list of qubits on which the operation acts
|
264
|
+
cargs (list[Clbit]): list of classical wires to attach to
|
265
|
+
"""
|
266
|
+
new_node = DAGOpNode(
|
267
|
+
op=operation,
|
268
|
+
qargs=qargs,
|
269
|
+
cargs=cargs,
|
270
|
+
)
|
271
|
+
new_node._node_id = self._multi_graph.add_node(new_node)
|
272
|
+
self._update_edges()
|
273
|
+
self._increment_op(new_node.op)
|
274
|
+
|
275
|
+
def _update_edges(self):
|
276
|
+
"""
|
277
|
+
Updates DagDependencyV2 by adding edges to the newly added node (max_node)
|
278
|
+
from the previously added nodes.
|
279
|
+
For each previously added node (prev_node), an edge from prev_node to max_node
|
280
|
+
is added if max_node is "reachable" from prev_node (this means that the two
|
281
|
+
nodes can be made adjacent by commuting them with other nodes), but the two nodes
|
282
|
+
themselves do not commute.
|
283
|
+
|
284
|
+
Currently. this function is only used when creating a new _DAGDependencyV2 from another
|
285
|
+
representation of a circuit, and hence there are no removed nodes (this is why
|
286
|
+
iterating over all nodes is fine).
|
287
|
+
"""
|
288
|
+
max_node_id = len(self._multi_graph) - 1
|
289
|
+
max_node = self._get_node(max_node_id)
|
290
|
+
|
291
|
+
reachable = [True] * max_node_id
|
292
|
+
|
293
|
+
# Analyze nodes in the reverse topological order.
|
294
|
+
# An improvement to the original algorithm is to consider only direct predecessors
|
295
|
+
# and to avoid constructing the lists of forward and backward reachable predecessors
|
296
|
+
# for every node when not required.
|
297
|
+
for prev_node_id in range(max_node_id - 1, -1, -1):
|
298
|
+
if reachable[prev_node_id]:
|
299
|
+
prev_node = self._get_node(prev_node_id)
|
300
|
+
|
301
|
+
if not self.comm_checker.commute(
|
302
|
+
prev_node.op,
|
303
|
+
prev_node.qargs,
|
304
|
+
prev_node.cargs,
|
305
|
+
max_node.op,
|
306
|
+
max_node.qargs,
|
307
|
+
max_node.cargs,
|
308
|
+
):
|
309
|
+
# If prev_node and max_node do not commute, then we add an edge
|
310
|
+
# between the two, and mark all direct predecessors of prev_node
|
311
|
+
# as not reaching max_node.
|
312
|
+
self._multi_graph.add_edge(prev_node_id, max_node_id, {"commute": False})
|
313
|
+
|
314
|
+
predecessor_ids = sorted(
|
315
|
+
[node._node_id for node in self.predecessors(self._get_node(prev_node_id))]
|
316
|
+
)
|
317
|
+
for predecessor_id in predecessor_ids:
|
318
|
+
reachable[predecessor_id] = False
|
319
|
+
else:
|
320
|
+
# If prev_node cannot reach max_node, then none of its predecessors can
|
321
|
+
# reach max_node either.
|
322
|
+
predecessor_ids = sorted(
|
323
|
+
[node._node_id for node in self.predecessors(self._get_node(prev_node_id))]
|
324
|
+
)
|
325
|
+
for predecessor_id in predecessor_ids:
|
326
|
+
reachable[predecessor_id] = False
|
327
|
+
|
328
|
+
def _get_node(self, node_id):
|
329
|
+
"""
|
330
|
+
Args:
|
331
|
+
node_id (int): label of considered node.
|
332
|
+
|
333
|
+
Returns:
|
334
|
+
node: corresponding to the label.
|
335
|
+
"""
|
336
|
+
return self._multi_graph.get_node_data(node_id)
|
337
|
+
|
338
|
+
def named_nodes(self, *names):
|
339
|
+
"""Get the set of "op" nodes with the given name."""
|
340
|
+
named_nodes = []
|
341
|
+
for node in self._multi_graph.nodes():
|
342
|
+
if node.op.name in names:
|
343
|
+
named_nodes.append(node)
|
344
|
+
return named_nodes
|
345
|
+
|
346
|
+
def _increment_op(self, op):
|
347
|
+
if op.name in self._op_names:
|
348
|
+
self._op_names[op.name] += 1
|
349
|
+
else:
|
350
|
+
self._op_names[op.name] = 1
|
351
|
+
|
352
|
+
def _decrement_op(self, op):
|
353
|
+
if self._op_names[op.name] == 1:
|
354
|
+
del self._op_names[op.name]
|
355
|
+
else:
|
356
|
+
self._op_names[op.name] -= 1
|
357
|
+
|
358
|
+
def count_ops(self):
|
359
|
+
"""Count the occurrences of operation names."""
|
360
|
+
return self._op_names
|
361
|
+
|
362
|
+
def op_nodes(self):
|
363
|
+
"""
|
364
|
+
Returns:
|
365
|
+
generator(dict): iterator over all the nodes.
|
366
|
+
"""
|
367
|
+
return iter(self._multi_graph.nodes())
|
368
|
+
|
369
|
+
def topological_nodes(self, key=None) -> Generator[DAGOpNode, Any, Any]:
|
370
|
+
"""
|
371
|
+
Yield nodes in topological order.
|
372
|
+
|
373
|
+
Args:
|
374
|
+
key (Callable): A callable which will take a DAGNode object and
|
375
|
+
return a string sort key. If not specified the
|
376
|
+
:attr:`~qiskit.dagcircuit.DAGNode.sort_key` attribute will be
|
377
|
+
used as the sort key for each node.
|
378
|
+
|
379
|
+
Returns:
|
380
|
+
generator(DAGOpNode): node in topological order
|
381
|
+
"""
|
382
|
+
|
383
|
+
def _key(x):
|
384
|
+
return ",".join(
|
385
|
+
f"{self.find_bit(q).index:04d}" for q in itertools.chain(x.qargs, x.cargs)
|
386
|
+
)
|
387
|
+
|
388
|
+
if key is None:
|
389
|
+
key = _key
|
390
|
+
|
391
|
+
return iter(rx.lexicographical_topological_sort(self._multi_graph, key=key))
|
392
|
+
|
393
|
+
def topological_op_nodes(self, key=None) -> Generator[DAGOpNode, Any, Any]:
|
394
|
+
"""
|
395
|
+
Yield nodes in topological order. This is a wrapper for topological_nodes since
|
396
|
+
all nodes are op nodes. It's here so that calls to dag.topological_op_nodes can
|
397
|
+
use either DAGCircuit or _DAGDependencyV2.
|
398
|
+
|
399
|
+
Returns:
|
400
|
+
generator(DAGOpNode): nodes in topological order.
|
401
|
+
"""
|
402
|
+
return self.topological_nodes(key)
|
403
|
+
|
404
|
+
def successors(self, node):
|
405
|
+
"""Returns iterator of the successors of a node as DAGOpNodes."""
|
406
|
+
return iter(self._multi_graph.successors(node._node_id))
|
407
|
+
|
408
|
+
def predecessors(self, node):
|
409
|
+
"""Returns iterator of the predecessors of a node as DAGOpNodes."""
|
410
|
+
return iter(self._multi_graph.predecessors(node._node_id))
|
411
|
+
|
412
|
+
def is_successor(self, node, node_succ):
|
413
|
+
"""Checks if a second node is in the successors of node."""
|
414
|
+
return self._multi_graph.has_edge(node._node_id, node_succ._node_id)
|
415
|
+
|
416
|
+
def is_predecessor(self, node, node_pred):
|
417
|
+
"""Checks if a second node is in the predecessors of node."""
|
418
|
+
return self._multi_graph.has_edge(node_pred._node_id, node._node_id)
|
419
|
+
|
420
|
+
def ancestors(self, node):
|
421
|
+
"""Returns set of the ancestors of a node as DAGOpNodes."""
|
422
|
+
return {self._multi_graph[x] for x in rx.ancestors(self._multi_graph, node._node_id)}
|
423
|
+
|
424
|
+
def descendants(self, node):
|
425
|
+
"""Returns set of the descendants of a node as DAGOpNodes."""
|
426
|
+
return {self._multi_graph[x] for x in rx.descendants(self._multi_graph, node._node_id)}
|
427
|
+
|
428
|
+
def bfs_successors(self, node):
|
429
|
+
"""
|
430
|
+
Returns an iterator of tuples of (DAGOpNode, [DAGOpNodes]) where the DAGOpNode is the
|
431
|
+
current node and [DAGOpNode] is its successors in BFS order.
|
432
|
+
"""
|
433
|
+
return iter(rx.bfs_successors(self._multi_graph, node._node_id))
|
434
|
+
|
435
|
+
def copy_empty_like(self):
|
436
|
+
"""Return a copy of self with the same structure but empty.
|
437
|
+
|
438
|
+
That structure includes:
|
439
|
+
* name and other metadata
|
440
|
+
* global phase
|
441
|
+
* duration
|
442
|
+
* all the qubits and clbits, including the registers.
|
443
|
+
|
444
|
+
Returns:
|
445
|
+
_DAGDependencyV2: An empty copy of self.
|
446
|
+
"""
|
447
|
+
target_dag = _DAGDependencyV2()
|
448
|
+
target_dag.name = self.name
|
449
|
+
target_dag._global_phase = self._global_phase
|
450
|
+
target_dag.metadata = self.metadata
|
451
|
+
target_dag._key_cache = self._key_cache
|
452
|
+
target_dag.comm_checker = self.comm_checker
|
453
|
+
|
454
|
+
target_dag.add_qubits(self.qubits)
|
455
|
+
target_dag.add_clbits(self.clbits)
|
456
|
+
|
457
|
+
target_dag.duration = self.duration
|
458
|
+
target_dag.unit = self.unit
|
459
|
+
|
460
|
+
for qreg in self.qregs.values():
|
461
|
+
target_dag.add_qreg(qreg)
|
462
|
+
for creg in self.cregs.values():
|
463
|
+
target_dag.add_creg(creg)
|
464
|
+
|
465
|
+
return target_dag
|
466
|
+
|
467
|
+
def draw(self, scale=0.7, filename=None, style="color"):
|
468
|
+
"""
|
469
|
+
Draws the _DAGDependencyV2 graph.
|
470
|
+
|
471
|
+
This function needs `pydot <https://github.com/erocarrera/pydot>`, which in turn needs
|
472
|
+
Graphviz <https://www.graphviz.org/>` to be installed.
|
473
|
+
|
474
|
+
Args:
|
475
|
+
scale (float): scaling factor
|
476
|
+
filename (str): file path to save image to (format inferred from name)
|
477
|
+
style (str): 'plain': B&W graph
|
478
|
+
'color' (default): color input/output/op nodes
|
479
|
+
|
480
|
+
Returns:
|
481
|
+
Ipython.display.Image: if in Jupyter notebook and not saving to file, otherwise None.
|
482
|
+
"""
|
483
|
+
from qiskit.visualization.dag_visualization import dag_drawer
|
484
|
+
|
485
|
+
return dag_drawer(dag=self, scale=scale, filename=filename, style=style)
|
486
|
+
|
487
|
+
def replace_block_with_op(self, node_block, op, wire_pos_map, cycle_check=True):
|
488
|
+
"""Replace a block of nodes with a single node.
|
489
|
+
|
490
|
+
This is used to consolidate a block of DAGOpNodes into a single
|
491
|
+
operation. A typical example is a block of CX and SWAP gates consolidated
|
492
|
+
into a LinearFunction. This function is an adaptation of a similar
|
493
|
+
function from DAGCircuit.
|
494
|
+
|
495
|
+
It is important that such consolidation preserves commutativity assumptions
|
496
|
+
present in _DAGDependencyV2. As an example, suppose that every node in a
|
497
|
+
block [A, B, C, D] commutes with another node E. Let F be the consolidated
|
498
|
+
node, F = A o B o C o D. Then F also commutes with E, and thus the result of
|
499
|
+
replacing [A, B, C, D] by F results in a valid _DAGDependencyV2. That is, any
|
500
|
+
deduction about commutativity in consolidated _DAGDependencyV2 is correct.
|
501
|
+
On the other hand, suppose that at least one of the nodes, say B, does not commute
|
502
|
+
with E. Then the consolidated _DAGDependencyV2 would imply that F does not commute
|
503
|
+
with E. Even though F and E may actually commute, it is still safe to assume that
|
504
|
+
they do not. That is, the current implementation of consolidation may lead to
|
505
|
+
suboptimal but not to incorrect results.
|
506
|
+
|
507
|
+
Args:
|
508
|
+
node_block (List[DAGOpNode]): A list of dag nodes that represents the
|
509
|
+
node block to be replaced
|
510
|
+
op (qiskit.circuit.Operation): The operation to replace the
|
511
|
+
block with
|
512
|
+
wire_pos_map (Dict[~qiskit.circuit.Qubit, int]): The dictionary mapping the qarg to
|
513
|
+
the position. This is necessary to reconstruct the qarg order
|
514
|
+
over multiple gates in the combined single op node.
|
515
|
+
cycle_check (bool): When set to True this method will check that
|
516
|
+
replacing the provided ``node_block`` with a single node
|
517
|
+
would introduce a cycle (which would invalidate the
|
518
|
+
``_DAGDependencyV2``) and will raise a ``DAGDependencyError`` if a cycle
|
519
|
+
would be introduced. This checking comes with a run time
|
520
|
+
penalty. If you can guarantee that your input ``node_block`` is
|
521
|
+
a contiguous block and won't introduce a cycle when it's
|
522
|
+
contracted to a single node, this can be set to ``False`` to
|
523
|
+
improve the runtime performance of this method.
|
524
|
+
Raises:
|
525
|
+
DAGDependencyError: if ``cycle_check`` is set to ``True`` and replacing
|
526
|
+
the specified block introduces a cycle or if ``node_block`` is
|
527
|
+
empty.
|
528
|
+
"""
|
529
|
+
block_qargs = set()
|
530
|
+
block_cargs = set()
|
531
|
+
block_ids = [x._node_id for x in node_block]
|
532
|
+
|
533
|
+
# If node block is empty return early
|
534
|
+
if not node_block:
|
535
|
+
raise DAGDependencyError("Can't replace an empty node_block")
|
536
|
+
|
537
|
+
for nd in node_block:
|
538
|
+
block_qargs |= set(nd.qargs)
|
539
|
+
block_cargs |= set(nd.cargs)
|
540
|
+
cond = getattr(nd.op, "condition", None)
|
541
|
+
if cond is not None:
|
542
|
+
block_cargs.update(condition_resources(cond).clbits)
|
543
|
+
|
544
|
+
# Create replacement node
|
545
|
+
new_node = DAGOpNode(
|
546
|
+
op,
|
547
|
+
qargs=sorted(block_qargs, key=lambda x: wire_pos_map[x]),
|
548
|
+
cargs=sorted(block_cargs, key=lambda x: wire_pos_map[x]),
|
549
|
+
dag=self,
|
550
|
+
)
|
551
|
+
|
552
|
+
try:
|
553
|
+
new_node._node_id = self._multi_graph.contract_nodes(
|
554
|
+
block_ids, new_node, check_cycle=cycle_check
|
555
|
+
)
|
556
|
+
except rx.DAGWouldCycle as ex:
|
557
|
+
raise DAGDependencyError(
|
558
|
+
"Replacing the specified node block would introduce a cycle"
|
559
|
+
) from ex
|
560
|
+
|
561
|
+
self._increment_op(op)
|
562
|
+
|
563
|
+
for nd in node_block:
|
564
|
+
self._decrement_op(nd.op)
|
565
|
+
|
566
|
+
return new_node
|