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
@@ -12,11 +12,15 @@
|
|
12
12
|
|
13
13
|
"""QDrift Class"""
|
14
14
|
|
15
|
+
from __future__ import annotations
|
16
|
+
|
17
|
+
import inspect
|
15
18
|
import math
|
16
|
-
from
|
19
|
+
from collections.abc import Callable
|
17
20
|
import numpy as np
|
18
21
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
19
22
|
from qiskit.quantum_info.operators import SparsePauliOp, Pauli
|
23
|
+
from qiskit.utils.deprecation import deprecate_arg
|
20
24
|
|
21
25
|
from .product_formula import ProductFormula
|
22
26
|
from .lie_trotter import LieTrotter
|
@@ -32,15 +36,33 @@ class QDrift(ProductFormula):
|
|
32
36
|
`arXiv:quant-ph/1811.08017 <https://arxiv.org/abs/1811.08017>`_
|
33
37
|
"""
|
34
38
|
|
39
|
+
@deprecate_arg(
|
40
|
+
name="atomic_evolution",
|
41
|
+
since="1.2",
|
42
|
+
predicate=lambda callable: callable is not None
|
43
|
+
and len(inspect.signature(callable).parameters) == 2,
|
44
|
+
deprecation_description=(
|
45
|
+
"The 'Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]' signature of the "
|
46
|
+
"'atomic_evolution' argument"
|
47
|
+
),
|
48
|
+
additional_msg=(
|
49
|
+
"Instead you should update your 'atomic_evolution' function to be of the following "
|
50
|
+
"type: 'Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]'."
|
51
|
+
),
|
52
|
+
pending=True,
|
53
|
+
)
|
35
54
|
def __init__(
|
36
55
|
self,
|
37
56
|
reps: int = 1,
|
38
57
|
insert_barriers: bool = False,
|
39
58
|
cx_structure: str = "chain",
|
40
|
-
atomic_evolution:
|
41
|
-
Callable[[
|
42
|
-
|
43
|
-
|
59
|
+
atomic_evolution: (
|
60
|
+
Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]
|
61
|
+
| Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]
|
62
|
+
| None
|
63
|
+
) = None,
|
64
|
+
seed: int | None = None,
|
65
|
+
wrap: bool = False,
|
44
66
|
) -> None:
|
45
67
|
r"""
|
46
68
|
Args:
|
@@ -48,13 +70,21 @@ class QDrift(ProductFormula):
|
|
48
70
|
insert_barriers: Whether to insert barriers between the atomic evolutions.
|
49
71
|
cx_structure: How to arrange the CX gates for the Pauli evolutions, can be
|
50
72
|
``"chain"``, where next neighbor connections are used, or ``"fountain"``, where all
|
51
|
-
qubits are connected to one.
|
52
|
-
|
53
|
-
|
54
|
-
|
73
|
+
qubits are connected to one. This only takes effect when
|
74
|
+
``atomic_evolution is None``.
|
75
|
+
atomic_evolution: A function to apply the evolution of a single :class:`.Pauli`, or
|
76
|
+
:class:`.SparsePauliOp` of only commuting terms, to a circuit. The function takes in
|
77
|
+
three arguments: the circuit to append the evolution to, the Pauli operator to
|
78
|
+
evolve, and the evolution time. By default, a single Pauli evolution is decomposed
|
79
|
+
into a chain of ``CX`` gates and a single ``RZ`` gate.
|
80
|
+
Alternatively, the function can also take Pauli operator and evolution time as
|
81
|
+
inputs and returns the circuit that will be appended to the overall circuit being
|
82
|
+
built.
|
55
83
|
seed: An optional seed for reproducibility of the random sampling process.
|
84
|
+
wrap: Whether to wrap the atomic evolutions into custom gate objects. This only takes
|
85
|
+
effect when ``atomic_evolution is None``.
|
56
86
|
"""
|
57
|
-
super().__init__(1, reps, insert_barriers, cx_structure, atomic_evolution)
|
87
|
+
super().__init__(1, reps, insert_barriers, cx_structure, atomic_evolution, wrap)
|
58
88
|
self.sampled_ops = None
|
59
89
|
self.rng = np.random.default_rng(seed)
|
60
90
|
|
@@ -12,12 +12,16 @@
|
|
12
12
|
|
13
13
|
"""The Suzuki-Trotter product formula."""
|
14
14
|
|
15
|
-
from
|
15
|
+
from __future__ import annotations
|
16
|
+
|
17
|
+
import inspect
|
18
|
+
from collections.abc import Callable
|
16
19
|
|
17
20
|
import numpy as np
|
18
21
|
|
19
22
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
20
23
|
from qiskit.quantum_info.operators import SparsePauliOp, Pauli
|
24
|
+
from qiskit.utils.deprecation import deprecate_arg
|
21
25
|
|
22
26
|
|
23
27
|
from .product_formula import ProductFormula
|
@@ -51,15 +55,33 @@ class SuzukiTrotter(ProductFormula):
|
|
51
55
|
`arXiv:math-ph/0506007 <https://arxiv.org/pdf/math-ph/0506007.pdf>`_
|
52
56
|
"""
|
53
57
|
|
58
|
+
@deprecate_arg(
|
59
|
+
name="atomic_evolution",
|
60
|
+
since="1.2",
|
61
|
+
predicate=lambda callable: callable is not None
|
62
|
+
and len(inspect.signature(callable).parameters) == 2,
|
63
|
+
deprecation_description=(
|
64
|
+
"The 'Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]' signature of the "
|
65
|
+
"'atomic_evolution' argument"
|
66
|
+
),
|
67
|
+
additional_msg=(
|
68
|
+
"Instead you should update your 'atomic_evolution' function to be of the following "
|
69
|
+
"type: 'Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]'."
|
70
|
+
),
|
71
|
+
pending=True,
|
72
|
+
)
|
54
73
|
def __init__(
|
55
74
|
self,
|
56
75
|
order: int = 2,
|
57
76
|
reps: int = 1,
|
58
77
|
insert_barriers: bool = False,
|
59
78
|
cx_structure: str = "chain",
|
60
|
-
atomic_evolution:
|
61
|
-
Callable[[
|
62
|
-
|
79
|
+
atomic_evolution: (
|
80
|
+
Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]
|
81
|
+
| Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]
|
82
|
+
| None
|
83
|
+
) = None,
|
84
|
+
wrap: bool = False,
|
63
85
|
) -> None:
|
64
86
|
"""
|
65
87
|
Args:
|
@@ -68,10 +90,17 @@ class SuzukiTrotter(ProductFormula):
|
|
68
90
|
insert_barriers: Whether to insert barriers between the atomic evolutions.
|
69
91
|
cx_structure: How to arrange the CX gates for the Pauli evolutions, can be ``"chain"``,
|
70
92
|
where next neighbor connections are used, or ``"fountain"``, where all qubits are
|
71
|
-
connected to one.
|
72
|
-
atomic_evolution: A function to
|
73
|
-
|
74
|
-
|
93
|
+
connected to one. This only takes effect when ``atomic_evolution is None``.
|
94
|
+
atomic_evolution: A function to apply the evolution of a single :class:`.Pauli`, or
|
95
|
+
:class:`.SparsePauliOp` of only commuting terms, to a circuit. The function takes in
|
96
|
+
three arguments: the circuit to append the evolution to, the Pauli operator to
|
97
|
+
evolve, and the evolution time. By default, a single Pauli evolution is decomposed
|
98
|
+
into a chain of ``CX`` gates and a single ``RZ`` gate.
|
99
|
+
Alternatively, the function can also take Pauli operator and evolution time as
|
100
|
+
inputs and returns the circuit that will be appended to the overall circuit being
|
101
|
+
built.
|
102
|
+
wrap: Whether to wrap the atomic evolutions into custom gate objects. This only takes
|
103
|
+
effect when ``atomic_evolution is None``.
|
75
104
|
Raises:
|
76
105
|
ValueError: If order is not even
|
77
106
|
"""
|
@@ -81,7 +110,7 @@ class SuzukiTrotter(ProductFormula):
|
|
81
110
|
"Suzuki product formulae are symmetric and therefore only defined "
|
82
111
|
"for even orders."
|
83
112
|
)
|
84
|
-
super().__init__(order, reps, insert_barriers, cx_structure, atomic_evolution)
|
113
|
+
super().__init__(order, reps, insert_barriers, cx_structure, atomic_evolution, wrap)
|
85
114
|
|
86
115
|
def synthesize(self, evolution):
|
87
116
|
# get operators and time to evolve
|
@@ -97,32 +126,13 @@ class SuzukiTrotter(ProductFormula):
|
|
97
126
|
|
98
127
|
# construct the evolution circuit
|
99
128
|
single_rep = QuantumCircuit(operators[0].num_qubits)
|
100
|
-
first_barrier = False
|
101
|
-
|
102
|
-
for op, coeff in ops_to_evolve:
|
103
|
-
# add barriers
|
104
|
-
if first_barrier:
|
105
|
-
if self.insert_barriers:
|
106
|
-
single_rep.barrier()
|
107
|
-
else:
|
108
|
-
first_barrier = True
|
109
|
-
|
110
|
-
single_rep.compose(self.atomic_evolution(op, coeff), wrap=True, inplace=True)
|
111
|
-
|
112
|
-
evolution_circuit = QuantumCircuit(operators[0].num_qubits)
|
113
|
-
first_barrier = False
|
114
|
-
|
115
|
-
for _ in range(self.reps):
|
116
|
-
# add barriers
|
117
|
-
if first_barrier:
|
118
|
-
if self.insert_barriers:
|
119
|
-
single_rep.barrier()
|
120
|
-
else:
|
121
|
-
first_barrier = True
|
122
129
|
|
123
|
-
|
130
|
+
for i, (op, coeff) in enumerate(ops_to_evolve):
|
131
|
+
self.atomic_evolution(single_rep, op, coeff)
|
132
|
+
if self.insert_barriers and i != len(ops_to_evolve) - 1:
|
133
|
+
single_rep.barrier()
|
124
134
|
|
125
|
-
return
|
135
|
+
return single_rep.repeat(self.reps, insert_barriers=self.insert_barriers).decompose()
|
126
136
|
|
127
137
|
@staticmethod
|
128
138
|
def _recurse(order, time, pauli_list):
|
@@ -17,33 +17,37 @@ for optimal synthesis of linear (CNOT-only) reversible circuits.
|
|
17
17
|
"""
|
18
18
|
|
19
19
|
from __future__ import annotations
|
20
|
-
|
20
|
+
|
21
21
|
import numpy as np
|
22
22
|
from qiskit.circuit import QuantumCircuit
|
23
|
-
|
23
|
+
|
24
|
+
from qiskit._accelerate.synthesis.linear import synth_cnot_count_full_pmh as fast_pmh
|
24
25
|
|
25
26
|
|
26
27
|
def synth_cnot_count_full_pmh(
|
27
|
-
state: list[list[bool]] | np.ndarray[bool], section_size: int =
|
28
|
+
state: list[list[bool]] | np.ndarray[bool], section_size: int | None = None
|
28
29
|
) -> QuantumCircuit:
|
29
|
-
"""
|
30
|
+
r"""
|
30
31
|
Synthesize linear reversible circuits for all-to-all architecture
|
31
32
|
using Patel, Markov and Hayes method.
|
32
33
|
|
33
34
|
This function is an implementation of the Patel, Markov and Hayes algorithm from [1]
|
34
35
|
for optimal synthesis of linear reversible circuits for all-to-all architecture,
|
35
|
-
as specified by an :math:`n
|
36
|
+
as specified by an :math:`n \times n` matrix.
|
36
37
|
|
37
38
|
Args:
|
38
|
-
state: :math:`n
|
39
|
-
the state of the input circuit
|
39
|
+
state: :math:`n \times n` boolean invertible matrix, describing
|
40
|
+
the state of the input circuit.
|
40
41
|
section_size: The size of each section in the Patel–Markov–Hayes algorithm [1].
|
42
|
+
If ``None`` it is chosen to be :math:`\max(2, \alpha\log_2(n))` with
|
43
|
+
:math:`\alpha = 0.56`, which approximately minimizes the upper bound on the number
|
44
|
+
of row operations given in [1] Eq. (3).
|
41
45
|
|
42
46
|
Returns:
|
43
|
-
|
47
|
+
A CX-only circuit implementing the linear transformation.
|
44
48
|
|
45
49
|
Raises:
|
46
|
-
|
50
|
+
ValueError: When ``section_size`` is larger than the number of columns.
|
47
51
|
|
48
52
|
References:
|
49
53
|
1. Patel, Ketan N., Igor L. Markov, and John P. Hayes,
|
@@ -51,93 +55,15 @@ def synth_cnot_count_full_pmh(
|
|
51
55
|
Quantum Information & Computation 8.3 (2008): 282-294.
|
52
56
|
`arXiv:quant-ph/0302002 [quant-ph] <https://arxiv.org/abs/quant-ph/0302002>`_
|
53
57
|
"""
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
"
|
58
|
+
normalized = np.asarray(state).astype(bool)
|
59
|
+
if section_size is not None and normalized.shape[1] < section_size:
|
60
|
+
raise ValueError(
|
61
|
+
f"The section_size ({section_size}) cannot be larger than the number of columns "
|
62
|
+
f"({normalized.shape[1]})."
|
58
63
|
)
|
59
|
-
state = np.array(state)
|
60
|
-
# Synthesize lower triangular part
|
61
|
-
[state, circuit_l] = _lwr_cnot_synth(state, section_size)
|
62
|
-
state = np.transpose(state)
|
63
|
-
# Synthesize upper triangular part
|
64
|
-
[state, circuit_u] = _lwr_cnot_synth(state, section_size)
|
65
|
-
circuit_l.reverse()
|
66
|
-
for i in circuit_u:
|
67
|
-
i.reverse()
|
68
|
-
# Convert the list into a circuit of C-NOT gates
|
69
|
-
circ = QuantumCircuit(state.shape[0])
|
70
|
-
for i in circuit_u + circuit_l:
|
71
|
-
circ.cx(i[0], i[1])
|
72
|
-
return circ
|
73
|
-
|
74
|
-
|
75
|
-
def _lwr_cnot_synth(state, section_size):
|
76
|
-
"""
|
77
|
-
This function is a helper function of the algorithm for optimal synthesis
|
78
|
-
of linear reversible circuits (the Patel–Markov–Hayes algorithm). It works
|
79
|
-
like gaussian elimination, except that it works a lot faster, and requires
|
80
|
-
fewer steps (and therefore fewer CNOTs). It takes the matrix "state" and
|
81
|
-
splits it into sections of size section_size. Then it eliminates all non-zero
|
82
|
-
sub-rows within each section, which are the same as a non-zero sub-row
|
83
|
-
above. Once this has been done, it continues with normal gaussian elimination.
|
84
|
-
The benefit is that with small section sizes (m), most of the sub-rows will
|
85
|
-
be cleared in the first step, resulting in a factor m fewer row row operations
|
86
|
-
during Gaussian elimination.
|
87
64
|
|
88
|
-
|
89
|
-
|
90
|
-
Patel, Ketan N., Igor L. Markov, and John P. Hayes.
|
91
|
-
Quantum Information & Computation 8.3 (2008): 282-294.
|
92
|
-
|
93
|
-
Note:
|
94
|
-
This implementation tweaks the Patel, Markov, and Hayes algorithm by adding
|
95
|
-
a "back reduce" which adds rows below the pivot row with a high degree of
|
96
|
-
overlap back to it. The intuition is to avoid a high-weight pivot row
|
97
|
-
increasing the weight of lower rows.
|
98
|
-
|
99
|
-
Args:
|
100
|
-
state (ndarray): n x n matrix, describing a linear quantum circuit
|
101
|
-
section_size (int): the section size the matrix columns are divided into
|
102
|
-
|
103
|
-
Returns:
|
104
|
-
numpy.matrix: n by n matrix, describing the state of the output circuit
|
105
|
-
list: a k by 2 list of C-NOT operations that need to be applied
|
106
|
-
"""
|
107
|
-
circuit = []
|
108
|
-
num_qubits = state.shape[0]
|
109
|
-
cutoff = 1
|
65
|
+
# call Rust implementation with normalized input
|
66
|
+
circuit_data = fast_pmh(normalized, section_size)
|
110
67
|
|
111
|
-
#
|
112
|
-
|
113
|
-
# Remove duplicate sub-rows in section sec
|
114
|
-
patt = {}
|
115
|
-
for row in range((sec - 1) * section_size, num_qubits):
|
116
|
-
sub_row_patt = copy.deepcopy(state[row, (sec - 1) * section_size : sec * section_size])
|
117
|
-
if np.sum(sub_row_patt) == 0:
|
118
|
-
continue
|
119
|
-
if str(sub_row_patt) not in patt:
|
120
|
-
patt[str(sub_row_patt)] = row
|
121
|
-
else:
|
122
|
-
state[row, :] ^= state[patt[str(sub_row_patt)], :]
|
123
|
-
circuit.append([patt[str(sub_row_patt)], row])
|
124
|
-
# Use gaussian elimination for remaining entries in column section
|
125
|
-
for col in range((sec - 1) * section_size, sec * section_size):
|
126
|
-
# Check if 1 on diagonal
|
127
|
-
diag_one = 1
|
128
|
-
if state[col, col] == 0:
|
129
|
-
diag_one = 0
|
130
|
-
# Remove ones in rows below column col
|
131
|
-
for row in range(col + 1, num_qubits):
|
132
|
-
if state[row, col] == 1:
|
133
|
-
if diag_one == 0:
|
134
|
-
state[col, :] ^= state[row, :]
|
135
|
-
circuit.append([row, col])
|
136
|
-
diag_one = 1
|
137
|
-
state[row, :] ^= state[col, :]
|
138
|
-
circuit.append([col, row])
|
139
|
-
# Back reduce the pivot row using the current row
|
140
|
-
if sum(state[col, :] & state[row, :]) > cutoff:
|
141
|
-
state[col, :] ^= state[row, :]
|
142
|
-
circuit.append([row, col])
|
143
|
-
return [state, circuit]
|
68
|
+
# construct circuit from the data
|
69
|
+
return QuantumCircuit._from_circuit_data(circuit_data)
|
@@ -28,15 +28,15 @@ from qiskit.circuit import QuantumCircuit
|
|
28
28
|
from qiskit.synthesis.linear.linear_matrix_utils import (
|
29
29
|
calc_inverse_matrix,
|
30
30
|
check_invertible_binary_matrix,
|
31
|
-
|
32
|
-
|
31
|
+
col_op,
|
32
|
+
row_op,
|
33
33
|
)
|
34
34
|
|
35
35
|
|
36
36
|
def _row_op_update_instructions(cx_instructions, mat, a, b):
|
37
37
|
# Add a cx gate to the instructions and update the matrix mat
|
38
38
|
cx_instructions.append((a, b))
|
39
|
-
|
39
|
+
row_op(mat, a, b)
|
40
40
|
|
41
41
|
|
42
42
|
def _get_lower_triangular(n, mat, mat_inv):
|
@@ -62,7 +62,7 @@ def _get_lower_triangular(n, mat, mat_inv):
|
|
62
62
|
first_j = j
|
63
63
|
else:
|
64
64
|
# cx_instructions_cols (L instructions) are not needed
|
65
|
-
|
65
|
+
col_op(mat, j, first_j)
|
66
66
|
# Use row operations directed upwards to zero out all "1"s above the remaining "1" in row i
|
67
67
|
for k in reversed(range(0, i)):
|
68
68
|
if mat[k, first_j]:
|
@@ -70,8 +70,8 @@ def _get_lower_triangular(n, mat, mat_inv):
|
|
70
70
|
|
71
71
|
# Apply only U instructions to get the permuted L
|
72
72
|
for inst in cx_instructions_rows:
|
73
|
-
|
74
|
-
|
73
|
+
row_op(mat_t, inst[0], inst[1])
|
74
|
+
col_op(mat_inv_t, inst[0], inst[1])
|
75
75
|
return mat_t, mat_inv_t
|
76
76
|
|
77
77
|
|
@@ -210,7 +210,7 @@ def _north_west_to_identity(n, mat):
|
|
210
210
|
def _optimize_cx_circ_depth_5n_line(mat):
|
211
211
|
# Optimize CX circuit in depth bounded by 5n for LNN connectivity.
|
212
212
|
# The algorithm [1] has two steps:
|
213
|
-
# a) transform the
|
213
|
+
# a) transform the original matrix to a north-west matrix (m2nw),
|
214
214
|
# b) transform the north-west matrix to identity (nw2id).
|
215
215
|
#
|
216
216
|
# A square n-by-n matrix A is called north-west if A[i][j]=0 for all i+j>=n
|
@@ -222,7 +222,7 @@ def _optimize_cx_circ_depth_5n_line(mat):
|
|
222
222
|
|
223
223
|
# According to [1] the synthesis is done on the inverse matrix
|
224
224
|
# so the matrix mat is inverted at this step
|
225
|
-
mat_inv = mat.copy
|
225
|
+
mat_inv = mat.astype(bool, copy=True)
|
226
226
|
mat_cpy = calc_inverse_matrix(mat_inv)
|
227
227
|
|
228
228
|
n = len(mat_cpy)
|
@@ -12,164 +12,16 @@
|
|
12
12
|
|
13
13
|
"""Utility functions for handling binary matrices."""
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
"""
|
29
|
-
if len(mat.shape) != 2 or mat.shape[0] != mat.shape[1]:
|
30
|
-
return False
|
31
|
-
|
32
|
-
rank = _compute_rank(mat)
|
33
|
-
return rank == mat.shape[0]
|
34
|
-
|
35
|
-
|
36
|
-
def random_invertible_binary_matrix(
|
37
|
-
num_qubits: int, seed: Optional[Union[np.random.Generator, int]] = None
|
38
|
-
):
|
39
|
-
"""Generates a random invertible n x n binary matrix.
|
40
|
-
|
41
|
-
Args:
|
42
|
-
num_qubits: the matrix size.
|
43
|
-
seed: a random seed.
|
44
|
-
|
45
|
-
Returns:
|
46
|
-
np.ndarray: A random invertible binary matrix of size num_qubits.
|
47
|
-
"""
|
48
|
-
if isinstance(seed, np.random.Generator):
|
49
|
-
rng = seed
|
50
|
-
else:
|
51
|
-
rng = np.random.default_rng(seed)
|
52
|
-
|
53
|
-
rank = 0
|
54
|
-
while rank != num_qubits:
|
55
|
-
mat = rng.integers(2, size=(num_qubits, num_qubits))
|
56
|
-
rank = _compute_rank(mat)
|
57
|
-
return mat
|
58
|
-
|
59
|
-
|
60
|
-
def _gauss_elimination(mat, ncols=None, full_elim=False):
|
61
|
-
"""Gauss elimination of a matrix mat with m rows and n columns.
|
62
|
-
If full_elim = True, it allows full elimination of mat[:, 0 : ncols]
|
63
|
-
Returns the matrix mat."""
|
64
|
-
|
65
|
-
mat, _ = _gauss_elimination_with_perm(mat, ncols, full_elim)
|
66
|
-
return mat
|
67
|
-
|
68
|
-
|
69
|
-
def _gauss_elimination_with_perm(mat, ncols=None, full_elim=False):
|
70
|
-
"""Gauss elimination of a matrix mat with m rows and n columns.
|
71
|
-
If full_elim = True, it allows full elimination of mat[:, 0 : ncols]
|
72
|
-
Returns the matrix mat, and the permutation perm that was done on the rows during the process.
|
73
|
-
perm[0 : rank] represents the indices of linearly independent rows in the original matrix."""
|
74
|
-
|
75
|
-
# Treat the matrix A as containing integer values
|
76
|
-
mat = np.array(mat, dtype=int, copy=True)
|
77
|
-
|
78
|
-
m = mat.shape[0] # no. of rows
|
79
|
-
n = mat.shape[1] # no. of columns
|
80
|
-
if ncols is not None:
|
81
|
-
n = min(n, ncols) # no. of active columns
|
82
|
-
|
83
|
-
perm = np.array(range(m)) # permutation on the rows
|
84
|
-
|
85
|
-
r = 0 # current rank
|
86
|
-
k = 0 # current pivot column
|
87
|
-
while (r < m) and (k < n):
|
88
|
-
is_non_zero = False
|
89
|
-
new_r = r
|
90
|
-
for j in range(k, n):
|
91
|
-
for i in range(r, m):
|
92
|
-
if mat[i][j]:
|
93
|
-
is_non_zero = True
|
94
|
-
k = j
|
95
|
-
new_r = i
|
96
|
-
break
|
97
|
-
if is_non_zero:
|
98
|
-
break
|
99
|
-
if not is_non_zero:
|
100
|
-
return mat, perm # A is in the canonical form
|
101
|
-
|
102
|
-
if new_r != r:
|
103
|
-
mat[[r, new_r]] = mat[[new_r, r]]
|
104
|
-
perm[r], perm[new_r] = perm[new_r], perm[r]
|
105
|
-
|
106
|
-
if full_elim:
|
107
|
-
for i in range(0, r):
|
108
|
-
if mat[i][k]:
|
109
|
-
mat[i] = mat[i] ^ mat[r]
|
110
|
-
|
111
|
-
for i in range(r + 1, m):
|
112
|
-
if mat[i][k]:
|
113
|
-
mat[i] = mat[i] ^ mat[r]
|
114
|
-
r += 1
|
115
|
-
|
116
|
-
return mat, perm
|
117
|
-
|
118
|
-
|
119
|
-
def calc_inverse_matrix(mat: np.ndarray, verify: bool = False):
|
120
|
-
"""Given a square numpy(dtype=int) matrix mat, tries to compute its inverse.
|
121
|
-
|
122
|
-
Args:
|
123
|
-
mat: a boolean square matrix.
|
124
|
-
verify: if True asserts that the multiplication of mat and its inverse is the identity matrix.
|
125
|
-
|
126
|
-
Returns:
|
127
|
-
np.ndarray: the inverse matrix.
|
128
|
-
|
129
|
-
Raises:
|
130
|
-
QiskitError: if the matrix is not square.
|
131
|
-
QiskitError: if the matrix is not invertible.
|
132
|
-
"""
|
133
|
-
|
134
|
-
if mat.shape[0] != mat.shape[1]:
|
135
|
-
raise QiskitError("Matrix to invert is a non-square matrix.")
|
136
|
-
|
137
|
-
n = mat.shape[0]
|
138
|
-
# concatenate the matrix and identity
|
139
|
-
mat1 = np.concatenate((mat, np.eye(n, dtype=int)), axis=1)
|
140
|
-
mat1 = _gauss_elimination(mat1, None, full_elim=True)
|
141
|
-
|
142
|
-
r = _compute_rank_after_gauss_elim(mat1[:, 0:n])
|
143
|
-
|
144
|
-
if r < n:
|
145
|
-
raise QiskitError("The matrix is not invertible.")
|
146
|
-
|
147
|
-
matinv = mat1[:, n : 2 * n]
|
148
|
-
|
149
|
-
if verify:
|
150
|
-
mat2 = np.dot(mat, matinv) % 2
|
151
|
-
assert np.array_equal(mat2, np.eye(n))
|
152
|
-
|
153
|
-
return matinv
|
154
|
-
|
155
|
-
|
156
|
-
def _compute_rank_after_gauss_elim(mat):
|
157
|
-
"""Given a matrix A after Gaussian elimination, computes its rank
|
158
|
-
(i.e. simply the number of nonzero rows)"""
|
159
|
-
return np.sum(mat.any(axis=1))
|
160
|
-
|
161
|
-
|
162
|
-
def _compute_rank(mat):
|
163
|
-
"""Given a matrix A computes its rank"""
|
164
|
-
mat = _gauss_elimination(mat)
|
165
|
-
return np.sum(mat.any(axis=1))
|
166
|
-
|
167
|
-
|
168
|
-
def _row_op(mat, ctrl, trgt):
|
169
|
-
# Perform ROW operation on a matrix mat
|
170
|
-
mat[trgt] = mat[trgt] ^ mat[ctrl]
|
171
|
-
|
172
|
-
|
173
|
-
def _col_op(mat, ctrl, trgt):
|
174
|
-
# Perform COL operation on a matrix mat
|
175
|
-
mat[:, ctrl] = mat[:, trgt] ^ mat[:, ctrl]
|
15
|
+
# pylint: disable=unused-import
|
16
|
+
from qiskit._accelerate.synthesis.linear import (
|
17
|
+
gauss_elimination,
|
18
|
+
gauss_elimination_with_perm,
|
19
|
+
compute_rank_after_gauss_elim,
|
20
|
+
compute_rank,
|
21
|
+
calc_inverse_matrix,
|
22
|
+
binary_matmul,
|
23
|
+
random_invertible_binary_matrix,
|
24
|
+
check_invertible_binary_matrix,
|
25
|
+
row_op,
|
26
|
+
col_op,
|
27
|
+
)
|
@@ -123,7 +123,7 @@ def synth_cnot_phase_aam(
|
|
123
123
|
|
124
124
|
# Implementation of the pseudo-code (Algorithm 1) in the aforementioned paper
|
125
125
|
sta.append([cnots, range_list, epsilon])
|
126
|
-
while sta
|
126
|
+
while sta:
|
127
127
|
[cnots, ilist, qubit] = sta.pop()
|
128
128
|
if cnots == []:
|
129
129
|
continue
|
@@ -39,7 +39,7 @@ from qiskit.synthesis.linear.linear_depth_lnn import _optimize_cx_circ_depth_5n_
|
|
39
39
|
def _initialize_phase_schedule(mat_z):
|
40
40
|
"""
|
41
41
|
Given a CZ layer (represented as an n*n CZ matrix Mz)
|
42
|
-
Return a
|
42
|
+
Return a schedule of phase gates implementing Mz in a SWAP-only netwrok
|
43
43
|
(c.f. Alg 1, [2])
|
44
44
|
"""
|
45
45
|
n = len(mat_z)
|
@@ -173,7 +173,7 @@ def _apply_phase_to_nw_circuit(n, phase_schedule, seq, swap_plus):
|
|
173
173
|
of exactly n layers of boxes, each being either a SWAP or a SWAP+. That is,
|
174
174
|
each northwest diagonalization circuit can be uniquely represented by which
|
175
175
|
of its n(n-1)/2 boxes are SWAP+ and which are SWAP.
|
176
|
-
Return a QuantumCircuit that computes the phase
|
176
|
+
Return a QuantumCircuit that computes the phase schedule S inside CX
|
177
177
|
"""
|
178
178
|
cir = QuantumCircuit(n)
|
179
179
|
|
@@ -217,7 +217,7 @@ def _apply_phase_to_nw_circuit(n, phase_schedule, seq, swap_plus):
|
|
217
217
|
|
218
218
|
def synth_cx_cz_depth_line_my(mat_x: np.ndarray, mat_z: np.ndarray) -> QuantumCircuit:
|
219
219
|
"""
|
220
|
-
Joint synthesis of a -CZ-CX- circuit for linear nearest
|
220
|
+
Joint synthesis of a -CZ-CX- circuit for linear nearest neighbor (LNN) connectivity,
|
221
221
|
with 2-qubit depth at most 5n, based on Maslov and Yang.
|
222
222
|
This method computes the CZ circuit inside the CX circuit via phase gate insertions.
|
223
223
|
|
@@ -119,7 +119,7 @@ def _create_patterns(n):
|
|
119
119
|
|
120
120
|
|
121
121
|
def synth_cz_depth_line_mr(mat: np.ndarray) -> QuantumCircuit:
|
122
|
-
r"""Synthesis of a CZ circuit for linear nearest
|
122
|
+
r"""Synthesis of a CZ circuit for linear nearest neighbor (LNN) connectivity,
|
123
123
|
based on Maslov and Roetteler.
|
124
124
|
|
125
125
|
Note that this method *reverts* the order of qubits in the circuit,
|