qiskit 1.1.2__cp38-abi3-macosx_10_9_universal2.whl → 1.2.0rc1__cp38-abi3-macosx_10_9_universal2.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 +27 -24
- qiskit/_accelerate.abi3.so +0 -0
- qiskit/_numpy_compat.py +1 -1
- qiskit/assembler/assemble_circuits.py +107 -64
- qiskit/assembler/assemble_schedules.py +5 -12
- qiskit/assembler/disassemble.py +10 -1
- qiskit/circuit/__init__.py +1 -1
- qiskit/circuit/_classical_resource_map.py +5 -5
- qiskit/circuit/_utils.py +0 -13
- qiskit/circuit/add_control.py +1 -1
- qiskit/circuit/annotated_operation.py +23 -1
- qiskit/circuit/classical/expr/expr.py +4 -4
- qiskit/circuit/classical/expr/visitors.py +1 -1
- qiskit/circuit/classical/types/__init__.py +1 -1
- qiskit/circuit/classical/types/types.py +2 -2
- qiskit/circuit/classicalfunction/boolean_expression.py +1 -1
- qiskit/circuit/classicalfunction/classical_function_visitor.py +5 -5
- qiskit/circuit/classicalfunction/utils.py +1 -1
- qiskit/circuit/classicalregister.py +1 -1
- qiskit/circuit/commutation_checker.py +83 -35
- qiskit/circuit/controlflow/_builder_utils.py +1 -1
- qiskit/circuit/controlflow/builder.py +10 -6
- qiskit/circuit/controlflow/if_else.py +2 -2
- qiskit/circuit/controlflow/switch_case.py +1 -1
- qiskit/circuit/delay.py +1 -1
- qiskit/circuit/duration.py +2 -2
- qiskit/circuit/equivalence.py +5 -7
- qiskit/circuit/gate.py +11 -8
- qiskit/circuit/instruction.py +31 -13
- qiskit/circuit/instructionset.py +2 -5
- qiskit/circuit/library/__init__.py +2 -1
- qiskit/circuit/library/arithmetic/linear_amplitude_function.py +1 -1
- qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +3 -3
- qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +1 -1
- qiskit/circuit/library/basis_change/__init__.py +1 -1
- qiskit/circuit/library/basis_change/qft.py +40 -6
- qiskit/circuit/library/blueprintcircuit.py +3 -5
- qiskit/circuit/library/data_preparation/__init__.py +9 -2
- qiskit/circuit/library/data_preparation/initializer.py +8 -0
- qiskit/circuit/library/data_preparation/state_preparation.py +98 -178
- qiskit/circuit/library/generalized_gates/isometry.py +8 -8
- qiskit/circuit/library/generalized_gates/linear_function.py +3 -2
- qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +4 -4
- qiskit/circuit/library/generalized_gates/permutation.py +8 -9
- qiskit/circuit/library/generalized_gates/uc.py +3 -3
- qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +2 -2
- qiskit/circuit/library/generalized_gates/unitary.py +13 -11
- qiskit/circuit/library/graph_state.py +1 -1
- qiskit/circuit/library/hamiltonian_gate.py +1 -2
- qiskit/circuit/library/hidden_linear_function.py +1 -1
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +3 -2
- qiskit/circuit/library/n_local/n_local.py +4 -5
- qiskit/circuit/library/n_local/pauli_two_design.py +1 -1
- qiskit/circuit/library/n_local/qaoa_ansatz.py +6 -8
- qiskit/circuit/library/n_local/two_local.py +1 -1
- qiskit/circuit/library/overlap.py +11 -5
- qiskit/circuit/library/pauli_evolution.py +7 -3
- qiskit/circuit/library/standard_gates/dcx.py +3 -0
- qiskit/circuit/library/standard_gates/ecr.py +3 -0
- qiskit/circuit/library/standard_gates/global_phase.py +3 -0
- qiskit/circuit/library/standard_gates/h.py +13 -5
- qiskit/circuit/library/standard_gates/i.py +3 -0
- qiskit/circuit/library/standard_gates/iswap.py +3 -0
- qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +19 -10
- qiskit/circuit/library/standard_gates/p.py +14 -9
- qiskit/circuit/library/standard_gates/r.py +3 -0
- qiskit/circuit/library/standard_gates/rx.py +21 -6
- qiskit/circuit/library/standard_gates/rxx.py +40 -1
- qiskit/circuit/library/standard_gates/ry.py +21 -6
- qiskit/circuit/library/standard_gates/ryy.py +40 -1
- qiskit/circuit/library/standard_gates/rz.py +22 -6
- qiskit/circuit/library/standard_gates/rzx.py +40 -1
- qiskit/circuit/library/standard_gates/rzz.py +41 -2
- qiskit/circuit/library/standard_gates/s.py +77 -0
- qiskit/circuit/library/standard_gates/swap.py +12 -5
- qiskit/circuit/library/standard_gates/sx.py +14 -5
- qiskit/circuit/library/standard_gates/t.py +5 -0
- qiskit/circuit/library/standard_gates/u.py +22 -7
- qiskit/circuit/library/standard_gates/u1.py +8 -3
- qiskit/circuit/library/standard_gates/u2.py +3 -0
- qiskit/circuit/library/standard_gates/u3.py +22 -7
- qiskit/circuit/library/standard_gates/x.py +156 -92
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +40 -1
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +52 -11
- qiskit/circuit/library/standard_gates/y.py +6 -1
- qiskit/circuit/library/standard_gates/z.py +8 -1
- qiskit/circuit/operation.py +1 -1
- qiskit/circuit/parameter.py +9 -10
- qiskit/circuit/parameterexpression.py +16 -13
- qiskit/circuit/parametertable.py +1 -190
- qiskit/circuit/parametervector.py +1 -1
- qiskit/circuit/quantumcircuit.py +392 -384
- qiskit/circuit/quantumcircuitdata.py +3 -5
- qiskit/circuit/quantumregister.py +1 -1
- qiskit/circuit/random/__init__.py +1 -1
- qiskit/circuit/random/utils.py +175 -26
- qiskit/circuit/register.py +5 -7
- qiskit/circuit/singleton.py +3 -3
- qiskit/circuit/tools/pi_check.py +4 -4
- qiskit/compiler/assembler.py +95 -24
- qiskit/compiler/scheduler.py +2 -2
- qiskit/compiler/transpiler.py +41 -127
- qiskit/converters/circuit_to_dag.py +4 -6
- qiskit/converters/circuit_to_gate.py +4 -8
- qiskit/converters/circuit_to_instruction.py +5 -17
- qiskit/converters/dag_to_circuit.py +2 -6
- qiskit/dagcircuit/collect_blocks.py +2 -2
- qiskit/dagcircuit/dagcircuit.py +190 -187
- qiskit/dagcircuit/dagdependency.py +4 -4
- qiskit/dagcircuit/dagdependency_v2.py +4 -4
- qiskit/dagcircuit/dagdepnode.py +1 -1
- qiskit/dagcircuit/dagnode.py +66 -157
- qiskit/passmanager/flow_controllers.py +1 -1
- qiskit/passmanager/passmanager.py +3 -3
- qiskit/primitives/__init__.py +1 -5
- qiskit/primitives/backend_estimator.py +25 -15
- qiskit/primitives/backend_estimator_v2.py +31 -7
- qiskit/primitives/backend_sampler.py +21 -12
- qiskit/primitives/backend_sampler_v2.py +12 -3
- qiskit/primitives/base/base_estimator.py +31 -4
- qiskit/primitives/base/base_primitive.py +2 -2
- qiskit/primitives/base/base_result.py +2 -2
- qiskit/primitives/base/base_sampler.py +26 -2
- qiskit/primitives/base/estimator_result.py +2 -2
- qiskit/primitives/base/sampler_result.py +2 -2
- qiskit/primitives/containers/__init__.py +0 -1
- qiskit/primitives/containers/bindings_array.py +2 -2
- qiskit/primitives/containers/bit_array.py +108 -10
- qiskit/primitives/containers/shape.py +3 -3
- qiskit/primitives/estimator.py +9 -2
- qiskit/primitives/primitive_job.py +1 -1
- qiskit/primitives/sampler.py +10 -3
- qiskit/primitives/statevector_estimator.py +5 -3
- qiskit/primitives/statevector_sampler.py +11 -5
- qiskit/primitives/utils.py +16 -0
- qiskit/providers/backend.py +15 -6
- qiskit/providers/backend_compat.py +7 -4
- qiskit/providers/basic_provider/basic_provider_tools.py +1 -1
- qiskit/providers/basic_provider/basic_simulator.py +32 -24
- qiskit/providers/fake_provider/fake_backend.py +10 -3
- qiskit/providers/fake_provider/fake_openpulse_2q.py +154 -146
- qiskit/providers/fake_provider/fake_openpulse_3q.py +226 -217
- qiskit/providers/fake_provider/fake_qasm_backend.py +5 -1
- qiskit/providers/fake_provider/generic_backend_v2.py +80 -50
- qiskit/providers/models/__init__.py +11 -0
- qiskit/providers/models/backendconfiguration.py +50 -4
- qiskit/providers/models/backendproperties.py +13 -2
- qiskit/providers/models/pulsedefaults.py +10 -11
- qiskit/providers/options.py +13 -13
- qiskit/providers/providerutils.py +3 -1
- qiskit/pulse/configuration.py +8 -12
- qiskit/pulse/instruction_schedule_map.py +3 -5
- qiskit/pulse/instructions/acquire.py +7 -8
- qiskit/pulse/instructions/instruction.py +2 -3
- qiskit/pulse/library/samplers/decorators.py +5 -9
- qiskit/pulse/library/symbolic_pulses.py +4 -7
- qiskit/pulse/library/waveform.py +2 -5
- qiskit/pulse/macros.py +11 -6
- qiskit/pulse/parser.py +8 -10
- qiskit/pulse/schedule.py +9 -17
- qiskit/pulse/transforms/alignments.py +1 -3
- qiskit/pulse/utils.py +1 -2
- qiskit/qasm/libs/stdgates.inc +35 -28
- qiskit/qasm2/__init__.py +7 -7
- qiskit/qasm2/export.py +5 -9
- qiskit/qasm2/parse.py +1 -1
- qiskit/qasm3/ast.py +9 -25
- qiskit/qasm3/exporter.py +578 -481
- qiskit/qasm3/printer.py +7 -16
- qiskit/qobj/common.py +10 -0
- qiskit/qobj/converters/lo_config.py +9 -0
- qiskit/qobj/converters/pulse_instruction.py +13 -6
- qiskit/qobj/pulse_qobj.py +69 -15
- qiskit/qobj/qasm_qobj.py +72 -20
- qiskit/qobj/utils.py +9 -0
- qiskit/qpy/binary_io/circuits.py +8 -5
- qiskit/qpy/binary_io/schedules.py +1 -1
- qiskit/qpy/binary_io/value.py +3 -3
- qiskit/qpy/interface.py +3 -2
- qiskit/qpy/type_keys.py +2 -2
- qiskit/quantum_info/operators/channel/quantum_channel.py +3 -6
- qiskit/quantum_info/operators/channel/superop.py +2 -2
- qiskit/quantum_info/operators/channel/transformations.py +1 -1
- qiskit/quantum_info/operators/dihedral/dihedral.py +3 -4
- qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +1 -3
- qiskit/quantum_info/operators/dihedral/random.py +6 -3
- qiskit/quantum_info/operators/measures.py +2 -2
- qiskit/quantum_info/operators/op_shape.py +12 -20
- qiskit/quantum_info/operators/operator.py +14 -21
- qiskit/quantum_info/operators/predicates.py +1 -0
- qiskit/quantum_info/operators/symplectic/base_pauli.py +7 -11
- qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
- qiskit/quantum_info/operators/symplectic/pauli.py +3 -3
- qiskit/quantum_info/operators/symplectic/pauli_list.py +9 -10
- qiskit/quantum_info/operators/symplectic/random.py +1 -1
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +14 -16
- qiskit/quantum_info/quaternion.py +1 -1
- qiskit/quantum_info/states/densitymatrix.py +5 -8
- qiskit/quantum_info/states/stabilizerstate.py +128 -37
- qiskit/quantum_info/states/statevector.py +4 -8
- qiskit/result/counts.py +2 -2
- qiskit/result/mitigation/correlated_readout_mitigator.py +2 -2
- qiskit/result/mitigation/local_readout_mitigator.py +2 -2
- qiskit/result/mitigation/utils.py +1 -3
- qiskit/result/models.py +17 -16
- qiskit/result/result.py +15 -20
- qiskit/scheduler/lowering.py +2 -2
- qiskit/synthesis/__init__.py +2 -1
- qiskit/synthesis/clifford/__init__.py +1 -1
- qiskit/synthesis/clifford/clifford_decompose_ag.py +2 -2
- qiskit/synthesis/clifford/clifford_decompose_bm.py +10 -240
- qiskit/synthesis/clifford/clifford_decompose_greedy.py +9 -303
- qiskit/synthesis/clifford/clifford_decompose_layers.py +25 -23
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +1 -1
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +1 -1
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +1 -1
- qiskit/synthesis/discrete_basis/solovay_kitaev.py +2 -2
- qiskit/synthesis/evolution/evolution_synthesis.py +4 -2
- qiskit/synthesis/evolution/lie_trotter.py +46 -19
- qiskit/synthesis/evolution/product_formula.py +111 -55
- qiskit/synthesis/evolution/qdrift.py +40 -10
- qiskit/synthesis/evolution/suzuki_trotter.py +43 -33
- qiskit/synthesis/linear/__init__.py +1 -0
- qiskit/synthesis/linear/cnot_synth.py +22 -96
- qiskit/synthesis/linear/linear_depth_lnn.py +8 -8
- qiskit/synthesis/linear/linear_matrix_utils.py +13 -161
- qiskit/synthesis/linear_phase/cnot_phase_synth.py +1 -1
- qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +3 -3
- qiskit/synthesis/linear_phase/cz_depth_lnn.py +1 -1
- qiskit/synthesis/one_qubit/one_qubit_decompose.py +29 -29
- qiskit/synthesis/permutation/permutation_full.py +5 -29
- qiskit/synthesis/permutation/permutation_lnn.py +2 -24
- qiskit/synthesis/permutation/permutation_utils.py +2 -59
- qiskit/synthesis/qft/__init__.py +1 -0
- qiskit/synthesis/qft/qft_decompose_full.py +79 -0
- qiskit/synthesis/qft/qft_decompose_lnn.py +17 -9
- qiskit/synthesis/stabilizer/stabilizer_circuit.py +6 -6
- qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -2
- qiskit/synthesis/two_qubit/local_invariance.py +8 -38
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +48 -129
- qiskit/synthesis/unitary/aqc/cnot_structures.py +1 -1
- qiskit/synthesis/unitary/qsd.py +5 -3
- qiskit/transpiler/__init__.py +1 -0
- qiskit/transpiler/basepasses.py +1 -1
- qiskit/transpiler/coupling.py +3 -3
- qiskit/transpiler/instruction_durations.py +1 -2
- qiskit/transpiler/layout.py +3 -3
- qiskit/transpiler/passes/__init__.py +2 -0
- qiskit/transpiler/passes/basis/basis_translator.py +82 -63
- qiskit/transpiler/passes/basis/translate_parameterized.py +3 -5
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +10 -10
- qiskit/transpiler/passes/calibration/rx_builder.py +3 -3
- qiskit/transpiler/passes/calibration/rzx_builder.py +3 -3
- qiskit/transpiler/passes/layout/apply_layout.py +13 -3
- qiskit/transpiler/passes/layout/sabre_layout.py +10 -8
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +4 -1
- qiskit/transpiler/passes/layout/set_layout.py +2 -2
- qiskit/transpiler/passes/layout/vf2_layout.py +1 -1
- qiskit/transpiler/passes/layout/vf2_utils.py +3 -3
- qiskit/transpiler/passes/optimization/__init__.py +1 -0
- qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
- qiskit/transpiler/passes/optimization/commutation_analysis.py +7 -10
- qiskit/transpiler/passes/optimization/commutative_cancellation.py +35 -19
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +11 -8
- qiskit/transpiler/passes/optimization/inverse_cancellation.py +6 -6
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +64 -41
- qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
- qiskit/transpiler/passes/optimization/split_2q_unitaries.py +83 -0
- qiskit/transpiler/passes/optimization/template_matching/backward_match.py +1 -1
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +2 -2
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +1 -1
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -2
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
- qiskit/transpiler/passes/routing/layout_transformation.py +2 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +35 -26
- qiskit/transpiler/passes/routing/star_prerouting.py +80 -105
- qiskit/transpiler/passes/routing/stochastic_swap.py +1 -3
- qiskit/transpiler/passes/scheduling/alap.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -2
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +1 -1
- qiskit/transpiler/passes/scheduling/asap.py +1 -2
- qiskit/transpiler/passes/scheduling/base_scheduler.py +5 -5
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +3 -3
- qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +11 -11
- qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +7 -6
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +4 -3
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +211 -36
- qiskit/transpiler/passes/synthesis/plugin.py +2 -2
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +80 -40
- qiskit/transpiler/passes/utils/__init__.py +0 -1
- qiskit/transpiler/passes/utils/check_gate_direction.py +4 -4
- qiskit/transpiler/passes/utils/check_map.py +3 -6
- qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +3 -4
- qiskit/transpiler/passes/utils/error.py +2 -2
- qiskit/transpiler/passes/utils/fixed_point.py +3 -3
- qiskit/transpiler/passes/utils/gate_direction.py +1 -1
- qiskit/transpiler/passes/utils/gates_basis.py +1 -2
- qiskit/transpiler/passmanager.py +7 -6
- qiskit/transpiler/preset_passmanagers/__init__.py +4 -228
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +117 -18
- qiskit/transpiler/preset_passmanagers/common.py +3 -6
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +518 -0
- qiskit/transpiler/preset_passmanagers/level0.py +1 -1
- qiskit/transpiler/target.py +27 -8
- qiskit/user_config.py +29 -6
- qiskit/utils/classtools.py +3 -3
- qiskit/utils/deprecation.py +3 -2
- qiskit/utils/lazy_tester.py +2 -2
- qiskit/utils/optionals.py +8 -8
- qiskit/visualization/bloch.py +19 -67
- qiskit/visualization/circuit/_utils.py +34 -10
- qiskit/visualization/circuit/circuit_visualization.py +23 -16
- qiskit/visualization/circuit/latex.py +29 -27
- qiskit/visualization/circuit/matplotlib.py +4 -2
- qiskit/visualization/circuit/qcstyle.py +2 -2
- qiskit/visualization/circuit/text.py +9 -15
- qiskit/visualization/dag_visualization.py +5 -12
- qiskit/visualization/pulse_v2/core.py +1 -1
- qiskit/visualization/pulse_v2/events.py +1 -1
- qiskit/visualization/pulse_v2/generators/frame.py +3 -4
- qiskit/visualization/pulse_v2/generators/waveform.py +5 -9
- qiskit/visualization/pulse_v2/layouts.py +1 -5
- qiskit/visualization/pulse_v2/plotters/matplotlib.py +1 -2
- qiskit/visualization/state_visualization.py +5 -6
- qiskit/visualization/timeline/plotters/matplotlib.py +1 -2
- qiskit/visualization/transition_visualization.py +7 -2
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/METADATA +26 -26
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/RECORD +340 -338
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/WHEEL +1 -1
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/entry_points.txt +3 -0
- qiskit/transpiler/passes/utils/block_to_matrix.py +0 -47
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
# This code is part of Qiskit.
|
2
2
|
#
|
3
|
-
# (C) Copyright IBM 2021,
|
3
|
+
# (C) Copyright IBM 2021, 2024.
|
4
4
|
#
|
5
5
|
# This code is licensed under the Apache License, Version 2.0. You may
|
6
6
|
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
@@ -10,25 +10,15 @@
|
|
10
10
|
# copyright notice, and modified files need to carry a notice indicating
|
11
11
|
# that they have been altered from the originals.
|
12
12
|
"""
|
13
|
-
Circuit synthesis for 2-qubit and 3-qubit Cliffords
|
13
|
+
Circuit synthesis for 2-qubit and 3-qubit Cliffords based on Bravyi & Maslov
|
14
|
+
decomposition.
|
14
15
|
"""
|
15
|
-
# pylint: disable=invalid-name
|
16
|
-
|
17
|
-
# ---------------------------------------------------------------------
|
18
|
-
# Synthesis based on Bravyi & Maslov decomposition
|
19
|
-
# ---------------------------------------------------------------------
|
20
|
-
|
21
|
-
|
22
|
-
from itertools import product
|
23
|
-
import numpy as np
|
24
16
|
|
25
17
|
from qiskit.circuit import QuantumCircuit
|
26
18
|
from qiskit.quantum_info import Clifford
|
27
|
-
|
28
|
-
from qiskit.
|
29
|
-
|
30
|
-
_append_v,
|
31
|
-
_append_w,
|
19
|
+
|
20
|
+
from qiskit._accelerate.synthesis.clifford import (
|
21
|
+
synth_clifford_bm as synth_clifford_bm_inner,
|
32
22
|
)
|
33
23
|
|
34
24
|
|
@@ -50,228 +40,8 @@ def synth_clifford_bm(clifford: Clifford) -> QuantumCircuit:
|
|
50
40
|
structure of the Clifford group*,
|
51
41
|
`arXiv:2003.09412 [quant-ph] <https://arxiv.org/abs/2003.09412>`_
|
52
42
|
"""
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if num_qubits == 1:
|
59
|
-
return _decompose_clifford_1q(clifford.tableau)
|
60
|
-
|
61
|
-
clifford_name = str(clifford)
|
62
|
-
|
63
|
-
# Inverse of final decomposed circuit
|
64
|
-
inv_circuit = QuantumCircuit(num_qubits, name="inv_circ")
|
65
|
-
|
66
|
-
# CNOT cost of clifford
|
67
|
-
cost = _cx_cost(clifford)
|
68
|
-
|
69
|
-
# Find composition of circuits with CX and (H.S)^a gates to reduce CNOT count
|
70
|
-
while cost > 0:
|
71
|
-
clifford, inv_circuit, cost = _reduce_cost(clifford, inv_circuit, cost)
|
72
|
-
|
73
|
-
# Decompose the remaining product of 1-qubit cliffords
|
74
|
-
ret_circ = QuantumCircuit(num_qubits, name=clifford_name)
|
75
|
-
for qubit in range(num_qubits):
|
76
|
-
pos = [qubit, qubit + num_qubits]
|
77
|
-
circ = _decompose_clifford_1q(clifford.tableau[pos][:, pos + [-1]])
|
78
|
-
if len(circ) > 0:
|
79
|
-
ret_circ.append(circ, [qubit])
|
80
|
-
|
81
|
-
# Add the inverse of the 2-qubit reductions circuit
|
82
|
-
if len(inv_circuit) > 0:
|
83
|
-
ret_circ.append(inv_circuit.inverse(), range(num_qubits))
|
84
|
-
|
85
|
-
return ret_circ.decompose()
|
86
|
-
|
87
|
-
|
88
|
-
# ---------------------------------------------------------------------
|
89
|
-
# 1-qubit Clifford decomposition
|
90
|
-
# ---------------------------------------------------------------------
|
91
|
-
|
92
|
-
|
93
|
-
def _decompose_clifford_1q(tableau):
|
94
|
-
"""Decompose a single-qubit clifford"""
|
95
|
-
circuit = QuantumCircuit(1, name="temp")
|
96
|
-
|
97
|
-
# Add phase correction
|
98
|
-
destab_phase, stab_phase = tableau[:, 2]
|
99
|
-
if destab_phase and not stab_phase:
|
100
|
-
circuit.z(0)
|
101
|
-
elif not destab_phase and stab_phase:
|
102
|
-
circuit.x(0)
|
103
|
-
elif destab_phase and stab_phase:
|
104
|
-
circuit.y(0)
|
105
|
-
destab_phase_label = "-" if destab_phase else "+"
|
106
|
-
stab_phase_label = "-" if stab_phase else "+"
|
107
|
-
|
108
|
-
destab_x, destab_z = tableau[0, 0], tableau[0, 1]
|
109
|
-
stab_x, stab_z = tableau[1, 0], tableau[1, 1]
|
110
|
-
|
111
|
-
# Z-stabilizer
|
112
|
-
if stab_z and not stab_x:
|
113
|
-
stab_label = "Z"
|
114
|
-
if destab_z:
|
115
|
-
destab_label = "Y"
|
116
|
-
circuit.s(0)
|
117
|
-
else:
|
118
|
-
destab_label = "X"
|
119
|
-
|
120
|
-
# X-stabilizer
|
121
|
-
elif not stab_z and stab_x:
|
122
|
-
stab_label = "X"
|
123
|
-
if destab_x:
|
124
|
-
destab_label = "Y"
|
125
|
-
circuit.sdg(0)
|
126
|
-
else:
|
127
|
-
destab_label = "Z"
|
128
|
-
circuit.h(0)
|
129
|
-
|
130
|
-
# Y-stabilizer
|
131
|
-
else:
|
132
|
-
stab_label = "Y"
|
133
|
-
if destab_z:
|
134
|
-
destab_label = "Z"
|
135
|
-
else:
|
136
|
-
destab_label = "X"
|
137
|
-
circuit.s(0)
|
138
|
-
circuit.h(0)
|
139
|
-
circuit.s(0)
|
140
|
-
|
141
|
-
# Add circuit name
|
142
|
-
name_destab = f"Destabilizer = ['{destab_phase_label}{destab_label}']"
|
143
|
-
name_stab = f"Stabilizer = ['{stab_phase_label}{stab_label}']"
|
144
|
-
circuit.name = f"Clifford: {name_stab}, {name_destab}"
|
43
|
+
circuit = QuantumCircuit._from_circuit_data(
|
44
|
+
synth_clifford_bm_inner(clifford.tableau.astype(bool))
|
45
|
+
)
|
46
|
+
circuit.name = str(clifford)
|
145
47
|
return circuit
|
146
|
-
|
147
|
-
|
148
|
-
# ---------------------------------------------------------------------
|
149
|
-
# Helper functions for Bravyi & Maslov decomposition
|
150
|
-
# ---------------------------------------------------------------------
|
151
|
-
|
152
|
-
|
153
|
-
def _reduce_cost(clifford, inv_circuit, cost):
|
154
|
-
"""Two-qubit cost reduction step"""
|
155
|
-
num_qubits = clifford.num_qubits
|
156
|
-
for qubit0 in range(num_qubits):
|
157
|
-
for qubit1 in range(qubit0 + 1, num_qubits):
|
158
|
-
for n0, n1 in product(range(3), repeat=2):
|
159
|
-
|
160
|
-
# Apply a 2-qubit block
|
161
|
-
reduced = clifford.copy()
|
162
|
-
for qubit, n in [(qubit0, n0), (qubit1, n1)]:
|
163
|
-
if n == 1:
|
164
|
-
_append_v(reduced, qubit)
|
165
|
-
elif n == 2:
|
166
|
-
_append_w(reduced, qubit)
|
167
|
-
_append_cx(reduced, qubit0, qubit1)
|
168
|
-
|
169
|
-
# Compute new cost
|
170
|
-
new_cost = _cx_cost(reduced)
|
171
|
-
|
172
|
-
if new_cost == cost - 1:
|
173
|
-
# Add decomposition to inverse circuit
|
174
|
-
for qubit, n in [(qubit0, n0), (qubit1, n1)]:
|
175
|
-
if n == 1:
|
176
|
-
inv_circuit.sdg(qubit)
|
177
|
-
inv_circuit.h(qubit)
|
178
|
-
elif n == 2:
|
179
|
-
inv_circuit.h(qubit)
|
180
|
-
inv_circuit.s(qubit)
|
181
|
-
inv_circuit.cx(qubit0, qubit1)
|
182
|
-
|
183
|
-
return reduced, inv_circuit, new_cost
|
184
|
-
|
185
|
-
# If we didn't reduce cost
|
186
|
-
raise QiskitError("Failed to reduce Clifford CX cost.")
|
187
|
-
|
188
|
-
|
189
|
-
def _cx_cost(clifford):
|
190
|
-
"""Return the number of CX gates required for Clifford decomposition."""
|
191
|
-
if clifford.num_qubits == 2:
|
192
|
-
return _cx_cost2(clifford)
|
193
|
-
if clifford.num_qubits == 3:
|
194
|
-
return _cx_cost3(clifford)
|
195
|
-
raise Exception("No Clifford CX cost function for num_qubits > 3.")
|
196
|
-
|
197
|
-
|
198
|
-
def _rank2(a, b, c, d):
|
199
|
-
"""Return rank of 2x2 boolean matrix."""
|
200
|
-
if (a & d) ^ (b & c):
|
201
|
-
return 2
|
202
|
-
if a or b or c or d:
|
203
|
-
return 1
|
204
|
-
return 0
|
205
|
-
|
206
|
-
|
207
|
-
def _cx_cost2(clifford):
|
208
|
-
"""Return CX cost of a 2-qubit clifford."""
|
209
|
-
U = clifford.tableau[:, :-1]
|
210
|
-
r00 = _rank2(U[0, 0], U[0, 2], U[2, 0], U[2, 2])
|
211
|
-
r01 = _rank2(U[0, 1], U[0, 3], U[2, 1], U[2, 3])
|
212
|
-
if r00 == 2:
|
213
|
-
return r01
|
214
|
-
return r01 + 1 - r00
|
215
|
-
|
216
|
-
|
217
|
-
def _cx_cost3(clifford):
|
218
|
-
"""Return CX cost of a 3-qubit clifford."""
|
219
|
-
# pylint: disable=too-many-return-statements,too-many-boolean-expressions
|
220
|
-
U = clifford.tableau[:, :-1]
|
221
|
-
n = 3
|
222
|
-
# create information transfer matrices R1, R2
|
223
|
-
R1 = np.zeros((n, n), dtype=int)
|
224
|
-
R2 = np.zeros((n, n), dtype=int)
|
225
|
-
for q1 in range(n):
|
226
|
-
for q2 in range(n):
|
227
|
-
R2[q1, q2] = _rank2(U[q1, q2], U[q1, q2 + n], U[q1 + n, q2], U[q1 + n, q2 + n])
|
228
|
-
mask = np.zeros(2 * n, dtype=int)
|
229
|
-
mask[[q2, q2 + n]] = 1
|
230
|
-
isLocX = np.array_equal(U[q1, :] & mask, U[q1, :])
|
231
|
-
isLocZ = np.array_equal(U[q1 + n, :] & mask, U[q1 + n, :])
|
232
|
-
isLocY = np.array_equal((U[q1, :] ^ U[q1 + n, :]) & mask, (U[q1, :] ^ U[q1 + n, :]))
|
233
|
-
R1[q1, q2] = 1 * (isLocX or isLocZ or isLocY) + 1 * (isLocX and isLocZ and isLocY)
|
234
|
-
|
235
|
-
diag1 = np.sort(np.diag(R1)).tolist()
|
236
|
-
diag2 = np.sort(np.diag(R2)).tolist()
|
237
|
-
|
238
|
-
nz1 = np.count_nonzero(R1)
|
239
|
-
nz2 = np.count_nonzero(R2)
|
240
|
-
|
241
|
-
if diag1 == [2, 2, 2]:
|
242
|
-
return 0
|
243
|
-
|
244
|
-
if diag1 == [1, 1, 2]:
|
245
|
-
return 1
|
246
|
-
|
247
|
-
if (
|
248
|
-
diag1 == [0, 1, 1]
|
249
|
-
or (diag1 == [1, 1, 1] and nz2 < 9)
|
250
|
-
or (diag1 == [0, 0, 2] and diag2 == [1, 1, 2])
|
251
|
-
):
|
252
|
-
return 2
|
253
|
-
|
254
|
-
if (
|
255
|
-
(diag1 == [1, 1, 1] and nz2 == 9)
|
256
|
-
or (
|
257
|
-
diag1 == [0, 0, 1]
|
258
|
-
and (nz1 == 1 or diag2 == [2, 2, 2] or (diag2 == [1, 1, 2] and nz2 < 9))
|
259
|
-
)
|
260
|
-
or (diag1 == [0, 0, 2] and diag2 == [0, 0, 2])
|
261
|
-
or (diag2 == [1, 2, 2] and nz1 == 0)
|
262
|
-
):
|
263
|
-
return 3
|
264
|
-
|
265
|
-
if diag2 == [0, 0, 1] or (
|
266
|
-
diag1 == [0, 0, 0]
|
267
|
-
and (
|
268
|
-
(diag2 == [1, 1, 1] and nz2 == 9 and nz1 == 3)
|
269
|
-
or (diag2 == [0, 1, 1] and nz2 == 8 and nz1 == 2)
|
270
|
-
)
|
271
|
-
):
|
272
|
-
return 5
|
273
|
-
|
274
|
-
if nz1 == 3 and nz2 == 3:
|
275
|
-
return 6
|
276
|
-
|
277
|
-
return 4
|
@@ -12,22 +12,16 @@
|
|
12
12
|
"""
|
13
13
|
Circuit synthesis for the Clifford class.
|
14
14
|
"""
|
15
|
-
# pylint: disable=invalid-name
|
16
15
|
|
17
16
|
# ---------------------------------------------------------------------
|
18
17
|
# Synthesis based on Bravyi et. al. greedy clifford compiler
|
19
18
|
# ---------------------------------------------------------------------
|
20
19
|
|
21
|
-
|
22
|
-
import numpy as np
|
23
20
|
from qiskit.circuit import QuantumCircuit
|
24
|
-
from qiskit.
|
25
|
-
|
26
|
-
from qiskit.
|
27
|
-
|
28
|
-
_append_h,
|
29
|
-
_append_s,
|
30
|
-
_append_swap,
|
21
|
+
from qiskit.quantum_info import Clifford
|
22
|
+
|
23
|
+
from qiskit._accelerate.synthesis.clifford import (
|
24
|
+
synth_clifford_greedy as synth_clifford_greedy_inner,
|
31
25
|
)
|
32
26
|
|
33
27
|
|
@@ -56,296 +50,8 @@ def synth_clifford_greedy(clifford: Clifford) -> QuantumCircuit:
|
|
56
50
|
*Clifford Circuit Optimization with Templates and Symbolic Pauli Gates*,
|
57
51
|
`arXiv:2105.02291 [quant-ph] <https://arxiv.org/abs/2105.02291>`_
|
58
52
|
"""
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
# Reducing the original Clifford to identity
|
66
|
-
# via symplectic Gaussian elimination
|
67
|
-
while len(qubit_list) > 0:
|
68
|
-
# Calculate the adjoint of clifford_cpy without the phase
|
69
|
-
clifford_adj = clifford_cpy.copy()
|
70
|
-
tmp = clifford_adj.destab_x.copy()
|
71
|
-
clifford_adj.destab_x = clifford_adj.stab_z.T
|
72
|
-
clifford_adj.destab_z = clifford_adj.destab_z.T
|
73
|
-
clifford_adj.stab_x = clifford_adj.stab_x.T
|
74
|
-
clifford_adj.stab_z = tmp.T
|
75
|
-
|
76
|
-
list_greedy_cost = []
|
77
|
-
for qubit in qubit_list:
|
78
|
-
pauli_x = Pauli("I" * (num_qubits - qubit - 1) + "X" + "I" * qubit)
|
79
|
-
pauli_x = pauli_x.evolve(clifford_adj, frame="s")
|
80
|
-
|
81
|
-
pauli_z = Pauli("I" * (num_qubits - qubit - 1) + "Z" + "I" * qubit)
|
82
|
-
pauli_z = pauli_z.evolve(clifford_adj, frame="s")
|
83
|
-
list_pairs = []
|
84
|
-
pauli_count = 0
|
85
|
-
|
86
|
-
# Compute the CNOT cost in order to find the qubit with the minimal cost
|
87
|
-
for i in qubit_list:
|
88
|
-
typeq = _from_pair_paulis_to_type(pauli_x, pauli_z, i)
|
89
|
-
list_pairs.append(typeq)
|
90
|
-
pauli_count += 1
|
91
|
-
cost = _compute_greedy_cost(list_pairs)
|
92
|
-
list_greedy_cost.append([cost, qubit])
|
93
|
-
|
94
|
-
_, min_qubit = (sorted(list_greedy_cost))[0]
|
95
|
-
|
96
|
-
# Gaussian elimination step for the qubit with minimal CNOT cost
|
97
|
-
pauli_x = Pauli("I" * (num_qubits - min_qubit - 1) + "X" + "I" * min_qubit)
|
98
|
-
pauli_x = pauli_x.evolve(clifford_adj, frame="s")
|
99
|
-
|
100
|
-
pauli_z = Pauli("I" * (num_qubits - min_qubit - 1) + "Z" + "I" * min_qubit)
|
101
|
-
pauli_z = pauli_z.evolve(clifford_adj, frame="s")
|
102
|
-
|
103
|
-
# Compute the decoupling operator of cliff_ox and cliff_oz
|
104
|
-
decouple_circ, decouple_cliff = _calc_decoupling(
|
105
|
-
pauli_x, pauli_z, qubit_list, min_qubit, num_qubits, clifford_cpy
|
106
|
-
)
|
107
|
-
circ = circ.compose(decouple_circ)
|
108
|
-
|
109
|
-
# Now the clifford acts trivially on min_qubit
|
110
|
-
clifford_cpy = decouple_cliff.adjoint().compose(clifford_cpy)
|
111
|
-
qubit_list.remove(min_qubit)
|
112
|
-
|
113
|
-
# Add the phases (Pauli gates) to the Clifford circuit
|
114
|
-
for qubit in range(num_qubits):
|
115
|
-
stab = clifford_cpy.stab_phase[qubit]
|
116
|
-
destab = clifford_cpy.destab_phase[qubit]
|
117
|
-
if destab and stab:
|
118
|
-
circ.y(qubit)
|
119
|
-
elif not destab and stab:
|
120
|
-
circ.x(qubit)
|
121
|
-
elif destab and not stab:
|
122
|
-
circ.z(qubit)
|
123
|
-
|
124
|
-
return circ
|
125
|
-
|
126
|
-
|
127
|
-
# ---------------------------------------------------------------------
|
128
|
-
# Helper functions for Bravyi et. al. greedy clifford compiler
|
129
|
-
# ---------------------------------------------------------------------
|
130
|
-
|
131
|
-
# Global arrays of the 16 pairs of Pauli operators
|
132
|
-
# divided into 5 equivalence classes under the action of single-qubit Cliffords
|
133
|
-
|
134
|
-
# Class A - canonical representative is 'XZ'
|
135
|
-
A_class = [
|
136
|
-
[[False, True], [True, True]], # 'XY'
|
137
|
-
[[False, True], [True, False]], # 'XZ'
|
138
|
-
[[True, True], [False, True]], # 'YX'
|
139
|
-
[[True, True], [True, False]], # 'YZ'
|
140
|
-
[[True, False], [False, True]], # 'ZX'
|
141
|
-
[[True, False], [True, True]],
|
142
|
-
] # 'ZY'
|
143
|
-
|
144
|
-
# Class B - canonical representative is 'XX'
|
145
|
-
B_class = [
|
146
|
-
[[True, False], [True, False]], # 'ZZ'
|
147
|
-
[[False, True], [False, True]], # 'XX'
|
148
|
-
[[True, True], [True, True]],
|
149
|
-
] # 'YY'
|
150
|
-
|
151
|
-
# Class C - canonical representative is 'XI'
|
152
|
-
C_class = [
|
153
|
-
[[True, False], [False, False]], # 'ZI'
|
154
|
-
[[False, True], [False, False]], # 'XI'
|
155
|
-
[[True, True], [False, False]],
|
156
|
-
] # 'YI'
|
157
|
-
|
158
|
-
# Class D - canonical representative is 'IZ'
|
159
|
-
D_class = [
|
160
|
-
[[False, False], [False, True]], # 'IX'
|
161
|
-
[[False, False], [True, False]], # 'IZ'
|
162
|
-
[[False, False], [True, True]],
|
163
|
-
] # 'IY'
|
164
|
-
|
165
|
-
# Class E - only 'II'
|
166
|
-
E_class = [[[False, False], [False, False]]] # 'II'
|
167
|
-
|
168
|
-
|
169
|
-
def _from_pair_paulis_to_type(pauli_x, pauli_z, qubit):
|
170
|
-
"""Converts a pair of Paulis pauli_x and pauli_z into a type"""
|
171
|
-
|
172
|
-
type_x = [pauli_x.z[qubit], pauli_x.x[qubit]]
|
173
|
-
type_z = [pauli_z.z[qubit], pauli_z.x[qubit]]
|
174
|
-
return [type_x, type_z]
|
175
|
-
|
176
|
-
|
177
|
-
def _compute_greedy_cost(list_pairs):
|
178
|
-
"""Compute the CNOT cost of one step of the algorithm"""
|
179
|
-
|
180
|
-
A_num = 0
|
181
|
-
B_num = 0
|
182
|
-
C_num = 0
|
183
|
-
D_num = 0
|
184
|
-
|
185
|
-
for pair in list_pairs:
|
186
|
-
if pair in A_class:
|
187
|
-
A_num += 1
|
188
|
-
elif pair in B_class:
|
189
|
-
B_num += 1
|
190
|
-
elif pair in C_class:
|
191
|
-
C_num += 1
|
192
|
-
elif pair in D_class:
|
193
|
-
D_num += 1
|
194
|
-
|
195
|
-
if (A_num % 2) == 0:
|
196
|
-
raise QiskitError("Symplectic Gaussian elimination fails.")
|
197
|
-
|
198
|
-
# Calculate the CNOT cost
|
199
|
-
cost = 3 * (A_num - 1) / 2 + (B_num + 1) * (B_num > 0) + C_num + D_num
|
200
|
-
if list_pairs[0] not in A_class: # additional SWAP
|
201
|
-
cost += 3
|
202
|
-
|
203
|
-
return cost
|
204
|
-
|
205
|
-
|
206
|
-
def _calc_decoupling(pauli_x, pauli_z, qubit_list, min_qubit, num_qubits, cliff):
|
207
|
-
"""Calculate a decoupling operator D:
|
208
|
-
D^{-1} * Ox * D = x1
|
209
|
-
D^{-1} * Oz * D = z1
|
210
|
-
and reduce the clifford such that it will act trivially on min_qubit
|
211
|
-
"""
|
212
|
-
|
213
|
-
circ = QuantumCircuit(num_qubits)
|
214
|
-
|
215
|
-
# decouple_cliff is initialized to an identity clifford
|
216
|
-
decouple_cliff = cliff.copy()
|
217
|
-
num_qubits = decouple_cliff.num_qubits
|
218
|
-
decouple_cliff.phase = np.zeros(2 * num_qubits)
|
219
|
-
decouple_cliff.symplectic_matrix = np.eye(2 * num_qubits)
|
220
|
-
|
221
|
-
qubit0 = min_qubit # The qubit for the symplectic Gaussian elimination
|
222
|
-
|
223
|
-
# Reduce the pair of Paulis to a representative in the equivalence class
|
224
|
-
# ['XZ', 'XX', 'XI', 'IZ', 'II'] by adding single-qubit gates
|
225
|
-
for qubit in qubit_list:
|
226
|
-
|
227
|
-
typeq = _from_pair_paulis_to_type(pauli_x, pauli_z, qubit)
|
228
|
-
|
229
|
-
if typeq in [
|
230
|
-
[[True, True], [False, False]], # 'YI'
|
231
|
-
[[True, True], [True, True]], # 'YY'
|
232
|
-
[[True, True], [True, False]],
|
233
|
-
]: # 'YZ':
|
234
|
-
circ.s(qubit)
|
235
|
-
_append_s(decouple_cliff, qubit)
|
236
|
-
|
237
|
-
elif typeq in [
|
238
|
-
[[True, False], [False, False]], # 'ZI'
|
239
|
-
[[True, False], [True, False]], # 'ZZ'
|
240
|
-
[[True, False], [False, True]], # 'ZX'
|
241
|
-
[[False, False], [False, True]],
|
242
|
-
]: # 'IX'
|
243
|
-
circ.h(qubit)
|
244
|
-
_append_h(decouple_cliff, qubit)
|
245
|
-
|
246
|
-
elif typeq in [
|
247
|
-
[[False, False], [True, True]], # 'IY'
|
248
|
-
[[True, False], [True, True]],
|
249
|
-
]: # 'ZY'
|
250
|
-
circ.s(qubit)
|
251
|
-
circ.h(qubit)
|
252
|
-
_append_s(decouple_cliff, qubit)
|
253
|
-
_append_h(decouple_cliff, qubit)
|
254
|
-
|
255
|
-
elif typeq == [[True, True], [False, True]]: # 'YX'
|
256
|
-
circ.h(qubit)
|
257
|
-
circ.s(qubit)
|
258
|
-
_append_h(decouple_cliff, qubit)
|
259
|
-
_append_s(decouple_cliff, qubit)
|
260
|
-
|
261
|
-
elif typeq == [[False, True], [True, True]]: # 'XY'
|
262
|
-
circ.s(qubit)
|
263
|
-
circ.h(qubit)
|
264
|
-
circ.s(qubit)
|
265
|
-
_append_s(decouple_cliff, qubit)
|
266
|
-
_append_h(decouple_cliff, qubit)
|
267
|
-
_append_s(decouple_cliff, qubit)
|
268
|
-
|
269
|
-
# Reducing each pair of Paulis (except of qubit0) to 'II'
|
270
|
-
# by adding two-qubit gates and single-qubit gates
|
271
|
-
A_qubits = []
|
272
|
-
B_qubits = []
|
273
|
-
C_qubits = []
|
274
|
-
D_qubits = []
|
275
|
-
|
276
|
-
for qubit in qubit_list:
|
277
|
-
typeq = _from_pair_paulis_to_type(pauli_x, pauli_z, qubit)
|
278
|
-
if typeq in A_class:
|
279
|
-
A_qubits.append(qubit)
|
280
|
-
elif typeq in B_class:
|
281
|
-
B_qubits.append(qubit)
|
282
|
-
elif typeq in C_class:
|
283
|
-
C_qubits.append(qubit)
|
284
|
-
elif typeq in D_class:
|
285
|
-
D_qubits.append(qubit)
|
286
|
-
|
287
|
-
if len(A_qubits) % 2 != 1:
|
288
|
-
raise QiskitError("Symplectic Gaussian elimination fails.")
|
289
|
-
|
290
|
-
if qubit0 not in A_qubits: # SWAP qubit0 and qubitA
|
291
|
-
qubitA = A_qubits[0]
|
292
|
-
circ.swap(qubit0, qubitA)
|
293
|
-
_append_swap(decouple_cliff, qubit0, qubitA)
|
294
|
-
if qubit0 in B_qubits:
|
295
|
-
B_qubits.remove(qubit0)
|
296
|
-
B_qubits.append(qubitA)
|
297
|
-
A_qubits.remove(qubitA)
|
298
|
-
A_qubits.append(qubit0)
|
299
|
-
elif qubit0 in C_qubits:
|
300
|
-
C_qubits.remove(qubit0)
|
301
|
-
C_qubits.append(qubitA)
|
302
|
-
A_qubits.remove(qubitA)
|
303
|
-
A_qubits.append(qubit0)
|
304
|
-
elif qubit0 in D_qubits:
|
305
|
-
D_qubits.remove(qubit0)
|
306
|
-
D_qubits.append(qubitA)
|
307
|
-
A_qubits.remove(qubitA)
|
308
|
-
A_qubits.append(qubit0)
|
309
|
-
else:
|
310
|
-
A_qubits.remove(qubitA)
|
311
|
-
A_qubits.append(qubit0)
|
312
|
-
|
313
|
-
# Reduce pairs in Class C to 'II'
|
314
|
-
for qubit in C_qubits:
|
315
|
-
circ.cx(qubit0, qubit)
|
316
|
-
_append_cx(decouple_cliff, qubit0, qubit)
|
317
|
-
|
318
|
-
# Reduce pairs in Class D to 'II'
|
319
|
-
for qubit in D_qubits:
|
320
|
-
circ.cx(qubit, qubit0)
|
321
|
-
_append_cx(decouple_cliff, qubit, qubit0)
|
322
|
-
|
323
|
-
# Reduce pairs in Class B to 'II'
|
324
|
-
if len(B_qubits) > 1:
|
325
|
-
for qubit in B_qubits[1:]:
|
326
|
-
qubitB = B_qubits[0]
|
327
|
-
circ.cx(qubitB, qubit)
|
328
|
-
_append_cx(decouple_cliff, qubitB, qubit)
|
329
|
-
|
330
|
-
if len(B_qubits) > 0:
|
331
|
-
qubitB = B_qubits[0]
|
332
|
-
circ.cx(qubit0, qubitB)
|
333
|
-
circ.h(qubitB)
|
334
|
-
circ.cx(qubitB, qubit0)
|
335
|
-
_append_cx(decouple_cliff, qubit0, qubitB)
|
336
|
-
_append_h(decouple_cliff, qubitB)
|
337
|
-
_append_cx(decouple_cliff, qubitB, qubit0)
|
338
|
-
|
339
|
-
# Reduce pairs in Class A (except of qubit0) to 'II'
|
340
|
-
Alen = int((len(A_qubits) - 1) / 2)
|
341
|
-
if Alen > 0:
|
342
|
-
A_qubits.remove(qubit0)
|
343
|
-
for qubit in range(Alen):
|
344
|
-
circ.cx(A_qubits[2 * qubit + 1], A_qubits[2 * qubit])
|
345
|
-
circ.cx(A_qubits[2 * qubit], qubit0)
|
346
|
-
circ.cx(qubit0, A_qubits[2 * qubit + 1])
|
347
|
-
_append_cx(decouple_cliff, A_qubits[2 * qubit + 1], A_qubits[2 * qubit])
|
348
|
-
_append_cx(decouple_cliff, A_qubits[2 * qubit], qubit0)
|
349
|
-
_append_cx(decouple_cliff, qubit0, A_qubits[2 * qubit + 1])
|
350
|
-
|
351
|
-
return circ, decouple_cliff
|
53
|
+
circuit = QuantumCircuit._from_circuit_data(
|
54
|
+
synth_clifford_greedy_inner(clifford.tableau.astype(bool))
|
55
|
+
)
|
56
|
+
circuit.name = str(clifford)
|
57
|
+
return circuit
|