qiskit 1.3.0b1__cp39-abi3-win32.whl → 1.3.0rc2__cp39-abi3-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qiskit/VERSION.txt +1 -1
- qiskit/__init__.py +20 -1
- qiskit/_accelerate.pyd +0 -0
- qiskit/assembler/assemble_schedules.py +2 -0
- qiskit/circuit/__init__.py +44 -1
- qiskit/circuit/_standard_gates_commutations.py +585 -0
- qiskit/circuit/barrier.py +2 -0
- qiskit/circuit/controlflow/builder.py +3 -3
- qiskit/circuit/controlflow/if_else.py +13 -5
- qiskit/circuit/controlflow/while_loop.py +10 -2
- qiskit/circuit/delay.py +20 -3
- qiskit/circuit/equivalence.py +13 -214
- qiskit/circuit/gate.py +3 -1
- qiskit/circuit/instruction.py +32 -11
- qiskit/circuit/instructionset.py +2 -0
- qiskit/circuit/library/__init__.py +110 -14
- qiskit/circuit/library/arithmetic/__init__.py +9 -2
- qiskit/circuit/library/arithmetic/adders/__init__.py +1 -0
- qiskit/circuit/library/arithmetic/adders/adder.py +154 -2
- qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +20 -56
- qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +14 -1
- qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +21 -91
- qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
- qiskit/circuit/library/arithmetic/multipliers/__init__.py +1 -0
- qiskit/circuit/library/arithmetic/multipliers/hrs_cumulative_multiplier.py +8 -1
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +94 -3
- qiskit/circuit/library/arithmetic/multipliers/rg_qft_multiplier.py +8 -1
- qiskit/circuit/library/arithmetic/weighted_adder.py +1 -1
- qiskit/circuit/library/basis_change/qft.py +20 -38
- qiskit/circuit/library/blueprintcircuit.py +64 -0
- qiskit/circuit/library/boolean_logic/__init__.py +4 -4
- qiskit/circuit/library/boolean_logic/inner_product.py +81 -4
- qiskit/circuit/library/boolean_logic/quantum_and.py +107 -4
- qiskit/circuit/library/boolean_logic/quantum_or.py +107 -3
- qiskit/circuit/library/boolean_logic/quantum_xor.py +97 -3
- qiskit/circuit/library/data_preparation/__init__.py +6 -3
- qiskit/circuit/library/data_preparation/{z_feature_map.py → _z_feature_map.py} +45 -34
- qiskit/circuit/library/data_preparation/_zz_feature_map.py +150 -0
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +342 -29
- qiskit/circuit/library/fourier_checking.py +72 -11
- qiskit/circuit/library/generalized_gates/__init__.py +1 -1
- qiskit/circuit/library/generalized_gates/diagonal.py +45 -51
- qiskit/circuit/library/generalized_gates/gms.py +67 -14
- qiskit/circuit/library/generalized_gates/gr.py +4 -4
- qiskit/circuit/library/generalized_gates/isometry.py +2 -2
- qiskit/circuit/library/generalized_gates/linear_function.py +12 -6
- qiskit/circuit/library/generalized_gates/mcmt.py +167 -107
- qiskit/circuit/library/generalized_gates/permutation.py +8 -6
- qiskit/circuit/library/generalized_gates/rv.py +8 -9
- qiskit/circuit/library/graph_state.py +93 -10
- qiskit/circuit/library/grover_operator.py +270 -2
- qiskit/circuit/library/hidden_linear_function.py +83 -20
- qiskit/circuit/library/iqp.py +99 -20
- qiskit/circuit/library/n_local/__init__.py +19 -7
- qiskit/circuit/library/n_local/efficient_su2.py +118 -5
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +259 -0
- qiskit/circuit/library/n_local/excitation_preserving.py +130 -6
- qiskit/circuit/library/n_local/n_local.py +406 -5
- qiskit/circuit/library/n_local/pauli_two_design.py +106 -4
- qiskit/circuit/library/n_local/qaoa_ansatz.py +80 -1
- qiskit/circuit/library/n_local/real_amplitudes.py +127 -7
- qiskit/circuit/library/n_local/two_local.py +14 -7
- qiskit/circuit/library/overlap.py +91 -26
- qiskit/circuit/library/pauli_evolution.py +17 -15
- qiskit/circuit/library/phase_estimation.py +80 -4
- qiskit/circuit/library/quantum_volume.py +72 -20
- qiskit/circuit/library/standard_gates/__init__.py +20 -1
- qiskit/circuit/library/standard_gates/dcx.py +2 -1
- qiskit/circuit/library/standard_gates/ecr.py +2 -2
- qiskit/circuit/library/standard_gates/h.py +4 -3
- qiskit/circuit/library/standard_gates/i.py +2 -1
- qiskit/circuit/library/standard_gates/iswap.py +2 -2
- qiskit/circuit/library/standard_gates/p.py +20 -12
- qiskit/circuit/library/standard_gates/r.py +1 -1
- qiskit/circuit/library/standard_gates/rx.py +4 -3
- qiskit/circuit/library/standard_gates/rxx.py +2 -2
- qiskit/circuit/library/standard_gates/ry.py +4 -3
- qiskit/circuit/library/standard_gates/ryy.py +2 -2
- qiskit/circuit/library/standard_gates/rz.py +13 -12
- qiskit/circuit/library/standard_gates/rzx.py +6 -6
- qiskit/circuit/library/standard_gates/rzz.py +1 -1
- qiskit/circuit/library/standard_gates/s.py +4 -4
- qiskit/circuit/library/standard_gates/swap.py +3 -3
- qiskit/circuit/library/standard_gates/sx.py +4 -3
- qiskit/circuit/library/standard_gates/t.py +2 -2
- qiskit/circuit/library/standard_gates/u.py +11 -3
- qiskit/circuit/library/standard_gates/u1.py +65 -15
- qiskit/circuit/library/standard_gates/u2.py +4 -1
- qiskit/circuit/library/standard_gates/u3.py +31 -3
- qiskit/circuit/library/standard_gates/x.py +7 -5
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +2 -2
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +2 -2
- qiskit/circuit/library/standard_gates/y.py +4 -3
- qiskit/circuit/library/standard_gates/z.py +3 -3
- qiskit/circuit/library/templates/clifford/clifford_2_1.py +9 -8
- qiskit/circuit/library/templates/clifford/clifford_2_2.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_2_3.py +9 -7
- qiskit/circuit/library/templates/clifford/clifford_2_4.py +9 -8
- qiskit/circuit/library/templates/clifford/clifford_3_1.py +9 -8
- qiskit/circuit/library/templates/clifford/clifford_4_1.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_4_2.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_4_3.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_4_4.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_5_1.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_6_1.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_6_2.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_6_3.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_6_4.py +9 -8
- qiskit/circuit/library/templates/clifford/clifford_6_5.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_8_1.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_8_2.py +10 -9
- qiskit/circuit/library/templates/clifford/clifford_8_3.py +10 -9
- qiskit/circuit/library/templates/nct/template_nct_2a_1.py +9 -7
- qiskit/circuit/library/templates/nct/template_nct_2a_2.py +10 -8
- qiskit/circuit/library/templates/nct/template_nct_2a_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_4a_1.py +16 -14
- qiskit/circuit/library/templates/nct/template_nct_4a_2.py +14 -12
- qiskit/circuit/library/templates/nct/template_nct_4a_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_4b_1.py +14 -12
- qiskit/circuit/library/templates/nct/template_nct_4b_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_5a_1.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_5a_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_5a_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_5a_4.py +11 -9
- qiskit/circuit/library/templates/nct/template_nct_6a_1.py +11 -9
- qiskit/circuit/library/templates/nct/template_nct_6a_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6a_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6a_4.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6b_1.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6b_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_6c_1.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_7a_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_7b_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_7c_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_7d_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_7e_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_9a_1.py +13 -11
- qiskit/circuit/library/templates/nct/template_nct_9c_1.py +11 -9
- qiskit/circuit/library/templates/nct/template_nct_9c_10.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_11.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_12.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_4.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_5.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_6.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_7.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_8.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9c_9.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_1.py +11 -9
- qiskit/circuit/library/templates/nct/template_nct_9d_10.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_2.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_3.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_4.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_5.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_6.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_7.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_8.py +12 -10
- qiskit/circuit/library/templates/nct/template_nct_9d_9.py +12 -10
- qiskit/circuit/library/templates/rzx/rzx_cy.py +11 -10
- qiskit/circuit/library/templates/rzx/rzx_xz.py +16 -15
- qiskit/circuit/library/templates/rzx/rzx_yz.py +12 -10
- qiskit/circuit/library/templates/rzx/rzx_zz1.py +22 -20
- qiskit/circuit/library/templates/rzx/rzx_zz2.py +16 -15
- qiskit/circuit/library/templates/rzx/rzx_zz3.py +17 -15
- qiskit/circuit/parameter.py +4 -0
- qiskit/circuit/parameterexpression.py +167 -34
- qiskit/circuit/quantumcircuit.py +162 -126
- qiskit/circuit/singleton.py +2 -0
- qiskit/circuit/store.py +2 -0
- qiskit/circuit/twirling.py +145 -0
- qiskit/compiler/assembler.py +17 -4
- qiskit/compiler/scheduler.py +2 -0
- qiskit/compiler/sequencer.py +2 -0
- qiskit/compiler/transpiler.py +81 -26
- qiskit/converters/circuit_to_dag.py +2 -2
- qiskit/converters/circuit_to_dagdependency.py +1 -1
- qiskit/converters/circuit_to_dagdependency_v2.py +1 -1
- qiskit/converters/circuit_to_instruction.py +1 -1
- qiskit/converters/dag_to_circuit.py +7 -5
- qiskit/converters/dag_to_dagdependency.py +1 -1
- qiskit/converters/dag_to_dagdependency_v2.py +1 -1
- qiskit/converters/dagdependency_to_circuit.py +5 -1
- qiskit/converters/dagdependency_to_dag.py +6 -1
- qiskit/dagcircuit/collect_blocks.py +3 -3
- qiskit/dagcircuit/dagdependency.py +18 -5
- qiskit/dagcircuit/dagdependency_v2.py +1 -1
- qiskit/dagcircuit/dagnode.py +2 -2
- qiskit/passmanager/__init__.py +2 -2
- qiskit/primitives/backend_estimator.py +5 -2
- qiskit/primitives/backend_sampler_v2.py +61 -18
- qiskit/primitives/base/base_estimator.py +2 -2
- qiskit/primitives/containers/data_bin.py +9 -1
- qiskit/primitives/statevector_sampler.py +1 -1
- qiskit/primitives/utils.py +1 -1
- qiskit/providers/__init__.py +3 -3
- qiskit/providers/backend.py +12 -1
- qiskit/providers/backend_compat.py +23 -3
- qiskit/providers/basic_provider/basic_simulator.py +12 -2
- qiskit/providers/fake_provider/fake_pulse_backend.py +6 -1
- qiskit/providers/fake_provider/generic_backend_v2.py +46 -30
- qiskit/providers/models/pulsedefaults.py +2 -0
- qiskit/pulse/builder.py +59 -18
- qiskit/pulse/calibration_entries.py +4 -1
- qiskit/pulse/channels.py +2 -0
- qiskit/pulse/exceptions.py +2 -0
- qiskit/pulse/instruction_schedule_map.py +21 -6
- qiskit/pulse/instructions/acquire.py +2 -0
- qiskit/pulse/instructions/delay.py +2 -0
- qiskit/pulse/instructions/directives.py +8 -0
- qiskit/pulse/instructions/frequency.py +3 -0
- qiskit/pulse/instructions/instruction.py +2 -0
- qiskit/pulse/instructions/phase.py +3 -0
- qiskit/pulse/instructions/play.py +2 -0
- qiskit/pulse/instructions/reference.py +2 -0
- qiskit/pulse/instructions/snapshot.py +2 -0
- qiskit/pulse/library/pulse.py +2 -0
- qiskit/pulse/library/symbolic_pulses.py +28 -0
- qiskit/pulse/library/waveform.py +2 -0
- qiskit/pulse/macros.py +1 -1
- qiskit/pulse/schedule.py +12 -13
- qiskit/pulse/transforms/alignments.py +5 -3
- qiskit/pulse/transforms/dag.py +7 -0
- qiskit/qasm2/export.py +5 -3
- qiskit/qasm2/parse.py +46 -2
- qiskit/qasm3/__init__.py +1 -0
- qiskit/qasm3/ast.py +123 -15
- qiskit/qasm3/exporter.py +103 -77
- qiskit/qobj/converters/pulse_instruction.py +6 -4
- qiskit/qpy/__init__.py +181 -0
- qiskit/qpy/binary_io/circuits.py +20 -5
- qiskit/qpy/binary_io/schedules.py +3 -4
- qiskit/qpy/binary_io/value.py +310 -13
- qiskit/qpy/common.py +46 -2
- qiskit/qpy/formats.py +7 -0
- qiskit/qpy/interface.py +40 -4
- qiskit/quantum_info/__init__.py +4 -0
- qiskit/quantum_info/operators/channel/transformations.py +28 -21
- qiskit/quantum_info/operators/dihedral/dihedral.py +1 -1
- qiskit/quantum_info/operators/operator.py +54 -8
- qiskit/quantum_info/operators/symplectic/base_pauli.py +11 -19
- qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
- qiskit/quantum_info/operators/symplectic/clifford_circuits.py +1 -1
- qiskit/quantum_info/operators/symplectic/pauli.py +2 -0
- qiskit/quantum_info/operators/symplectic/pauli_list.py +4 -4
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +23 -2
- qiskit/quantum_info/states/densitymatrix.py +5 -5
- qiskit/quantum_info/states/stabilizerstate.py +1 -1
- qiskit/quantum_info/states/statevector.py +6 -6
- qiskit/result/mitigation/base_readout_mitigator.py +1 -1
- qiskit/result/mitigation/correlated_readout_mitigator.py +9 -1
- qiskit/result/mitigation/local_readout_mitigator.py +9 -1
- qiskit/result/mitigation/utils.py +57 -0
- qiskit/scheduler/config.py +2 -0
- qiskit/scheduler/methods/basic.py +3 -0
- qiskit/scheduler/schedule_circuit.py +2 -0
- qiskit/scheduler/sequence.py +2 -0
- qiskit/synthesis/__init__.py +25 -0
- qiskit/synthesis/arithmetic/__init__.py +16 -0
- qiskit/synthesis/arithmetic/adders/__init__.py +17 -0
- qiskit/synthesis/arithmetic/adders/cdkm_ripple_carry_adder.py +154 -0
- qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +103 -0
- qiskit/synthesis/arithmetic/adders/vbe_ripple_carry_adder.py +161 -0
- qiskit/synthesis/arithmetic/multipliers/__init__.py +16 -0
- qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +102 -0
- qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +99 -0
- qiskit/synthesis/clifford/clifford_decompose_bm.py +1 -2
- qiskit/synthesis/clifford/clifford_decompose_greedy.py +3 -2
- qiskit/synthesis/clifford/clifford_decompose_layers.py +2 -1
- qiskit/synthesis/evolution/__init__.py +1 -0
- qiskit/synthesis/evolution/lie_trotter.py +16 -42
- qiskit/synthesis/evolution/pauli_network.py +80 -0
- qiskit/synthesis/evolution/product_formula.py +165 -238
- qiskit/synthesis/evolution/qdrift.py +36 -29
- qiskit/synthesis/evolution/suzuki_trotter.py +87 -27
- qiskit/synthesis/multi_controlled/__init__.py +1 -0
- qiskit/synthesis/multi_controlled/mcmt_vchain.py +52 -0
- qiskit/synthesis/qft/qft_decompose_full.py +19 -1
- qiskit/synthesis/qft/qft_decompose_lnn.py +2 -1
- qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -1
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +4 -63
- qiskit/synthesis/unitary/qsd.py +5 -5
- qiskit/transpiler/__init__.py +21 -14
- qiskit/transpiler/basepasses.py +1 -1
- qiskit/transpiler/passes/__init__.py +2 -0
- qiskit/transpiler/passes/basis/basis_translator.py +9 -565
- qiskit/transpiler/passes/basis/decompose.py +45 -12
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
- qiskit/transpiler/passes/calibration/pulse_gate.py +4 -2
- qiskit/transpiler/passes/calibration/rx_builder.py +11 -7
- qiskit/transpiler/passes/calibration/rzx_builder.py +46 -30
- qiskit/transpiler/passes/layout/disjoint_utils.py +15 -13
- qiskit/transpiler/passes/layout/sabre_layout.py +7 -2
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +5 -0
- qiskit/transpiler/passes/optimization/__init__.py +1 -0
- qiskit/transpiler/passes/optimization/collect_cliffords.py +19 -3
- qiskit/transpiler/passes/optimization/collect_linear_functions.py +1 -1
- qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
- qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.py +1 -1
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +48 -131
- qiskit/transpiler/passes/optimization/echo_rzx_weyl_decomposition.py +4 -2
- qiskit/transpiler/passes/optimization/elide_permutations.py +9 -32
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +5 -11
- qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
- qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py +1 -1
- qiskit/transpiler/passes/optimization/remove_identity_equiv.py +69 -0
- qiskit/transpiler/passes/optimization/template_matching/backward_match.py +5 -5
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +4 -4
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +2 -2
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +1 -1
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +7 -3
- qiskit/transpiler/passes/routing/star_prerouting.py +2 -2
- qiskit/transpiler/passes/scheduling/alap.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/align_measures.py +2 -2
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +2 -0
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +2 -2
- qiskit/transpiler/passes/scheduling/asap.py +1 -1
- qiskit/transpiler/passes/scheduling/base_scheduler.py +14 -12
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +9 -4
- qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +16 -5
- qiskit/transpiler/passes/scheduling/padding/pad_delay.py +4 -1
- qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +6 -2
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +9 -4
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +262 -99
- qiskit/transpiler/passes/synthesis/hls_plugins.py +637 -7
- qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +3 -3
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +55 -34
- qiskit/transpiler/passes/utils/barrier_before_final_measurements.py +2 -56
- qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +5 -0
- qiskit/transpiler/passes/utils/gate_direction.py +12 -275
- qiskit/transpiler/passes/utils/gates_basis.py +7 -30
- qiskit/transpiler/passes/utils/merge_adjacent_barriers.py +2 -1
- qiskit/transpiler/passmanager_config.py +22 -4
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +40 -14
- qiskit/transpiler/preset_passmanagers/common.py +5 -3
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +125 -42
- qiskit/transpiler/preset_passmanagers/plugin.py +1 -1
- qiskit/transpiler/target.py +74 -16
- qiskit/utils/deprecate_pulse.py +119 -0
- qiskit/visualization/circuit/_utils.py +2 -2
- qiskit/visualization/circuit/circuit_visualization.py +3 -2
- qiskit/visualization/circuit/matplotlib.py +1 -1
- qiskit/visualization/dag_visualization.py +1 -1
- qiskit/visualization/pass_manager_visualization.py +3 -14
- qiskit/visualization/pulse_v2/interface.py +3 -1
- qiskit/visualization/timeline/core.py +25 -2
- qiskit/visualization/timeline/interface.py +12 -0
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/METADATA +9 -8
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/RECORD +357 -346
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/WHEEL +1 -1
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/entry_points.txt +19 -0
- qiskit/circuit/library/data_preparation/zz_feature_map.py +0 -118
- qiskit/synthesis/two_qubit/weyl.py +0 -97
- qiskit/transpiler/passes/synthesis/qubit_tracker.py +0 -132
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/top_level.txt +0 -0
@@ -17,21 +17,28 @@ from __future__ import annotations
|
|
17
17
|
import collections
|
18
18
|
import itertools
|
19
19
|
import typing
|
20
|
-
from collections.abc import Callable, Mapping, Sequence
|
20
|
+
from collections.abc import Callable, Mapping, Sequence, Iterable
|
21
21
|
|
22
22
|
import numpy
|
23
|
-
from qiskit.circuit.
|
23
|
+
from qiskit.circuit.gate import Gate
|
24
|
+
from qiskit.circuit.quantumcircuit import QuantumCircuit, ParameterValueType
|
25
|
+
from qiskit.circuit.parametervector import ParameterVector, ParameterVectorElement
|
24
26
|
from qiskit.circuit.quantumregister import QuantumRegister
|
25
27
|
from qiskit.circuit import (
|
26
28
|
Instruction,
|
27
29
|
Parameter,
|
28
|
-
ParameterVector,
|
29
30
|
ParameterExpression,
|
30
31
|
CircuitInstruction,
|
31
32
|
)
|
32
33
|
from qiskit.exceptions import QiskitError
|
33
34
|
from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping
|
34
|
-
from qiskit.
|
35
|
+
from qiskit.utils.deprecation import deprecate_func
|
36
|
+
|
37
|
+
from qiskit._accelerate.circuit_library import (
|
38
|
+
Block,
|
39
|
+
py_n_local,
|
40
|
+
get_entangler_map as fast_entangler_map,
|
41
|
+
)
|
35
42
|
|
36
43
|
from ..blueprintcircuit import BlueprintCircuit
|
37
44
|
|
@@ -39,6 +46,219 @@ from ..blueprintcircuit import BlueprintCircuit
|
|
39
46
|
if typing.TYPE_CHECKING:
|
40
47
|
import qiskit # pylint: disable=cyclic-import
|
41
48
|
|
49
|
+
# entanglement for an individual block, e.g. if the block is CXGate() and we have
|
50
|
+
# 3 qubits, this could be [(0, 1), (1, 2), (2, 0)]
|
51
|
+
BlockEntanglement = typing.Union[str, Iterable[Iterable[int]]]
|
52
|
+
|
53
|
+
|
54
|
+
def n_local(
|
55
|
+
num_qubits: int,
|
56
|
+
rotation_blocks: str | Gate | Iterable[str | Gate],
|
57
|
+
entanglement_blocks: str | Gate | Iterable[str | Gate],
|
58
|
+
entanglement: (
|
59
|
+
BlockEntanglement
|
60
|
+
| Iterable[BlockEntanglement]
|
61
|
+
| Callable[[int], BlockEntanglement | Iterable[BlockEntanglement]]
|
62
|
+
) = "full",
|
63
|
+
reps: int = 3,
|
64
|
+
insert_barriers: bool = False,
|
65
|
+
parameter_prefix: str = "θ",
|
66
|
+
overwrite_block_parameters: bool = True,
|
67
|
+
skip_final_rotation_layer: bool = False,
|
68
|
+
skip_unentangled_qubits: bool = False,
|
69
|
+
name: str | None = "nlocal",
|
70
|
+
) -> QuantumCircuit:
|
71
|
+
r"""Construct an n-local variational circuit.
|
72
|
+
|
73
|
+
The structure of the n-local circuit are alternating rotation and entanglement layers.
|
74
|
+
In both layers, parameterized circuit-blocks act on the circuit in a defined way.
|
75
|
+
In the rotation layer, the blocks are applied stacked on top of each other, while in the
|
76
|
+
entanglement layer according to the ``entanglement`` strategy.
|
77
|
+
The circuit blocks can have arbitrary sizes (smaller equal to the number of qubits in the
|
78
|
+
circuit). Each layer is repeated ``reps`` times, and by default a final rotation layer is
|
79
|
+
appended.
|
80
|
+
|
81
|
+
For instance, a rotation block on 2 qubits and an entanglement block on 4 qubits using
|
82
|
+
``"linear"`` entanglement yields the following circuit.
|
83
|
+
|
84
|
+
.. parsed-literal::
|
85
|
+
|
86
|
+
┌──────┐ ░ ┌──────┐ ░ ┌──────┐
|
87
|
+
┤0 ├─░─┤0 ├──────────────── ... ─░─┤0 ├
|
88
|
+
│ Rot │ ░ │ │┌──────┐ ░ │ Rot │
|
89
|
+
┤1 ├─░─┤1 ├┤0 ├──────── ... ─░─┤1 ├
|
90
|
+
├──────┤ ░ │ Ent ││ │┌──────┐ ░ ├──────┤
|
91
|
+
┤0 ├─░─┤2 ├┤1 ├┤0 ├ ... ─░─┤0 ├
|
92
|
+
│ Rot │ ░ │ ││ Ent ││ │ ░ │ Rot │
|
93
|
+
┤1 ├─░─┤3 ├┤2 ├┤1 ├ ... ─░─┤1 ├
|
94
|
+
├──────┤ ░ └──────┘│ ││ Ent │ ░ ├──────┤
|
95
|
+
┤0 ├─░─────────┤3 ├┤2 ├ ... ─░─┤0 ├
|
96
|
+
│ Rot │ ░ └──────┘│ │ ░ │ Rot │
|
97
|
+
┤1 ├─░─────────────────┤3 ├ ... ─░─┤1 ├
|
98
|
+
└──────┘ ░ └──────┘ ░ └──────┘
|
99
|
+
|
100
|
+
| |
|
101
|
+
+---------------------------------+
|
102
|
+
repeated reps times
|
103
|
+
|
104
|
+
Entanglement:
|
105
|
+
|
106
|
+
The entanglement describes the connections of the gates in the entanglement layer.
|
107
|
+
For a two-qubit gate for example, the entanglement contains pairs of qubits on which the
|
108
|
+
gate should acts, e.g. ``[[ctrl0, target0], [ctrl1, target1], ...]``.
|
109
|
+
A set of default entanglement strategies is provided and can be selected by name:
|
110
|
+
|
111
|
+
* ``"full"`` entanglement is each qubit is entangled with all the others.
|
112
|
+
* ``"linear"`` entanglement is qubit :math:`i` entangled with qubit :math:`i + 1`,
|
113
|
+
for all :math:`i \in \{0, 1, ... , n - 2\}`, where :math:`n` is the total number of qubits.
|
114
|
+
* ``"reverse_linear"`` entanglement is qubit :math:`i` entangled with qubit :math:`i + 1`,
|
115
|
+
for all :math:`i \in \{n-2, n-3, ... , 1, 0\}`, where :math:`n` is the total number of qubits.
|
116
|
+
Note that if ``entanglement_blocks=="cx"`` then this option provides the same unitary as
|
117
|
+
``"full"`` with fewer entangling gates.
|
118
|
+
* ``"pairwise"`` entanglement is one layer where qubit :math:`i` is entangled with qubit
|
119
|
+
:math:`i + 1`, for all even values of :math:`i`, and then a second layer where qubit :math:`i`
|
120
|
+
is entangled with qubit :math:`i + 1`, for all odd values of :math:`i`.
|
121
|
+
* ``"circular"`` entanglement is linear entanglement but with an additional entanglement of the
|
122
|
+
first and last qubit before the linear part.
|
123
|
+
* ``"sca"`` (shifted-circular-alternating) entanglement is a generalized and modified version
|
124
|
+
of the proposed circuit 14 in `Sim et al. <https://arxiv.org/abs/1905.10876>`__.
|
125
|
+
It consists of circular entanglement where the "long" entanglement connecting the first with
|
126
|
+
the last qubit is shifted by one each block. Furthermore the role of control and target
|
127
|
+
qubits are swapped every block (therefore alternating).
|
128
|
+
|
129
|
+
If an entanglement layer contains multiple blocks, then the entanglement should be
|
130
|
+
given as list of entanglements for each block. For example::
|
131
|
+
|
132
|
+
entanglement_blocks = ["rxx", "ryy"]
|
133
|
+
entanglement = ["full", "linear"] # full for rxx and linear for ryy
|
134
|
+
|
135
|
+
or::
|
136
|
+
|
137
|
+
structure_rxx = [[0, 1], [2, 3]]
|
138
|
+
structure_ryy = [[0, 2]]
|
139
|
+
entanglement = [structure_rxx, structure_ryy]
|
140
|
+
|
141
|
+
Finally, the entanglement can vary in each repetition of the circuit. For this, we
|
142
|
+
support passing a callable that takes as input the layer index and returns the entanglement
|
143
|
+
for the layer in the above format. See the examples below for a concrete example.
|
144
|
+
|
145
|
+
Examples:
|
146
|
+
|
147
|
+
The rotation and entanglement gates can be specified via single strings, if they
|
148
|
+
are made up of a single block per layer:
|
149
|
+
|
150
|
+
.. plot::
|
151
|
+
:include-source:
|
152
|
+
:context:
|
153
|
+
|
154
|
+
from qiskit.circuit.library import n_local
|
155
|
+
|
156
|
+
circuit = n_local(3, "ry", "cx", "linear", reps=2, insert_barriers=True)
|
157
|
+
circuit.draw("mpl")
|
158
|
+
|
159
|
+
Multiple gates per layer can be set by passing a list. Here, for example, we use
|
160
|
+
Pauli-Y and Pauli-Z rotations in the rotation layer:
|
161
|
+
|
162
|
+
.. plot::
|
163
|
+
:include-source:
|
164
|
+
:context:
|
165
|
+
|
166
|
+
circuit = n_local(3, ["ry", "rz"], "cz", "full", reps=1, insert_barriers=True)
|
167
|
+
circuit.draw("mpl")
|
168
|
+
|
169
|
+
To omit rotation or entanglement layers, the block can be set to an empty list:
|
170
|
+
|
171
|
+
.. plot::
|
172
|
+
:include-source:
|
173
|
+
:context:
|
174
|
+
|
175
|
+
circuit = n_local(4, [], "cry", reps=2)
|
176
|
+
circuit.draw("mpl")
|
177
|
+
|
178
|
+
The entanglement can be set explicitly via the ``entanglement`` argument:
|
179
|
+
|
180
|
+
.. plot::
|
181
|
+
:include-source:
|
182
|
+
:context:
|
183
|
+
|
184
|
+
entangler_map = [[0, 1], [2, 0]]
|
185
|
+
circuit = n_local(3, "x", "crx", entangler_map, reps=2)
|
186
|
+
circuit.draw("mpl")
|
187
|
+
|
188
|
+
We can set different entanglements per layer, by specifing a callable that takes
|
189
|
+
as input the current layer index, and returns the entanglement structure. For example,
|
190
|
+
the following uses different entanglements for odd and even layers:
|
191
|
+
|
192
|
+
.. plot:
|
193
|
+
:include-source:
|
194
|
+
:context:
|
195
|
+
|
196
|
+
def entanglement(layer_index):
|
197
|
+
if layer_index % 2 == 0:
|
198
|
+
return [[0, 1], [0, 2]]
|
199
|
+
return [[1, 2]]
|
200
|
+
|
201
|
+
circuit = n_local(3, "x", "cx", entanglement, reps=3, insert_barriers=True)
|
202
|
+
circuit.draw("mpl")
|
203
|
+
|
204
|
+
|
205
|
+
Args:
|
206
|
+
num_qubits: The number of qubits of the circuit.
|
207
|
+
rotation_blocks: The blocks used in the rotation layers. If multiple are passed,
|
208
|
+
these will be applied one after another (like new sub-layers).
|
209
|
+
entanglement_blocks: The blocks used in the entanglement layers. If multiple are passed,
|
210
|
+
these will be applied one after another.
|
211
|
+
entanglement: The indices specifying on which qubits the input blocks act. This is
|
212
|
+
specified by string describing an entanglement strategy (see the additional info)
|
213
|
+
or a list of qubit connections.
|
214
|
+
If a list of entanglement blocks is passed, different entanglement for each block can
|
215
|
+
be specified by passing a list of entanglements. To specify varying entanglement for
|
216
|
+
each repetition, pass a callable that takes as input the layer and returns the
|
217
|
+
entanglement for that layer.
|
218
|
+
Defaults to ``"full"``, meaning an all-to-all entanglement structure.
|
219
|
+
reps: Specifies how often the rotation blocks and entanglement blocks are repeated.
|
220
|
+
insert_barriers: If ``True``, barriers are inserted in between each layer. If ``False``,
|
221
|
+
no barriers are inserted.
|
222
|
+
parameter_prefix: The prefix used if default parameters are generated.
|
223
|
+
overwrite_block_parameters: If the parameters in the added blocks should be overwritten.
|
224
|
+
If ``False``, the parameters in the blocks are not changed.
|
225
|
+
skip_final_rotation_layer: Whether a final rotation layer is added to the circuit.
|
226
|
+
skip_unentangled_qubits: If ``True``, the rotation gates act only on qubits that
|
227
|
+
are entangled. If ``False``, the rotation gates act on all qubits.
|
228
|
+
name: The name of the circuit.
|
229
|
+
|
230
|
+
Returns:
|
231
|
+
An n-local circuit.
|
232
|
+
"""
|
233
|
+
if reps < 0:
|
234
|
+
# this is an important check, since we cast this to an unsigned integer Rust-side
|
235
|
+
raise ValueError(f"reps must be non-negative, but is {reps}")
|
236
|
+
|
237
|
+
supported_gates = get_standard_gate_name_mapping()
|
238
|
+
rotation_blocks = _normalize_blocks(
|
239
|
+
rotation_blocks, supported_gates, overwrite_block_parameters
|
240
|
+
)
|
241
|
+
entanglement_blocks = _normalize_blocks(
|
242
|
+
entanglement_blocks, supported_gates, overwrite_block_parameters
|
243
|
+
)
|
244
|
+
|
245
|
+
entanglement = _normalize_entanglement(entanglement, len(entanglement_blocks))
|
246
|
+
|
247
|
+
data = py_n_local(
|
248
|
+
num_qubits=num_qubits,
|
249
|
+
rotation_blocks=rotation_blocks,
|
250
|
+
entanglement_blocks=entanglement_blocks,
|
251
|
+
entanglement=entanglement,
|
252
|
+
reps=reps,
|
253
|
+
insert_barriers=insert_barriers,
|
254
|
+
parameter_prefix=parameter_prefix,
|
255
|
+
skip_final_rotation_layer=skip_final_rotation_layer,
|
256
|
+
skip_unentangled_qubits=skip_unentangled_qubits,
|
257
|
+
)
|
258
|
+
circuit = QuantumCircuit._from_circuit_data(data, add_regs=True, name=name)
|
259
|
+
|
260
|
+
return circuit
|
261
|
+
|
42
262
|
|
43
263
|
class NLocal(BlueprintCircuit):
|
44
264
|
"""The n-local circuit class.
|
@@ -54,7 +274,7 @@ class NLocal(BlueprintCircuit):
|
|
54
274
|
For instance, a rotation block on 2 qubits and an entanglement block on 4 qubits using
|
55
275
|
``'linear'`` entanglement yields the following circuit.
|
56
276
|
|
57
|
-
..
|
277
|
+
.. code-block:: text
|
58
278
|
|
59
279
|
┌──────┐ ░ ┌──────┐ ░ ┌──────┐
|
60
280
|
┤0 ├─░─┤0 ├──────────────── ... ─░─┤0 ├
|
@@ -76,8 +296,18 @@ class NLocal(BlueprintCircuit):
|
|
76
296
|
|
77
297
|
If specified, barriers can be inserted in between every block.
|
78
298
|
If an initial state object is provided, it is added in front of the NLocal.
|
299
|
+
|
300
|
+
.. seealso::
|
301
|
+
|
302
|
+
The :func:`.n_local` function constructs a functionally equivalent circuit, but faster.
|
303
|
+
|
79
304
|
"""
|
80
305
|
|
306
|
+
@deprecate_func(
|
307
|
+
since="1.3",
|
308
|
+
additional_msg="Use the function qiskit.circuit.library.n_local instead.",
|
309
|
+
pending=True,
|
310
|
+
)
|
81
311
|
def __init__(
|
82
312
|
self,
|
83
313
|
num_qubits: int | None = None,
|
@@ -1069,3 +1299,174 @@ def _stdlib_gate_from_simple_block(block: QuantumCircuit) -> _StdlibGateResult |
|
|
1069
1299
|
):
|
1070
1300
|
return None
|
1071
1301
|
return _StdlibGateResult(instruction.operation.base_class, len(instruction.operation.params))
|
1302
|
+
|
1303
|
+
|
1304
|
+
def _normalize_entanglement(
|
1305
|
+
entanglement: (
|
1306
|
+
BlockEntanglement
|
1307
|
+
| Iterable[BlockEntanglement]
|
1308
|
+
| Callable[[int], BlockEntanglement | Iterable[BlockEntanglement]]
|
1309
|
+
),
|
1310
|
+
num_entanglement_blocks: int,
|
1311
|
+
) -> list[str | list[tuple[int]]] | Callable[[int], list[str | list[tuple[int]]]]:
|
1312
|
+
"""If the entanglement is Iterable[Iterable], normalize to list[tuple]."""
|
1313
|
+
if isinstance(entanglement, str):
|
1314
|
+
return [entanglement] * num_entanglement_blocks
|
1315
|
+
|
1316
|
+
if callable(entanglement):
|
1317
|
+
return lambda offset: _normalize_entanglement(entanglement(offset), num_entanglement_blocks)
|
1318
|
+
|
1319
|
+
# here, entanglement is an Iterable
|
1320
|
+
if len(entanglement) == 0:
|
1321
|
+
# handle edge cases when entanglement is set to an empty list
|
1322
|
+
return [[]]
|
1323
|
+
|
1324
|
+
# if the entanglement is Iterable[Iterable[int]], normalize to Iterable[Iterable[Iterable[int]]]
|
1325
|
+
try:
|
1326
|
+
# if users e.g. gave Iterable[int] this in invalid and will raise a TypeError
|
1327
|
+
if isinstance(entanglement[0][0], (int, numpy.integer)):
|
1328
|
+
entanglement = [entanglement]
|
1329
|
+
except TypeError as exc:
|
1330
|
+
raise TypeError(f"Invalid entanglement type: {entanglement}.") from exc
|
1331
|
+
|
1332
|
+
# ensure the number of block entanglements matches the number of blocks
|
1333
|
+
if len(entanglement) != num_entanglement_blocks:
|
1334
|
+
raise QiskitError(
|
1335
|
+
f"Number of block-entanglements ({len(entanglement)}) must match number of "
|
1336
|
+
f"entanglement blocks ({num_entanglement_blocks})!"
|
1337
|
+
)
|
1338
|
+
|
1339
|
+
# normalize the data: str remains, and Iterable[Iterable[int]] becomes list[tuple[int]]
|
1340
|
+
normalized = []
|
1341
|
+
for block in entanglement:
|
1342
|
+
if isinstance(block, str):
|
1343
|
+
normalized.append(block)
|
1344
|
+
else:
|
1345
|
+
normalized.append([tuple(connections) for connections in block])
|
1346
|
+
|
1347
|
+
return normalized
|
1348
|
+
|
1349
|
+
|
1350
|
+
def _normalize_blocks(
|
1351
|
+
blocks: str | Gate | Iterable[str | Gate],
|
1352
|
+
supported_gates: dict[str, Gate],
|
1353
|
+
overwrite_block_parameters: bool,
|
1354
|
+
) -> list[Block]:
|
1355
|
+
# normalize the input into an iterable -- we add an extra check for a circuit as
|
1356
|
+
# courtesy to the users, since the NLocal class used to accept circuits
|
1357
|
+
if isinstance(blocks, (str, Gate, QuantumCircuit)):
|
1358
|
+
blocks = [blocks]
|
1359
|
+
|
1360
|
+
normalized = []
|
1361
|
+
for block in blocks:
|
1362
|
+
# since the NLocal circuit accepted circuits as inputs, we raise a warning here
|
1363
|
+
# to simplify the transition (even though, strictly speaking, quantum circuits are
|
1364
|
+
# not a supported input type)
|
1365
|
+
if isinstance(block, QuantumCircuit):
|
1366
|
+
raise ValueError(
|
1367
|
+
"The blocks should be of type Gate or str, but you passed a QuantumCircuit. "
|
1368
|
+
"You can call .to_gate() on the circuit to turn it into a Gate object."
|
1369
|
+
)
|
1370
|
+
|
1371
|
+
is_standard = False
|
1372
|
+
if isinstance(block, str):
|
1373
|
+
if block not in supported_gates:
|
1374
|
+
raise ValueError(f"Unsupported gate: {block}")
|
1375
|
+
block = supported_gates[block]
|
1376
|
+
is_standard = True
|
1377
|
+
elif isinstance(block, Gate) and getattr(block, "_standard_gate", None) is not None:
|
1378
|
+
if len(block.params) == 0:
|
1379
|
+
is_standard = True
|
1380
|
+
# the fast path will always overwrite block parameters
|
1381
|
+
elif overwrite_block_parameters:
|
1382
|
+
# if all parameters are plain Parameter objects, this is a plain
|
1383
|
+
# standard gate we do not need to propagate parameterizations for
|
1384
|
+
is_standard = all(isinstance(p, Parameter) for p in block.params)
|
1385
|
+
|
1386
|
+
if is_standard:
|
1387
|
+
block = Block.from_standard_gate(block._standard_gate)
|
1388
|
+
else:
|
1389
|
+
if overwrite_block_parameters:
|
1390
|
+
num_parameters, builder = _get_gate_builder(block)
|
1391
|
+
else:
|
1392
|
+
num_parameters, builder = _trivial_builder(block)
|
1393
|
+
|
1394
|
+
block = Block.from_callable(block.num_qubits, num_parameters, builder)
|
1395
|
+
|
1396
|
+
normalized.append(block)
|
1397
|
+
|
1398
|
+
return normalized
|
1399
|
+
|
1400
|
+
|
1401
|
+
def _trivial_builder(
|
1402
|
+
gate: Gate,
|
1403
|
+
) -> tuple[int, Callable[list[Parameter], tuple[Gate, list[ParameterValueType]]]]:
|
1404
|
+
|
1405
|
+
def builder(_):
|
1406
|
+
copied = gate.copy()
|
1407
|
+
return copied, copied.params
|
1408
|
+
|
1409
|
+
return 0, builder
|
1410
|
+
|
1411
|
+
|
1412
|
+
def _get_gate_builder(
|
1413
|
+
gate: Gate,
|
1414
|
+
) -> tuple[int, Callable[list[Parameter], tuple[Gate, list[ParameterValueType]]]]:
|
1415
|
+
"""Construct a callable that handles parameter-rebinding.
|
1416
|
+
|
1417
|
+
For a given gate, this return the number of free parameters and a callable that can be
|
1418
|
+
used to obtain a re-parameterized version of the gate. For example::
|
1419
|
+
|
1420
|
+
x, y = Parameter("x"), Parameter("y")
|
1421
|
+
gate = CUGate(x, 2 * y, 0.5, 0.)
|
1422
|
+
|
1423
|
+
num_parameters, builder = _build_gate(gate)
|
1424
|
+
print(num_parameters) # prints 2
|
1425
|
+
|
1426
|
+
a, b = Parameter("a"), Parameter("b")
|
1427
|
+
new_gate, new_params = builder([a, b])
|
1428
|
+
print(new_gate) # CUGate(a, 2 * b, 0.5, 0)
|
1429
|
+
print(new_params) # [a, 2 * b, 0.5, 0]
|
1430
|
+
|
1431
|
+
"""
|
1432
|
+
free_parameters = set()
|
1433
|
+
for p in gate.params:
|
1434
|
+
if isinstance(p, ParameterExpression):
|
1435
|
+
free_parameters |= set(p.parameters)
|
1436
|
+
|
1437
|
+
num_parameters = len(free_parameters)
|
1438
|
+
|
1439
|
+
sorted_parameters = _sort_parameters(free_parameters)
|
1440
|
+
|
1441
|
+
def builder(new_parameters):
|
1442
|
+
out = gate.copy()
|
1443
|
+
|
1444
|
+
# re-bind the ``Gate.params`` attribute
|
1445
|
+
param_dict = dict(zip(sorted_parameters, new_parameters))
|
1446
|
+
bound_params = gate.params.copy()
|
1447
|
+
for i, expr in enumerate(gate.params):
|
1448
|
+
if isinstance(expr, ParameterExpression):
|
1449
|
+
for parameter in expr.parameters:
|
1450
|
+
expr = expr.assign(parameter, param_dict[parameter])
|
1451
|
+
bound_params[i] = expr
|
1452
|
+
|
1453
|
+
out.params = bound_params
|
1454
|
+
|
1455
|
+
# if the definition exists, rebind it
|
1456
|
+
if out._definition is not None:
|
1457
|
+
out._definition.assign_parameters(param_dict, inplace=True)
|
1458
|
+
|
1459
|
+
return out, bound_params
|
1460
|
+
|
1461
|
+
return num_parameters, builder
|
1462
|
+
|
1463
|
+
|
1464
|
+
def _sort_parameters(parameters):
|
1465
|
+
"""Sort a list of Parameter objects."""
|
1466
|
+
|
1467
|
+
def key(parameter):
|
1468
|
+
if isinstance(parameter, ParameterVectorElement):
|
1469
|
+
return (parameter.vector.name, parameter.index)
|
1470
|
+
return (parameter.name,)
|
1471
|
+
|
1472
|
+
return sorted(parameters, key=key)
|
@@ -16,9 +16,104 @@ from __future__ import annotations
|
|
16
16
|
import numpy as np
|
17
17
|
|
18
18
|
from qiskit.circuit import QuantumCircuit
|
19
|
+
from qiskit.circuit.library.standard_gates import RXGate, RYGate, RZGate, CZGate
|
20
|
+
from qiskit.utils.deprecation import deprecate_func
|
21
|
+
from qiskit._accelerate.circuit_library import Block, py_n_local
|
22
|
+
from .two_local import TwoLocal
|
19
23
|
|
20
24
|
|
21
|
-
|
25
|
+
def pauli_two_design(
|
26
|
+
num_qubits: int,
|
27
|
+
reps: int = 3,
|
28
|
+
seed: int | None = None,
|
29
|
+
insert_barriers: bool = False,
|
30
|
+
parameter_prefix: str = "θ",
|
31
|
+
name: str = "PauliTwoDesign",
|
32
|
+
) -> QuantumCircuit:
|
33
|
+
r"""Construct a Pauli 2-design ansatz.
|
34
|
+
|
35
|
+
This class implements a particular form of a 2-design circuit [1], which is frequently studied
|
36
|
+
in quantum machine learning literature, such as, e.g., the investigation of Barren plateaus in
|
37
|
+
variational algorithms [2].
|
38
|
+
|
39
|
+
The circuit consists of alternating rotation and entanglement layers with
|
40
|
+
an initial layer of :math:`\sqrt{H} = RY(\pi/4)` gates.
|
41
|
+
The rotation layers contain single qubit Pauli rotations, where the axis is chosen uniformly
|
42
|
+
at random to be X, Y or Z. The entanglement layers is compromised of pairwise CZ gates
|
43
|
+
with a total depth of 2.
|
44
|
+
|
45
|
+
For instance, the circuit could look like this:
|
46
|
+
|
47
|
+
.. parsed-literal::
|
48
|
+
|
49
|
+
┌─────────┐┌──────────┐ ░ ┌──────────┐ ░ ┌──────────┐
|
50
|
+
q_0: ┤ RY(π/4) ├┤ RZ(θ[0]) ├─■─────░─┤ RY(θ[4]) ├─■─────░──┤ RZ(θ[8]) ├
|
51
|
+
├─────────┤├──────────┤ │ ░ ├──────────┤ │ ░ ├──────────┤
|
52
|
+
q_1: ┤ RY(π/4) ├┤ RZ(θ[1]) ├─■──■──░─┤ RY(θ[5]) ├─■──■──░──┤ RX(θ[9]) ├
|
53
|
+
├─────────┤├──────────┤ │ ░ ├──────────┤ │ ░ ┌┴──────────┤
|
54
|
+
q_2: ┤ RY(π/4) ├┤ RX(θ[2]) ├─■──■──░─┤ RY(θ[6]) ├─■──■──░─┤ RX(θ[10]) ├
|
55
|
+
├─────────┤├──────────┤ │ ░ ├──────────┤ │ ░ ├───────────┤
|
56
|
+
q_3: ┤ RY(π/4) ├┤ RZ(θ[3]) ├─■─────░─┤ RX(θ[7]) ├─■─────░─┤ RY(θ[11]) ├
|
57
|
+
└─────────┘└──────────┘ ░ └──────────┘ ░ └───────────┘
|
58
|
+
|
59
|
+
Examples:
|
60
|
+
|
61
|
+
.. plot::
|
62
|
+
:include-source:
|
63
|
+
|
64
|
+
from qiskit.circuit.library import pauli_two_design
|
65
|
+
circuit = pauli_two_design(4, reps=2, seed=5, insert_barriers=True)
|
66
|
+
circuit.draw("mpl")
|
67
|
+
|
68
|
+
Args:
|
69
|
+
num_qubits: The number of qubits of the Pauli Two-Design circuit.
|
70
|
+
reps: Specifies how often a block consisting of a rotation layer and entanglement
|
71
|
+
layer is repeated.
|
72
|
+
seed: The seed for randomly choosing the axes of the Pauli rotations.
|
73
|
+
parameter_prefix: The prefix used for the rotation parameters.
|
74
|
+
insert_barriers: If ``True``, barriers are inserted in between each layer. If ``False``,
|
75
|
+
no barriers are inserted. Defaults to ``False``.
|
76
|
+
name: The circuit name.
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
A Pauli 2-design circuit.
|
80
|
+
|
81
|
+
References:
|
82
|
+
|
83
|
+
[1]: Nakata et al., Unitary 2-designs from random X- and Z-diagonal unitaries.
|
84
|
+
`arXiv:1502.07514 <https://arxiv.org/pdf/1502.07514.pdf>`_
|
85
|
+
|
86
|
+
[2]: McClean et al., Barren plateaus in quantum neural network training landscapes.
|
87
|
+
`arXiv:1803.11173 <https://arxiv.org/pdf/1803.11173.pdf>`_
|
88
|
+
"""
|
89
|
+
rng = np.random.default_rng(seed)
|
90
|
+
random_block = Block.from_callable(1, 1, lambda params: _random_pauli_builder(params, rng))
|
91
|
+
cz_block = Block.from_standard_gate(CZGate._standard_gate)
|
92
|
+
|
93
|
+
data = py_n_local(
|
94
|
+
num_qubits=num_qubits,
|
95
|
+
reps=reps,
|
96
|
+
rotation_blocks=[random_block],
|
97
|
+
entanglement_blocks=[cz_block],
|
98
|
+
entanglement=["pairwise"],
|
99
|
+
insert_barriers=insert_barriers,
|
100
|
+
skip_final_rotation_layer=False,
|
101
|
+
skip_unentangled_qubits=False,
|
102
|
+
parameter_prefix=parameter_prefix,
|
103
|
+
)
|
104
|
+
two_design = QuantumCircuit._from_circuit_data(data)
|
105
|
+
|
106
|
+
circuit = QuantumCircuit(num_qubits, name=name)
|
107
|
+
circuit.ry(np.pi / 4, circuit.qubits)
|
108
|
+
circuit.compose(two_design, inplace=True, copy=False)
|
109
|
+
|
110
|
+
return circuit
|
111
|
+
|
112
|
+
|
113
|
+
def _random_pauli_builder(params, rng):
|
114
|
+
gate_cls = rng.choice([RXGate, RYGate, RZGate])
|
115
|
+
gate = gate_cls(params[0])
|
116
|
+
return gate, gate.params
|
22
117
|
|
23
118
|
|
24
119
|
class PauliTwoDesign(TwoLocal):
|
@@ -37,7 +132,7 @@ class PauliTwoDesign(TwoLocal):
|
|
37
132
|
For instance, the circuit could look like this (but note that choosing a different seed
|
38
133
|
yields different Pauli rotations).
|
39
134
|
|
40
|
-
..
|
135
|
+
.. code-block:: text
|
41
136
|
|
42
137
|
┌─────────┐┌──────────┐ ░ ┌──────────┐ ░ ┌──────────┐
|
43
138
|
q_0: ┤ RY(π/4) ├┤ RZ(θ[0]) ├─■─────░─┤ RY(θ[4]) ├─■─────░──┤ RZ(θ[8]) ├
|
@@ -58,6 +153,10 @@ class PauliTwoDesign(TwoLocal):
|
|
58
153
|
circuit = PauliTwoDesign(4, reps=2, seed=5, insert_barriers=True)
|
59
154
|
circuit.draw('mpl')
|
60
155
|
|
156
|
+
.. seealso::
|
157
|
+
|
158
|
+
The :func:`.pauli_two_design` function constructs the functionally same circuit, but faster.
|
159
|
+
|
61
160
|
References:
|
62
161
|
|
63
162
|
[1]: Nakata et al., Unitary 2-designs from random X- and Z-diagonal unitaries.
|
@@ -67,6 +166,11 @@ class PauliTwoDesign(TwoLocal):
|
|
67
166
|
`arXiv:1803.11173 <https://arxiv.org/pdf/1803.11173.pdf>`_
|
68
167
|
"""
|
69
168
|
|
169
|
+
@deprecate_func(
|
170
|
+
since="1.3",
|
171
|
+
additional_msg="Use the function qiskit.circuit.library.pauli_two_design instead.",
|
172
|
+
pending=True,
|
173
|
+
)
|
70
174
|
def __init__(
|
71
175
|
self,
|
72
176
|
num_qubits: int | None = None,
|
@@ -85,8 +189,6 @@ class PauliTwoDesign(TwoLocal):
|
|
85
189
|
no barriers are inserted. Defaults to ``False``.
|
86
190
|
|
87
191
|
"""
|
88
|
-
from qiskit.circuit.library import RYGate # pylint: disable=cyclic-import
|
89
|
-
|
90
192
|
# store a random number generator
|
91
193
|
self._seed = seed
|
92
194
|
self._rng = np.random.default_rng(seed)
|
@@ -21,8 +21,87 @@ from qiskit.circuit.parametervector import ParameterVector
|
|
21
21
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
22
22
|
from qiskit.circuit.quantumregister import QuantumRegister
|
23
23
|
from qiskit.quantum_info import SparsePauliOp
|
24
|
+
from qiskit.quantum_info.operators.base_operator import BaseOperator
|
25
|
+
|
26
|
+
from .evolved_operator_ansatz import (
|
27
|
+
EvolvedOperatorAnsatz,
|
28
|
+
_is_pauli_identity,
|
29
|
+
evolved_operator_ansatz,
|
30
|
+
)
|
31
|
+
|
32
|
+
|
33
|
+
def qaoa_ansatz(
|
34
|
+
cost_operator: BaseOperator,
|
35
|
+
reps: int = 1,
|
36
|
+
initial_state: QuantumCircuit | None = None,
|
37
|
+
mixer_operator: BaseOperator | None = None,
|
38
|
+
insert_barriers: bool = False,
|
39
|
+
name: str = "QAOA",
|
40
|
+
flatten: bool = True,
|
41
|
+
) -> QuantumCircuit:
|
42
|
+
r"""A generalized QAOA quantum circuit with a support of custom initial states and mixers.
|
43
|
+
|
44
|
+
Examples:
|
45
|
+
|
46
|
+
To define the QAOA ansatz we require a cost Hamiltonian, encoding the classical
|
47
|
+
optimization problem:
|
48
|
+
|
49
|
+
.. plot::
|
50
|
+
:include-source:
|
51
|
+
|
52
|
+
from qiskit.quantum_info import SparsePauliOp
|
53
|
+
from qiskit.circuit.library import qaoa_ansatz
|
54
|
+
|
55
|
+
cost_operator = SparsePauliOp(["ZZII", "IIZZ", "ZIIZ"])
|
56
|
+
ansatz = qaoa_ansatz(cost_operator, reps=3, insert_barriers=True)
|
57
|
+
ansatz.draw("mpl")
|
58
|
+
|
59
|
+
Args:
|
60
|
+
cost_operator: The operator representing the cost of the optimization problem, denoted as
|
61
|
+
:math:`U(C, \gamma)` in [1].
|
62
|
+
reps: The integer determining the depth of the circuit, called :math:`p` in [1].
|
63
|
+
initial_state: An optional initial state to use, which defaults to a layer of
|
64
|
+
Hadamard gates preparing the :math:`|+\rangle^{\otimes n}` state.
|
65
|
+
If a custom mixer is chosen, this circuit should be set to prepare its ground state,
|
66
|
+
to appropriately fulfill the annealing conditions.
|
67
|
+
mixer_operator: An optional custom mixer, which defaults to global Pauli-:math:`X`
|
68
|
+
rotations. This is denoted as :math:`U(B, \beta)` in [1]. If this is set,
|
69
|
+
the ``initial_state`` might also require modification.
|
70
|
+
insert_barriers: Whether to insert barriers in-between the cost and mixer operators.
|
71
|
+
name: The name of the circuit.
|
72
|
+
flatten: If ``True``, a flat circuit is returned instead of nesting it inside multiple
|
73
|
+
layers of gate objects. Setting this to ``False`` is significantly less performant,
|
74
|
+
especially for parameter binding, but can be desirable for a cleaner visualization.
|
24
75
|
|
25
|
-
|
76
|
+
References:
|
77
|
+
|
78
|
+
[1]: Farhi et al., A Quantum Approximate Optimization Algorithm.
|
79
|
+
`arXiv:1411.4028 <https://arxiv.org/pdf/1411.4028>`_
|
80
|
+
"""
|
81
|
+
num_qubits = cost_operator.num_qubits
|
82
|
+
|
83
|
+
if initial_state is None:
|
84
|
+
initial_state = QuantumCircuit(num_qubits)
|
85
|
+
initial_state.h(range(num_qubits))
|
86
|
+
|
87
|
+
if mixer_operator is None:
|
88
|
+
mixer_operator = SparsePauliOp.from_sparse_list(
|
89
|
+
[("X", [i], 1) for i in range(num_qubits)], num_qubits
|
90
|
+
)
|
91
|
+
|
92
|
+
parameter_prefix = ["γ", "β"]
|
93
|
+
|
94
|
+
return initial_state.compose(
|
95
|
+
evolved_operator_ansatz(
|
96
|
+
[cost_operator, mixer_operator],
|
97
|
+
reps=reps,
|
98
|
+
insert_barriers=insert_barriers,
|
99
|
+
parameter_prefix=parameter_prefix,
|
100
|
+
name=name,
|
101
|
+
flatten=flatten,
|
102
|
+
),
|
103
|
+
copy=False,
|
104
|
+
)
|
26
105
|
|
27
106
|
|
28
107
|
class QAOAAnsatz(EvolvedOperatorAnsatz):
|