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,299 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 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
|
+
A definition of the approximate circuit compilation optimization problem based on CNOT unit
|
14
|
+
definition.
|
15
|
+
"""
|
16
|
+
from __future__ import annotations
|
17
|
+
import typing
|
18
|
+
from abc import ABC
|
19
|
+
|
20
|
+
import numpy as np
|
21
|
+
from numpy import linalg as la
|
22
|
+
|
23
|
+
from .approximate import ApproximatingObjective
|
24
|
+
from .elementary_operations import ry_matrix, rz_matrix, place_unitary, place_cnot, rx_matrix
|
25
|
+
|
26
|
+
|
27
|
+
class CNOTUnitObjective(ApproximatingObjective, ABC):
|
28
|
+
"""
|
29
|
+
A base class for a problem definition based on CNOT unit. This class may have different
|
30
|
+
subclasses for objective and gradient computations.
|
31
|
+
"""
|
32
|
+
|
33
|
+
def __init__(self, num_qubits: int, cnots: np.ndarray) -> None:
|
34
|
+
"""
|
35
|
+
Args:
|
36
|
+
num_qubits: number of qubits.
|
37
|
+
cnots: a CNOT structure to be used in the optimization procedure.
|
38
|
+
"""
|
39
|
+
super().__init__()
|
40
|
+
self._num_qubits = num_qubits
|
41
|
+
self._cnots = cnots
|
42
|
+
self._num_cnots = cnots.shape[1]
|
43
|
+
|
44
|
+
@property
|
45
|
+
def num_cnots(self):
|
46
|
+
"""
|
47
|
+
Returns:
|
48
|
+
A number of CNOT units to be used by the approximate circuit.
|
49
|
+
"""
|
50
|
+
return self._num_cnots
|
51
|
+
|
52
|
+
@property
|
53
|
+
def num_thetas(self):
|
54
|
+
"""
|
55
|
+
Returns:
|
56
|
+
Number of parameters (angles) of rotation gates in this circuit.
|
57
|
+
"""
|
58
|
+
return 3 * self._num_qubits + 4 * self._num_cnots
|
59
|
+
|
60
|
+
|
61
|
+
class DefaultCNOTUnitObjective(CNOTUnitObjective):
|
62
|
+
"""A naive implementation of the objective function based on CNOT units."""
|
63
|
+
|
64
|
+
def __init__(self, num_qubits: int, cnots: np.ndarray) -> None:
|
65
|
+
"""
|
66
|
+
Args:
|
67
|
+
num_qubits: number of qubits.
|
68
|
+
cnots: a CNOT structure to be used in the optimization procedure.
|
69
|
+
"""
|
70
|
+
super().__init__(num_qubits, cnots)
|
71
|
+
|
72
|
+
# last objective computations to be re-used by gradient
|
73
|
+
self._last_thetas: np.ndarray | None = None
|
74
|
+
self._cnot_right_collection: np.ndarray | None = None
|
75
|
+
self._cnot_left_collection: np.ndarray | None = None
|
76
|
+
self._rotation_matrix: int | np.ndarray | None = None
|
77
|
+
self._cnot_matrix: np.ndarray | None = None
|
78
|
+
|
79
|
+
def objective(self, param_values: np.ndarray) -> typing.SupportsFloat:
|
80
|
+
# rename parameters just to make shorter and make use of our dictionary
|
81
|
+
thetas = param_values
|
82
|
+
n = self._num_qubits
|
83
|
+
d = int(2**n)
|
84
|
+
cnots = self._cnots
|
85
|
+
num_cnots = self.num_cnots
|
86
|
+
|
87
|
+
# to save intermediate computations we define the following matrices
|
88
|
+
# this is the collection of cnot unit matrices ordered from left to
|
89
|
+
# right as in the circuit, not matrix product
|
90
|
+
cnot_unit_collection = np.zeros((d, d * num_cnots), dtype=complex)
|
91
|
+
# this is the collection of matrix products of the cnot units up
|
92
|
+
# to the given position from the right of the circuit
|
93
|
+
cnot_right_collection = np.zeros((d, d * num_cnots), dtype=complex)
|
94
|
+
# this is the collection of matrix products of the cnot units up
|
95
|
+
# to the given position from the left of the circuit
|
96
|
+
cnot_left_collection = np.zeros((d, d * num_cnots), dtype=complex)
|
97
|
+
# first, we construct each cnot unit matrix
|
98
|
+
for cnot_index in range(num_cnots):
|
99
|
+
theta_index = 4 * cnot_index
|
100
|
+
|
101
|
+
# cnot qubit indices for the cnot unit identified by cnot_index
|
102
|
+
q1 = int(cnots[0, cnot_index])
|
103
|
+
q2 = int(cnots[1, cnot_index])
|
104
|
+
|
105
|
+
# rotations that are applied on the q1 qubit
|
106
|
+
ry1 = ry_matrix(thetas[0 + theta_index])
|
107
|
+
rz1 = rz_matrix(thetas[1 + theta_index])
|
108
|
+
|
109
|
+
# rotations that are applied on the q2 qubit
|
110
|
+
ry2 = ry_matrix(thetas[2 + theta_index])
|
111
|
+
rx2 = rx_matrix(thetas[3 + theta_index])
|
112
|
+
|
113
|
+
# combine the rotations on qubits q1 and q2
|
114
|
+
single_q1 = np.dot(rz1, ry1)
|
115
|
+
single_q2 = np.dot(rx2, ry2)
|
116
|
+
|
117
|
+
# we place single qubit matrices at the corresponding locations in the (2^n, 2^n) matrix
|
118
|
+
full_q1 = place_unitary(single_q1, n, q1)
|
119
|
+
full_q2 = place_unitary(single_q2, n, q2)
|
120
|
+
|
121
|
+
# we place a cnot matrix at the qubits q1 and q2 in the full matrix
|
122
|
+
cnot_q1q2 = place_cnot(n, q1, q2)
|
123
|
+
|
124
|
+
# compute the cnot unit matrix and store in cnot_unit_collection
|
125
|
+
cnot_unit_collection[:, d * cnot_index : d * (cnot_index + 1)] = la.multi_dot(
|
126
|
+
[full_q2, full_q1, cnot_q1q2]
|
127
|
+
)
|
128
|
+
|
129
|
+
# this is the matrix corresponding to the intermediate matrix products
|
130
|
+
# it will end up being the matrix product of all the cnot unit matrices
|
131
|
+
# first we multiply from the right-hand side of the circuit
|
132
|
+
cnot_matrix = np.eye(d)
|
133
|
+
for cnot_index in range(num_cnots - 1, -1, -1):
|
134
|
+
cnot_matrix = np.dot(
|
135
|
+
cnot_matrix, cnot_unit_collection[:, d * cnot_index : d * (cnot_index + 1)]
|
136
|
+
)
|
137
|
+
cnot_right_collection[:, d * cnot_index : d * (cnot_index + 1)] = cnot_matrix
|
138
|
+
# now we multiply from the left-hand side of the circuit
|
139
|
+
cnot_matrix = np.eye(d)
|
140
|
+
for cnot_index in range(num_cnots):
|
141
|
+
cnot_matrix = np.dot(
|
142
|
+
cnot_unit_collection[:, d * cnot_index : d * (cnot_index + 1)], cnot_matrix
|
143
|
+
)
|
144
|
+
cnot_left_collection[:, d * cnot_index : d * (cnot_index + 1)] = cnot_matrix
|
145
|
+
|
146
|
+
# this is the matrix corresponding to the initial rotations
|
147
|
+
# we start with 1 and kronecker product each qubit's rotations
|
148
|
+
rotation_matrix: int | np.ndarray = 1
|
149
|
+
for q in range(n):
|
150
|
+
theta_index = 4 * num_cnots + 3 * q
|
151
|
+
rz0 = rz_matrix(thetas[0 + theta_index])
|
152
|
+
ry1 = ry_matrix(thetas[1 + theta_index])
|
153
|
+
rz2 = rz_matrix(thetas[2 + theta_index])
|
154
|
+
rotation_matrix = np.kron(rotation_matrix, la.multi_dot([rz0, ry1, rz2]))
|
155
|
+
|
156
|
+
# the matrix corresponding to the full circuit is the cnot part and
|
157
|
+
# rotation part multiplied together
|
158
|
+
circuit_matrix = np.dot(cnot_matrix, rotation_matrix)
|
159
|
+
|
160
|
+
# compute error
|
161
|
+
error = 0.5 * (la.norm(circuit_matrix - self._target_matrix, "fro") ** 2)
|
162
|
+
|
163
|
+
# cache computations for gradient
|
164
|
+
self._last_thetas = thetas
|
165
|
+
self._cnot_left_collection = cnot_left_collection
|
166
|
+
self._cnot_right_collection = cnot_right_collection
|
167
|
+
self._rotation_matrix = rotation_matrix
|
168
|
+
self._cnot_matrix = cnot_matrix
|
169
|
+
|
170
|
+
return error
|
171
|
+
|
172
|
+
def gradient(self, param_values: np.ndarray) -> np.ndarray:
|
173
|
+
# just to make shorter
|
174
|
+
thetas = param_values
|
175
|
+
# if given thetas are the same as used at the previous objective computations, then
|
176
|
+
# we re-use computations, otherwise we have to re-compute objective
|
177
|
+
if not np.all(np.isclose(thetas, self._last_thetas)):
|
178
|
+
self.objective(thetas)
|
179
|
+
|
180
|
+
# the partial derivative of the circuit with respect to an angle
|
181
|
+
# is the same circuit with the corresponding pauli gate, multiplied
|
182
|
+
# by a global phase of -1j / 2, next to the rotation gate (it commutes)
|
183
|
+
pauli_x = np.multiply(-1j / 2, np.asarray([[0, 1], [1, 0]]))
|
184
|
+
pauli_y = np.multiply(-1j / 2, np.asarray([[0, -1j], [1j, 0]]))
|
185
|
+
pauli_z = np.multiply(-1j / 2, np.asarray([[1, 0], [0, -1]]))
|
186
|
+
|
187
|
+
n = self._num_qubits
|
188
|
+
d = int(2**n)
|
189
|
+
cnots = self._cnots
|
190
|
+
num_cnots = self.num_cnots
|
191
|
+
|
192
|
+
# the partial derivative of the cost function is -Re<V',U>
|
193
|
+
# where V' is the partial derivative of the circuit
|
194
|
+
# first we compute the partial derivatives in the cnot part
|
195
|
+
der = np.zeros(4 * num_cnots + 3 * n)
|
196
|
+
for cnot_index in range(num_cnots):
|
197
|
+
theta_index = 4 * cnot_index
|
198
|
+
|
199
|
+
# cnot qubit indices for the cnot unit identified by cnot_index
|
200
|
+
q1 = int(cnots[0, cnot_index])
|
201
|
+
q2 = int(cnots[1, cnot_index])
|
202
|
+
|
203
|
+
# rotations that are applied on the q1 qubit
|
204
|
+
ry1 = ry_matrix(thetas[0 + theta_index])
|
205
|
+
rz1 = rz_matrix(thetas[1 + theta_index])
|
206
|
+
|
207
|
+
# rotations that are applied on the q2 qubit
|
208
|
+
ry2 = ry_matrix(thetas[2 + theta_index])
|
209
|
+
rx2 = rx_matrix(thetas[3 + theta_index])
|
210
|
+
|
211
|
+
# combine the rotations on qubits q1 and q2
|
212
|
+
# note we have to insert an extra pauli gate to take the derivative
|
213
|
+
# of the appropriate rotation gate
|
214
|
+
for i in range(4):
|
215
|
+
if i == 0:
|
216
|
+
single_q1 = la.multi_dot([rz1, pauli_y, ry1])
|
217
|
+
single_q2 = np.dot(rx2, ry2)
|
218
|
+
elif i == 1:
|
219
|
+
single_q1 = la.multi_dot([pauli_z, rz1, ry1])
|
220
|
+
single_q2 = np.dot(rx2, ry2)
|
221
|
+
elif i == 2:
|
222
|
+
single_q1 = np.dot(rz1, ry1)
|
223
|
+
single_q2 = la.multi_dot([rx2, pauli_y, ry2])
|
224
|
+
else:
|
225
|
+
single_q1 = np.dot(rz1, ry1)
|
226
|
+
single_q2 = la.multi_dot([pauli_x, rx2, ry2])
|
227
|
+
|
228
|
+
# we place single qubit matrices at the corresponding locations in
|
229
|
+
# the (2^n, 2^n) matrix
|
230
|
+
full_q1 = place_unitary(single_q1, n, q1)
|
231
|
+
full_q2 = place_unitary(single_q2, n, q2)
|
232
|
+
|
233
|
+
# we place a cnot matrix at the qubits q1 and q2 in the full matrix
|
234
|
+
cnot_q1q2 = place_cnot(n, q1, q2)
|
235
|
+
|
236
|
+
# partial derivative of that particular cnot unit, size of (2^n, 2^n)
|
237
|
+
der_cnot_unit = la.multi_dot([full_q2, full_q1, cnot_q1q2])
|
238
|
+
# der_cnot_unit is multiplied by the matrix product of cnot units to the left
|
239
|
+
# of it (if there are any) and to the right of it (if there are any)
|
240
|
+
if cnot_index == 0:
|
241
|
+
der_cnot_matrix = np.dot(
|
242
|
+
self._cnot_right_collection[:, d : 2 * d],
|
243
|
+
der_cnot_unit,
|
244
|
+
)
|
245
|
+
elif num_cnots - 1 == cnot_index:
|
246
|
+
der_cnot_matrix = np.dot(
|
247
|
+
der_cnot_unit,
|
248
|
+
self._cnot_left_collection[:, d * (num_cnots - 2) : d * (num_cnots - 1)],
|
249
|
+
)
|
250
|
+
else:
|
251
|
+
der_cnot_matrix = la.multi_dot(
|
252
|
+
[
|
253
|
+
self._cnot_right_collection[
|
254
|
+
:, d * (cnot_index + 1) : d * (cnot_index + 2)
|
255
|
+
],
|
256
|
+
der_cnot_unit,
|
257
|
+
self._cnot_left_collection[:, d * (cnot_index - 1) : d * cnot_index],
|
258
|
+
]
|
259
|
+
)
|
260
|
+
|
261
|
+
# the matrix corresponding to the full circuit partial derivative
|
262
|
+
# is the partial derivative of the cnot part multiplied by the usual
|
263
|
+
# rotation part
|
264
|
+
der_circuit_matrix = np.dot(der_cnot_matrix, self._rotation_matrix)
|
265
|
+
# we compute the partial derivative of the cost function
|
266
|
+
der[i + theta_index] = -np.real(
|
267
|
+
np.trace(np.dot(der_circuit_matrix.conj().T, self._target_matrix))
|
268
|
+
)
|
269
|
+
|
270
|
+
# now we compute the partial derivatives in the rotation part
|
271
|
+
# we start with 1 and kronecker product each qubit's rotations
|
272
|
+
for i in range(3 * n):
|
273
|
+
der_rotation_matrix: int | np.ndarray = 1
|
274
|
+
for q in range(n):
|
275
|
+
theta_index = 4 * num_cnots + 3 * q
|
276
|
+
rz0 = rz_matrix(thetas[0 + theta_index])
|
277
|
+
ry1 = ry_matrix(thetas[1 + theta_index])
|
278
|
+
rz2 = rz_matrix(thetas[2 + theta_index])
|
279
|
+
# for the appropriate rotation gate that we are taking
|
280
|
+
# the partial derivative of, we have to insert the
|
281
|
+
# corresponding pauli matrix
|
282
|
+
if i - 3 * q == 0:
|
283
|
+
rz0 = np.dot(pauli_z, rz0)
|
284
|
+
elif i - 3 * q == 1:
|
285
|
+
ry1 = np.dot(pauli_y, ry1)
|
286
|
+
elif i - 3 * q == 2:
|
287
|
+
rz2 = np.dot(pauli_z, rz2)
|
288
|
+
der_rotation_matrix = np.kron(der_rotation_matrix, la.multi_dot([rz0, ry1, rz2]))
|
289
|
+
|
290
|
+
# the matrix corresponding to the full circuit partial derivative
|
291
|
+
# is the usual cnot part multiplied by the partial derivative of
|
292
|
+
# the rotation part
|
293
|
+
der_circuit_matrix = np.dot(self._cnot_matrix, der_rotation_matrix)
|
294
|
+
# we compute the partial derivative of the cost function
|
295
|
+
der[4 * num_cnots + i] = -np.real(
|
296
|
+
np.trace(np.dot(der_circuit_matrix.conj().T, self._target_matrix))
|
297
|
+
)
|
298
|
+
|
299
|
+
return der
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 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
|
+
These are a number of elementary functions that are required for the AQC routines to work.
|
14
|
+
"""
|
15
|
+
|
16
|
+
import numpy as np
|
17
|
+
|
18
|
+
from qiskit.circuit.library.standard_gates import RXGate, RZGate, RYGate
|
19
|
+
|
20
|
+
|
21
|
+
def place_unitary(unitary: np.ndarray, n: int, j: int) -> np.ndarray:
|
22
|
+
"""
|
23
|
+
Computes I(j - 1) tensor product U tensor product I(n - j), where U is a unitary matrix
|
24
|
+
of size ``(2, 2)``.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
unitary: a unitary matrix of size ``(2, 2)``.
|
28
|
+
n: num qubits.
|
29
|
+
j: position where to place a unitary.
|
30
|
+
|
31
|
+
Returns:
|
32
|
+
a unitary of n qubits with u in position j.
|
33
|
+
"""
|
34
|
+
return np.kron(np.kron(np.eye(2**j), unitary), np.eye(2 ** (n - 1 - j)))
|
35
|
+
|
36
|
+
|
37
|
+
def place_cnot(n: int, j: int, k: int) -> np.ndarray:
|
38
|
+
"""
|
39
|
+
Places a CNOT from j to k.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
n: number of qubits.
|
43
|
+
j: control qubit.
|
44
|
+
k: target qubit.
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
a unitary of n qubits with CNOT placed at ``j`` and ``k``.
|
48
|
+
"""
|
49
|
+
if j < k:
|
50
|
+
unitary = np.kron(
|
51
|
+
np.kron(np.eye(2**j), [[1, 0], [0, 0]]), np.eye(2 ** (n - 1 - j))
|
52
|
+
) + np.kron(
|
53
|
+
np.kron(
|
54
|
+
np.kron(np.kron(np.eye(2**j), [[0, 0], [0, 1]]), np.eye(2 ** (k - j - 1))),
|
55
|
+
[[0, 1], [1, 0]],
|
56
|
+
),
|
57
|
+
np.eye(2 ** (n - 1 - k)),
|
58
|
+
)
|
59
|
+
else:
|
60
|
+
unitary = np.kron(
|
61
|
+
np.kron(np.eye(2**j), [[1, 0], [0, 0]]), np.eye(2 ** (n - 1 - j))
|
62
|
+
) + np.kron(
|
63
|
+
np.kron(
|
64
|
+
np.kron(np.kron(np.eye(2**k), [[0, 1], [1, 0]]), np.eye(2 ** (j - k - 1))),
|
65
|
+
[[0, 0], [0, 1]],
|
66
|
+
),
|
67
|
+
np.eye(2 ** (n - 1 - j)),
|
68
|
+
)
|
69
|
+
return unitary
|
70
|
+
|
71
|
+
|
72
|
+
def rx_matrix(phi: float) -> np.ndarray:
|
73
|
+
"""
|
74
|
+
Computes an RX rotation by the angle of ``phi``.
|
75
|
+
|
76
|
+
Args:
|
77
|
+
phi: rotation angle.
|
78
|
+
|
79
|
+
Returns:
|
80
|
+
an RX rotation matrix.
|
81
|
+
"""
|
82
|
+
return RXGate(phi).to_matrix()
|
83
|
+
|
84
|
+
|
85
|
+
def ry_matrix(phi: float) -> np.ndarray:
|
86
|
+
"""
|
87
|
+
Computes an RY rotation by the angle of ``phi``.
|
88
|
+
|
89
|
+
Args:
|
90
|
+
phi: rotation angle.
|
91
|
+
|
92
|
+
Returns:
|
93
|
+
an RY rotation matrix.
|
94
|
+
"""
|
95
|
+
return RYGate(phi).to_matrix()
|
96
|
+
|
97
|
+
|
98
|
+
def rz_matrix(phi: float) -> np.ndarray:
|
99
|
+
"""
|
100
|
+
Computes an RZ rotation by the angle of ``phi``.
|
101
|
+
|
102
|
+
Args:
|
103
|
+
phi: rotation angle.
|
104
|
+
|
105
|
+
Returns:
|
106
|
+
an RZ rotation matrix.
|
107
|
+
"""
|
108
|
+
return RZGate(phi).to_matrix()
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2022.
|
4
|
+
#
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
+
#
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
11
|
+
# that they have been altered from the originals.
|
12
|
+
|
13
|
+
r"""
|
14
|
+
================================================================================
|
15
|
+
Fast implementation of objective function class
|
16
|
+
(:mod:`qiskit.synthesis.unitary.aqc.fast_gradient`)
|
17
|
+
================================================================================
|
18
|
+
|
19
|
+
.. currentmodule:: qiskit.synthesis.unitary.aqc.fast_gradient
|
20
|
+
|
21
|
+
Extension to the implementation of Approximate Quantum Compiler as described in the paper [1].
|
22
|
+
|
23
|
+
Interface
|
24
|
+
=========
|
25
|
+
|
26
|
+
The main public class of this module is FastCNOTUnitObjective. It replaces the default objective
|
27
|
+
function implementation :class:`.DefaultCNOTUnitObjective` for faster computation.
|
28
|
+
The individual classes include the public one (FastCNOTUnitObjective) and few
|
29
|
+
internal ones:
|
30
|
+
|
31
|
+
.. autosummary::
|
32
|
+
:toctree: ../stubs
|
33
|
+
:template: autosummary/class_no_inherited_members.rst
|
34
|
+
|
35
|
+
FastCNOTUnitObjective
|
36
|
+
LayerBase
|
37
|
+
Layer1Q
|
38
|
+
Layer2Q
|
39
|
+
PMatrix
|
40
|
+
|
41
|
+
|
42
|
+
Mathematical Details
|
43
|
+
====================
|
44
|
+
|
45
|
+
In what follows we briefly outline the main ideas underlying the accelerated implementation
|
46
|
+
of objective function class.
|
47
|
+
|
48
|
+
* The key ingredient of approximate compiling is the efficient optimization procedure
|
49
|
+
that minimizes :math:`\|V - U\|_{\mathrm{F}}` on a classical computer, where :math:`U`
|
50
|
+
is a given (target) unitary matrix and :math:`V` is a matrix of approximating quantum
|
51
|
+
circuit. Alternatively, we maximize the Hilbert-Schmidt product between :math:`U` and
|
52
|
+
:math:`V` as outlined in the main part of the documentation.
|
53
|
+
|
54
|
+
* The circuit :math:`V` can be represented as a sequence of 2-qubit gates (layers)
|
55
|
+
applied one after another. The corresponding matrix takes the form:
|
56
|
+
:math:`V = C_0 C_1 \ldots C_{L-1} F`, where :math:`L` is the length of the sequence
|
57
|
+
(number of layers). If the total number of qubits :math:`n > 2`, every
|
58
|
+
:math:`C_i = C_i(\Theta_i)` is a sparse, :math:`2^n \times 2^n` matrix of 2-qubit gate
|
59
|
+
(CNOT unit block) parameterized by a sub-set of parameters :math:`\Theta_i`
|
60
|
+
(4 parameters per unit block), and :math:`F` is a matrix that comprises the action
|
61
|
+
of all 1-qubit gates in front of approximating circuit. See the paper [1] for details.
|
62
|
+
|
63
|
+
* Over the course of optimization we compute the value of objective function and its
|
64
|
+
gradient, which implies computation of :math:`V` and its derivatives
|
65
|
+
:math:`{\partial V}/{\partial \Theta_i}` for all :math:`i`, given the current estimation
|
66
|
+
of all the parameters :math:`\Theta`.
|
67
|
+
|
68
|
+
* A naive implementation of the product :math:`V = C_0 C_1 \ldots C_{L-1} F` and its
|
69
|
+
derivatives would include computation and memorization of forward and backward partial
|
70
|
+
products as required by the backtracking algorithm. This is wasteful in terms of
|
71
|
+
performance and resource allocation.
|
72
|
+
|
73
|
+
* Minimization of :math:`\|V - U\|_{\mathrm{F}}^2` is equivalent to maximization of
|
74
|
+
:math:`\text{Re}\left(\text{Tr}\left(U^{\dagger} V\right)\right)`. By cyclic permutation
|
75
|
+
of the sequence of matrices under trace operation, we can avoid memorization of intermediate
|
76
|
+
partial products of gate matrices :math:`C_i`. Note, matrix size grows exponentially with
|
77
|
+
the number of qubits, quickly becoming prohibitively large.
|
78
|
+
|
79
|
+
* Sparse structure of :math:`C_i` can be exploited to speed up matrix-matrix multiplication.
|
80
|
+
However, using sparse matrices as such does not give performance gain because sparse patterns
|
81
|
+
tend to violate data proximity inside the cache memory of modern CPUs. Instead, we make use
|
82
|
+
of special structure of gate matrices :math:`C_i` coupled with permutation ones. Although
|
83
|
+
permutation is not cache friendly either, its impact is seemingly less severe than that
|
84
|
+
of sparse matrix multiplication (at least in Python implementation).
|
85
|
+
|
86
|
+
* On every optimization iteration we, first, compute :math:`V = C_0 C_1 \ldots C_{L-1} F`
|
87
|
+
given the current estimation of all the parameters :math:`\Theta`.
|
88
|
+
|
89
|
+
* As for the gradient of objective function, it can be shown (by moving cyclically around
|
90
|
+
an individual matrices under trace operation) that:
|
91
|
+
|
92
|
+
.. math::
|
93
|
+
\text{Tr}\left( U^{\dagger} \frac{\partial V}{\partial \Theta_{l,k}} \right) =
|
94
|
+
\langle \text{vec}\left(E_l\right), \text{vec}\left(
|
95
|
+
\frac{\partial C_l}{\partial \Theta_{l,k}}\right) \rangle,
|
96
|
+
|
97
|
+
where :math:`\Theta_{l,k}` is a :math:`k`-th parameter of :math:`l`-th CNOT unit block,
|
98
|
+
and :math:`E_l=C_{l-1}\left(C_{l-2}\left(\cdots\left(C_0\left(U^{\dagger}V
|
99
|
+
C_0^{\dagger}\right)C_1^{\dagger}\right) \cdots\right)C_{l-1}^{\dagger}\right)C_l^{\dagger}`
|
100
|
+
is an intermediate matrix.
|
101
|
+
|
102
|
+
* For every :math:`l`-th gradient component, we compute the trace using the matrix
|
103
|
+
:math:`E_l`, then this matrix is updated by multiplication on left and on the right
|
104
|
+
by corresponding gate matrices :math:`C_l` and :math:`C_{l+1}^{\dagger}` respectively
|
105
|
+
and proceed to the next gradient component.
|
106
|
+
|
107
|
+
* We save computations and resources by not storing intermediate partial products of
|
108
|
+
:math:`C_i`. Instead, incrementally updated matrix :math:`E_l` keeps all related
|
109
|
+
information. Also, vectorization of involved matrices (see the above formula) allows
|
110
|
+
us to replace matrix-matrix multiplication by "cheaper" vector-vector one under the
|
111
|
+
trace operation.
|
112
|
+
|
113
|
+
* The matrices :math:`C_i` are sparse. However, even for relatively small matrices
|
114
|
+
(< 1M elements) sparse-dense multiplication can be very slow. Construction of sparse
|
115
|
+
matrices takes a time as well. We should update every gate matrix on each iteration
|
116
|
+
of optimization loop.
|
117
|
+
|
118
|
+
* In fact, any gate matrix :math:`C_i` can be transformed to what we call a standard
|
119
|
+
form: :math:`C_i = P^T \widetilde{C}_i P`, where :math:`P` is an easily computable
|
120
|
+
permutation matrix and :math:`\widetilde{C}_i` has a block-diagonal layout:
|
121
|
+
|
122
|
+
.. math::
|
123
|
+
\widetilde{C}_i = \left(
|
124
|
+
\begin{array}{ccc}
|
125
|
+
G_{4 \times 4} & \ddots & 0 \\
|
126
|
+
\ddots & \ddots & \ddots \\
|
127
|
+
0 & \ddots & G_{4 \times 4}
|
128
|
+
\end{array}
|
129
|
+
\right)
|
130
|
+
|
131
|
+
* The 2-qubit gate matrix :math:`G_{4 \times 4}` is repeated along diagonal of the full
|
132
|
+
:math:`2^n \times 2^n` :math:`\widetilde{C}_i`.
|
133
|
+
|
134
|
+
* We do not actually create neither matrix :math:`\widetilde{C}_i` nor :math:`P`.
|
135
|
+
In fact, only :math:`G_{4 \times 4}` and a permutation array (of size :math:`2^n`)
|
136
|
+
are kept in memory.
|
137
|
+
|
138
|
+
* Consider left-hand side multiplication by some dense, :math:`2^n \times 2^n` matrix :math:`M`:
|
139
|
+
|
140
|
+
.. math::
|
141
|
+
C_i M = P^T \widetilde{C}_i P M = P^T \left( \widetilde{C}_i \left( P M \right) \right)
|
142
|
+
|
143
|
+
* First, we permute rows of :math:`M`, which is equivalent to the product :math:`P M`, but
|
144
|
+
without expensive multiplication of two :math:`2^n \times 2^n` matrices.
|
145
|
+
|
146
|
+
* Second, we compute :math:`\widetilde{C}_i P M` multiplying every block-diagonal sub-matrix
|
147
|
+
:math:`G_{4 \times 4}` by the corresponding rows of :math:`P M`. This is the dense-dense
|
148
|
+
matrix multiplication, which is very well optimized on modern CPUs. Important: the total
|
149
|
+
number of operations is :math:`O(2^{2 n})` in contrast to :math:`O(2^{3 n})` as in general
|
150
|
+
case.
|
151
|
+
|
152
|
+
* Third, we permute rows of :math:`\widetilde{C}_i P M` by applying :math:`P^T`.
|
153
|
+
|
154
|
+
* Right-hand side multiplication is done in a similar way.
|
155
|
+
|
156
|
+
* In summary, we save computational resources by exploiting some properties of 2-qubit gate
|
157
|
+
matrices :math:`C_i` and using hardware optimized multiplication of dense matrices. There
|
158
|
+
is still a room for further improvement, of course.
|
159
|
+
|
160
|
+
References:
|
161
|
+
|
162
|
+
[1]: Liam Madden, Andrea Simonetto, Best Approximate Quantum Compiling Problems.
|
163
|
+
`arXiv:2106.05649 <https://arxiv.org/abs/2106.05649>`_
|
164
|
+
"""
|