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
@@ -357,9 +357,7 @@ class StochasticSwap(TransformationPass):
|
|
357
357
|
|
358
358
|
# Give up if we fail again
|
359
359
|
if not success_flag:
|
360
|
-
raise TranspilerError(
|
361
|
-
"swap mapper failed: " + "layer %d, sublayer %d" % (i, j)
|
362
|
-
)
|
360
|
+
raise TranspilerError(f"swap mapper failed: layer {i}, sublayer {j}")
|
363
361
|
|
364
362
|
# Update the record of qubit positions
|
365
363
|
# for each inner iteration
|
@@ -15,10 +15,9 @@
|
|
15
15
|
from qiskit.circuit import Delay, Qubit, Measure
|
16
16
|
from qiskit.dagcircuit import DAGCircuit
|
17
17
|
from qiskit.transpiler.exceptions import TranspilerError
|
18
|
+
from qiskit.transpiler.passes.scheduling.base_scheduler import BaseSchedulerTransform
|
18
19
|
from qiskit.utils.deprecation import deprecate_func
|
19
20
|
|
20
|
-
from .base_scheduler import BaseSchedulerTransform
|
21
|
-
|
22
21
|
|
23
22
|
class ALAPSchedule(BaseSchedulerTransform):
|
24
23
|
"""ALAP Scheduling pass, which schedules the **stop** time of instructions as late as possible.
|
@@ -44,7 +44,7 @@ Pulse alignment constraint
|
|
44
44
|
multiple of this value. Violation of this constraint may result in the
|
45
45
|
backend execution failure.
|
46
46
|
|
47
|
-
In most of the
|
47
|
+
In most of the scenarios, the scheduled start time of ``DAGOpNode`` corresponds to the
|
48
48
|
start time of the underlying pulse instruction composing the node operation.
|
49
49
|
However, this assumption can be intentionally broken by defining a pulse gate,
|
50
50
|
i.e. calibration, with the schedule involving pre-buffer, i.e. some random pulse delay
|
@@ -62,7 +62,7 @@ Granularity constraint
|
|
62
62
|
This value is reported by ``timing_constraints["granularity"]`` in the backend
|
63
63
|
configuration in units of dt. This is the constraint for a single pulse :class:`Play`
|
64
64
|
instruction that may constitute your pulse gate.
|
65
|
-
The length of waveform samples should be
|
65
|
+
The length of waveform samples should be multiple of this constraint value.
|
66
66
|
Violation of this constraint may result in failue in backend execution.
|
67
67
|
|
68
68
|
Minimum pulse length constraint
|
@@ -14,7 +14,7 @@
|
|
14
14
|
from qiskit.circuit.delay import Delay
|
15
15
|
from qiskit.dagcircuit import DAGCircuit
|
16
16
|
from qiskit.transpiler.basepasses import AnalysisPass
|
17
|
-
from qiskit.transpiler import Target
|
17
|
+
from qiskit.transpiler.target import Target
|
18
18
|
|
19
19
|
|
20
20
|
class InstructionDurationCheck(AnalysisPass):
|
@@ -16,7 +16,7 @@ from qiskit.dagcircuit import DAGCircuit
|
|
16
16
|
from qiskit.pulse import Play
|
17
17
|
from qiskit.transpiler.basepasses import AnalysisPass
|
18
18
|
from qiskit.transpiler.exceptions import TranspilerError
|
19
|
-
from qiskit.transpiler import Target
|
19
|
+
from qiskit.transpiler.target import Target
|
20
20
|
|
21
21
|
|
22
22
|
class ValidatePulseGates(AnalysisPass):
|
@@ -21,7 +21,7 @@ from qiskit.circuit.reset import Reset
|
|
21
21
|
from qiskit.dagcircuit import DAGCircuit, DAGOpNode, DAGOutNode
|
22
22
|
from qiskit.transpiler.basepasses import AnalysisPass
|
23
23
|
from qiskit.transpiler.exceptions import TranspilerError
|
24
|
-
from qiskit.transpiler import Target
|
24
|
+
from qiskit.transpiler.target import Target
|
25
25
|
|
26
26
|
|
27
27
|
class ConstrainedReschedule(AnalysisPass):
|
@@ -15,10 +15,9 @@
|
|
15
15
|
from qiskit.circuit import Delay, Qubit, Measure
|
16
16
|
from qiskit.dagcircuit import DAGCircuit
|
17
17
|
from qiskit.transpiler.exceptions import TranspilerError
|
18
|
+
from qiskit.transpiler.passes.scheduling.base_scheduler import BaseSchedulerTransform
|
18
19
|
from qiskit.utils.deprecation import deprecate_func
|
19
20
|
|
20
|
-
from .base_scheduler import BaseSchedulerTransform
|
21
|
-
|
22
21
|
|
23
22
|
class ASAPSchedule(BaseSchedulerTransform):
|
24
23
|
"""ASAP Scheduling pass, which schedules the start time of instructions as early as possible..
|
@@ -13,13 +13,13 @@
|
|
13
13
|
"""Base circuit scheduling pass."""
|
14
14
|
import warnings
|
15
15
|
|
16
|
-
from qiskit.transpiler import InstructionDurations
|
17
|
-
from qiskit.transpiler.basepasses import TransformationPass
|
18
|
-
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
|
19
|
-
from qiskit.dagcircuit import DAGOpNode, DAGCircuit, DAGOutNode
|
20
16
|
from qiskit.circuit import Delay, Gate, Measure, Reset
|
21
17
|
from qiskit.circuit.parameterexpression import ParameterExpression
|
18
|
+
from qiskit.dagcircuit import DAGOpNode, DAGCircuit, DAGOutNode
|
19
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
22
20
|
from qiskit.transpiler.exceptions import TranspilerError
|
21
|
+
from qiskit.transpiler.instruction_durations import InstructionDurations
|
22
|
+
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
|
23
23
|
from qiskit.transpiler.target import Target
|
24
24
|
|
25
25
|
|
@@ -68,7 +68,7 @@ class BaseSchedulerTransform(TransformationPass):
|
|
68
68
|
However, such optimization should be done by another pass,
|
69
69
|
otherwise scheduling may break topological ordering of the original circuit.
|
70
70
|
|
71
|
-
Realistic control flow scheduling respecting for
|
71
|
+
Realistic control flow scheduling respecting for microarchitecture
|
72
72
|
|
73
73
|
In the dispersive QND readout scheme, qubit is measured with microwave stimulus to qubit (Q)
|
74
74
|
followed by resonator ring-down (depopulation). This microwave signal is recorded
|
@@ -20,10 +20,10 @@ from qiskit.circuit.library.standard_gates import IGate, UGate, U3Gate
|
|
20
20
|
from qiskit.dagcircuit import DAGOpNode, DAGInNode
|
21
21
|
from qiskit.quantum_info.operators.predicates import matrix_equal
|
22
22
|
from qiskit.synthesis.one_qubit import OneQubitEulerDecomposer
|
23
|
-
from qiskit.transpiler import InstructionDurations
|
24
|
-
from qiskit.transpiler.passes.optimization import Optimize1qGates
|
25
23
|
from qiskit.transpiler.basepasses import TransformationPass
|
26
24
|
from qiskit.transpiler.exceptions import TranspilerError
|
25
|
+
from qiskit.transpiler.instruction_durations import InstructionDurations
|
26
|
+
from qiskit.transpiler.passes.optimization import Optimize1qGates
|
27
27
|
from qiskit.utils.deprecation import deprecate_func
|
28
28
|
|
29
29
|
|
@@ -130,7 +130,7 @@ class DynamicalDecoupling(TransformationPass):
|
|
130
130
|
will be used [d/2, d, d, ..., d, d, d/2].
|
131
131
|
skip_reset_qubits (bool): if True, does not insert DD on idle
|
132
132
|
periods that immediately follow initialized/reset qubits (as
|
133
|
-
qubits in the ground state are less
|
133
|
+
qubits in the ground state are less susceptible to decoherence).
|
134
134
|
target (Target): The :class:`~.Target` representing the target backend, if both
|
135
135
|
``durations`` and this are specified then this argument will take
|
136
136
|
precedence and ``durations`` will be ignored.
|
@@ -202,7 +202,7 @@ class BasePadding(TransformationPass):
|
|
202
202
|
):
|
203
203
|
"""Add new operation to DAG with scheduled information.
|
204
204
|
|
205
|
-
This is identical to apply_operation_back + updating the node_start_time
|
205
|
+
This is identical to apply_operation_back + updating the node_start_time property.
|
206
206
|
|
207
207
|
Args:
|
208
208
|
dag: DAG circuit on which the sequence is applied.
|
@@ -26,9 +26,9 @@ from qiskit.synthesis.one_qubit import OneQubitEulerDecomposer
|
|
26
26
|
from qiskit.transpiler.exceptions import TranspilerError
|
27
27
|
from qiskit.transpiler.instruction_durations import InstructionDurations
|
28
28
|
from qiskit.transpiler.passes.optimization import Optimize1qGates
|
29
|
+
from qiskit.transpiler.passes.scheduling.padding.base_padding import BasePadding
|
29
30
|
from qiskit.transpiler.target import Target
|
30
31
|
|
31
|
-
from .base_padding import BasePadding
|
32
32
|
|
33
33
|
logger = logging.getLogger(__name__)
|
34
34
|
|
@@ -128,7 +128,7 @@ class PadDynamicalDecoupling(BasePadding):
|
|
128
128
|
will be used [d/2, d, d, ..., d, d, d/2].
|
129
129
|
skip_reset_qubits: If True, does not insert DD on idle periods that
|
130
130
|
immediately follow initialized/reset qubits
|
131
|
-
(as qubits in the ground state are less
|
131
|
+
(as qubits in the ground state are less susceptible to decoherence).
|
132
132
|
pulse_alignment: The hardware constraints for gate timing allocation.
|
133
133
|
This is usually provided from ``backend.configuration().timing_constraints``.
|
134
134
|
If provided, the delay length, i.e. ``spacing``, is implicitly adjusted to
|
@@ -311,7 +311,7 @@ class PadDynamicalDecoupling(BasePadding):
|
|
311
311
|
# slack = 992 dt - 4 x 160 dt = 352 dt
|
312
312
|
#
|
313
313
|
# unconstraind sequence: 44dt-X1-88dt-Y2-88dt-X3-88dt-Y4-44dt
|
314
|
-
#
|
314
|
+
# constrained sequence : 32dt-X1-80dt-Y2-80dt-X3-80dt-Y4-32dt + extra slack 48 dt
|
315
315
|
#
|
316
316
|
# Now we evenly split extra slack into start and end of the sequence.
|
317
317
|
# The distributed slack should be multiple of 16.
|
@@ -361,17 +361,17 @@ class PadDynamicalDecoupling(BasePadding):
|
|
361
361
|
theta, phi, lam, phase = OneQubitEulerDecomposer().angles_and_phase(u_inv)
|
362
362
|
if isinstance(next_node, DAGOpNode) and isinstance(next_node.op, (UGate, U3Gate)):
|
363
363
|
# Absorb the inverse into the successor (from left in circuit)
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
364
|
+
op = next_node.op
|
365
|
+
theta_r, phi_r, lam_r = op.params
|
366
|
+
op.params = Optimize1qGates.compose_u3(theta_r, phi_r, lam_r, theta, phi, lam)
|
367
|
+
next_node.op = op
|
368
368
|
sequence_gphase += phase
|
369
369
|
elif isinstance(prev_node, DAGOpNode) and isinstance(prev_node.op, (UGate, U3Gate)):
|
370
370
|
# Absorb the inverse into the predecessor (from right in circuit)
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
371
|
+
op = prev_node.op
|
372
|
+
theta_l, phi_l, lam_l = op.params
|
373
|
+
op.params = Optimize1qGates.compose_u3(theta, phi, lam, theta_l, phi_l, lam_l)
|
374
|
+
prev_node.op = op
|
375
375
|
sequence_gphase += phase
|
376
376
|
else:
|
377
377
|
# Don't do anything if there's no single-qubit gate to absorb the inverse
|
@@ -14,13 +14,13 @@
|
|
14
14
|
|
15
15
|
import warnings
|
16
16
|
|
17
|
-
from qiskit.transpiler import InstructionDurations
|
18
|
-
from qiskit.transpiler.basepasses import AnalysisPass
|
19
|
-
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
|
20
|
-
from qiskit.dagcircuit import DAGOpNode, DAGCircuit
|
21
17
|
from qiskit.circuit import Delay, Gate
|
22
18
|
from qiskit.circuit.parameterexpression import ParameterExpression
|
19
|
+
from qiskit.dagcircuit import DAGOpNode, DAGCircuit
|
20
|
+
from qiskit.transpiler.basepasses import AnalysisPass
|
23
21
|
from qiskit.transpiler.exceptions import TranspilerError
|
22
|
+
from qiskit.transpiler.instruction_durations import InstructionDurations
|
23
|
+
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
|
24
24
|
from qiskit.transpiler.target import Target
|
25
25
|
|
26
26
|
|
@@ -70,8 +70,9 @@ class BaseScheduler(AnalysisPass):
|
|
70
70
|
duration = dag.calibrations[node.op.name][cal_key].duration
|
71
71
|
|
72
72
|
# Note that node duration is updated (but this is analysis pass)
|
73
|
-
|
74
|
-
|
73
|
+
op = node.op.to_mutable()
|
74
|
+
op.duration = duration
|
75
|
+
node.op = op
|
75
76
|
else:
|
76
77
|
duration = node.op.duration
|
77
78
|
|
@@ -105,9 +105,10 @@ class TimeUnitConversion(TransformationPass):
|
|
105
105
|
)
|
106
106
|
except TranspilerError:
|
107
107
|
continue
|
108
|
-
|
109
|
-
|
110
|
-
|
108
|
+
op = node.op.to_mutable()
|
109
|
+
op.duration = duration
|
110
|
+
op.unit = time_unit
|
111
|
+
node.op = op
|
111
112
|
|
112
113
|
self.property_set["time_unit"] = time_unit
|
113
114
|
return dag
|
@@ -131,9 +131,38 @@ Permutation Synthesis
|
|
131
131
|
ACGSynthesisPermutation
|
132
132
|
KMSSynthesisPermutation
|
133
133
|
TokenSwapperSynthesisPermutation
|
134
|
+
|
135
|
+
|
136
|
+
QFT Synthesis
|
137
|
+
'''''''''''''
|
138
|
+
|
139
|
+
.. list-table:: Plugins for :class:`.QFTGate` (key = ``"qft"``)
|
140
|
+
:header-rows: 1
|
141
|
+
|
142
|
+
* - Plugin name
|
143
|
+
- Plugin class
|
144
|
+
- Targeted connectivity
|
145
|
+
* - ``"full"``
|
146
|
+
- :class:`~.QFTSynthesisFull`
|
147
|
+
- all-to-all
|
148
|
+
* - ``"line"``
|
149
|
+
- :class:`~.QFTSynthesisLine`
|
150
|
+
- linear
|
151
|
+
* - ``"default"``
|
152
|
+
- :class:`~.QFTSynthesisFull`
|
153
|
+
- all-to-all
|
154
|
+
|
155
|
+
.. autosummary::
|
156
|
+
:toctree: ../stubs/
|
157
|
+
|
158
|
+
QFTSynthesisFull
|
159
|
+
QFTSynthesisLine
|
134
160
|
"""
|
135
161
|
|
136
|
-
from
|
162
|
+
from __future__ import annotations
|
163
|
+
|
164
|
+
import typing
|
165
|
+
from typing import Optional, Union, List, Tuple, Callable, Sequence
|
137
166
|
|
138
167
|
import numpy as np
|
139
168
|
import rustworkx as rx
|
@@ -142,7 +171,7 @@ from qiskit.circuit.operation import Operation
|
|
142
171
|
from qiskit.converters import circuit_to_dag, dag_to_circuit
|
143
172
|
from qiskit.transpiler.basepasses import TransformationPass
|
144
173
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
145
|
-
from qiskit.circuit import
|
174
|
+
from qiskit.circuit import ControlledGate, EquivalenceLibrary, equivalence
|
146
175
|
from qiskit.circuit.library import LinearFunction
|
147
176
|
from qiskit.transpiler.passes.utils import control_flow
|
148
177
|
from qiskit.transpiler.target import Target
|
@@ -157,6 +186,7 @@ from qiskit.circuit.annotated_operation import (
|
|
157
186
|
ControlModifier,
|
158
187
|
PowerModifier,
|
159
188
|
)
|
189
|
+
from qiskit.circuit.library import QFTGate
|
160
190
|
from qiskit.synthesis.clifford import (
|
161
191
|
synth_clifford_full,
|
162
192
|
synth_clifford_layers,
|
@@ -176,9 +206,16 @@ from qiskit.synthesis.permutation import (
|
|
176
206
|
synth_permutation_acg,
|
177
207
|
synth_permutation_depth_lnn_kms,
|
178
208
|
)
|
209
|
+
from qiskit.synthesis.qft import (
|
210
|
+
synth_qft_full,
|
211
|
+
synth_qft_line,
|
212
|
+
)
|
179
213
|
|
180
214
|
from .plugin import HighLevelSynthesisPluginManager, HighLevelSynthesisPlugin
|
181
215
|
|
216
|
+
if typing.TYPE_CHECKING:
|
217
|
+
from qiskit.dagcircuit import DAGOpNode
|
218
|
+
|
182
219
|
|
183
220
|
class HLSConfig:
|
184
221
|
"""The high-level-synthesis config allows to specify a list of "methods" used by
|
@@ -365,6 +402,8 @@ class HighLevelSynthesis(TransformationPass):
|
|
365
402
|
if not self._top_level_only and (self._target is None or self._target.num_qubits is None):
|
366
403
|
basic_insts = {"measure", "reset", "barrier", "snapshot", "delay", "store"}
|
367
404
|
self._device_insts = basic_insts | set(self._basis_gates)
|
405
|
+
else:
|
406
|
+
self._device_insts = set()
|
368
407
|
|
369
408
|
def run(self, dag: DAGCircuit) -> DAGCircuit:
|
370
409
|
"""Run the HighLevelSynthesis pass on `dag`.
|
@@ -384,11 +423,11 @@ class HighLevelSynthesis(TransformationPass):
|
|
384
423
|
dag_op_nodes = dag.op_nodes()
|
385
424
|
|
386
425
|
for node in dag_op_nodes:
|
387
|
-
if
|
426
|
+
if node.is_control_flow():
|
388
427
|
node.op = control_flow.map_blocks(self.run, node.op)
|
389
428
|
continue
|
390
429
|
|
391
|
-
if
|
430
|
+
if node.is_directive():
|
392
431
|
continue
|
393
432
|
|
394
433
|
if dag.has_calibration_for(node) or len(node.qargs) < self._min_qubits:
|
@@ -398,6 +437,9 @@ class HighLevelSynthesis(TransformationPass):
|
|
398
437
|
[dag.find_bit(x).index for x in node.qargs] if self._use_qubit_indices else None
|
399
438
|
)
|
400
439
|
|
440
|
+
if self._definitely_skip_node(node, qubits):
|
441
|
+
continue
|
442
|
+
|
401
443
|
decomposition, modified = self._recursively_handle_op(node.op, qubits)
|
402
444
|
|
403
445
|
if not modified:
|
@@ -414,6 +456,43 @@ class HighLevelSynthesis(TransformationPass):
|
|
414
456
|
|
415
457
|
return dag
|
416
458
|
|
459
|
+
def _definitely_skip_node(self, node: DAGOpNode, qubits: Sequence[int] | None) -> bool:
|
460
|
+
"""Fast-path determination of whether a node can certainly be skipped (i.e. nothing will
|
461
|
+
attempt to synthesise it) without accessing its Python-space `Operation`.
|
462
|
+
|
463
|
+
This is tightly coupled to `_recursively_handle_op`; it exists as a temporary measure to
|
464
|
+
avoid Python-space `Operation` creation from a `DAGOpNode` if we wouldn't do anything to the
|
465
|
+
node (which is _most_ nodes)."""
|
466
|
+
return (
|
467
|
+
# The fast path is just for Rust-space standard gates (which excludes
|
468
|
+
# `AnnotatedOperation`).
|
469
|
+
node.is_standard_gate()
|
470
|
+
# If it's a controlled gate, we might choose to do funny things to it.
|
471
|
+
and not node.is_controlled_gate()
|
472
|
+
# If there are plugins to try, they need to be tried.
|
473
|
+
and not self._methods_to_try(node.name)
|
474
|
+
# If all the above constraints hold, and it's already supported or the basis translator
|
475
|
+
# can handle it, we'll leave it be.
|
476
|
+
and (
|
477
|
+
self._instruction_supported(node.name, qubits)
|
478
|
+
# This uses unfortunately private details of `EquivalenceLibrary`, but so does the
|
479
|
+
# `BasisTranslator`, and this is supposed to just be temporary til this is moved
|
480
|
+
# into Rust space.
|
481
|
+
or (
|
482
|
+
self._equiv_lib is not None
|
483
|
+
and equivalence.Key(name=node.name, num_qubits=node.num_qubits)
|
484
|
+
in self._equiv_lib._key_to_node_index
|
485
|
+
)
|
486
|
+
)
|
487
|
+
)
|
488
|
+
|
489
|
+
def _instruction_supported(self, name: str, qubits: Sequence[int]) -> bool:
|
490
|
+
qubits = tuple(qubits) if qubits is not None else None
|
491
|
+
# include path for when target exists but target.num_qubits is None (BasicSimulator)
|
492
|
+
if self._target is None or self._target.num_qubits is None:
|
493
|
+
return name in self._device_insts
|
494
|
+
return self._target.instruction_supported(operation_name=name, qargs=qubits)
|
495
|
+
|
417
496
|
def _recursively_handle_op(
|
418
497
|
self, op: Operation, qubits: Optional[List] = None
|
419
498
|
) -> Tuple[Union[QuantumCircuit, DAGCircuit, Operation], bool]:
|
@@ -441,6 +520,9 @@ class HighLevelSynthesis(TransformationPass):
|
|
441
520
|
an annotated operation.
|
442
521
|
"""
|
443
522
|
|
523
|
+
# WARNING: if adding new things in here, ensure that `_definitely_skip_node` is also
|
524
|
+
# up-to-date.
|
525
|
+
|
444
526
|
# Try to apply plugin mechanism
|
445
527
|
decomposition = self._synthesize_op_using_plugins(op, qubits)
|
446
528
|
if decomposition is not None:
|
@@ -459,17 +541,9 @@ class HighLevelSynthesis(TransformationPass):
|
|
459
541
|
# or is in equivalence library
|
460
542
|
controlled_gate_open_ctrl = isinstance(op, ControlledGate) and op._open_ctrl
|
461
543
|
if not controlled_gate_open_ctrl:
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
self._target.instruction_supported(
|
466
|
-
operation_name=op.name,
|
467
|
-
qargs=qargs,
|
468
|
-
)
|
469
|
-
if self._target is not None and self._target.num_qubits is not None
|
470
|
-
else op.name in self._device_insts
|
471
|
-
)
|
472
|
-
if inst_supported or (self._equiv_lib is not None and self._equiv_lib.has_entry(op)):
|
544
|
+
if self._instruction_supported(op.name, qubits) or (
|
545
|
+
self._equiv_lib is not None and self._equiv_lib.has_entry(op)
|
546
|
+
):
|
473
547
|
return op, False
|
474
548
|
|
475
549
|
try:
|
@@ -490,6 +564,22 @@ class HighLevelSynthesis(TransformationPass):
|
|
490
564
|
dag = self.run(dag)
|
491
565
|
return dag, True
|
492
566
|
|
567
|
+
def _methods_to_try(self, name: str):
|
568
|
+
"""Get a sequence of methods to try for a given op name."""
|
569
|
+
if (methods := self.hls_config.methods.get(name)) is not None:
|
570
|
+
# the operation's name appears in the user-provided config,
|
571
|
+
# we use the list of methods provided by the user
|
572
|
+
return methods
|
573
|
+
if (
|
574
|
+
self.hls_config.use_default_on_unspecified
|
575
|
+
and "default" in self.hls_plugin_manager.method_names(name)
|
576
|
+
):
|
577
|
+
# the operation's name does not appear in the user-specified config,
|
578
|
+
# we use the "default" method when instructed to do so and the "default"
|
579
|
+
# method is available
|
580
|
+
return ["default"]
|
581
|
+
return []
|
582
|
+
|
493
583
|
def _synthesize_op_using_plugins(
|
494
584
|
self, op: Operation, qubits: List
|
495
585
|
) -> Union[QuantumCircuit, None]:
|
@@ -500,25 +590,10 @@ class HighLevelSynthesis(TransformationPass):
|
|
500
590
|
"""
|
501
591
|
hls_plugin_manager = self.hls_plugin_manager
|
502
592
|
|
503
|
-
if op.name in self.hls_config.methods.keys():
|
504
|
-
# the operation's name appears in the user-provided config,
|
505
|
-
# we use the list of methods provided by the user
|
506
|
-
methods = self.hls_config.methods[op.name]
|
507
|
-
elif (
|
508
|
-
self.hls_config.use_default_on_unspecified
|
509
|
-
and "default" in hls_plugin_manager.method_names(op.name)
|
510
|
-
):
|
511
|
-
# the operation's name does not appear in the user-specified config,
|
512
|
-
# we use the "default" method when instructed to do so and the "default"
|
513
|
-
# method is available
|
514
|
-
methods = ["default"]
|
515
|
-
else:
|
516
|
-
methods = []
|
517
|
-
|
518
593
|
best_decomposition = None
|
519
594
|
best_score = np.inf
|
520
595
|
|
521
|
-
for method in
|
596
|
+
for method in self._methods_to_try(op.name):
|
522
597
|
# There are two ways to specify a synthesis method. The more explicit
|
523
598
|
# way is to specify it as a tuple consisting of a synthesis algorithm and a
|
524
599
|
# list of additional arguments, e.g.,
|
@@ -540,8 +615,8 @@ class HighLevelSynthesis(TransformationPass):
|
|
540
615
|
if isinstance(plugin_specifier, str):
|
541
616
|
if plugin_specifier not in hls_plugin_manager.method_names(op.name):
|
542
617
|
raise TranspilerError(
|
543
|
-
"Specified method:
|
544
|
-
|
618
|
+
f"Specified method: {plugin_specifier} not found in available "
|
619
|
+
f"plugins for {op.name}"
|
545
620
|
)
|
546
621
|
plugin_method = hls_plugin_manager.method(op.name, plugin_specifier)
|
547
622
|
else:
|
@@ -779,7 +854,7 @@ class KMSSynthesisLinearFunction(HighLevelSynthesisPlugin):
|
|
779
854
|
use_inverted = options.get("use_inverted", False)
|
780
855
|
use_transposed = options.get("use_transposed", False)
|
781
856
|
|
782
|
-
mat = high_level_object.linear.astype(
|
857
|
+
mat = high_level_object.linear.astype(bool, copy=False)
|
783
858
|
|
784
859
|
if use_transposed:
|
785
860
|
mat = np.transpose(mat)
|
@@ -831,7 +906,7 @@ class PMHSynthesisLinearFunction(HighLevelSynthesisPlugin):
|
|
831
906
|
use_inverted = options.get("use_inverted", False)
|
832
907
|
use_transposed = options.get("use_transposed", False)
|
833
908
|
|
834
|
-
mat = high_level_object.linear.astype(
|
909
|
+
mat = high_level_object.linear.astype(bool, copy=False)
|
835
910
|
|
836
911
|
if use_transposed:
|
837
912
|
mat = np.transpose(mat)
|
@@ -887,6 +962,107 @@ class ACGSynthesisPermutation(HighLevelSynthesisPlugin):
|
|
887
962
|
return decomposition
|
888
963
|
|
889
964
|
|
965
|
+
class QFTSynthesisFull(HighLevelSynthesisPlugin):
|
966
|
+
"""Synthesis plugin for QFT gates using all-to-all connectivity.
|
967
|
+
|
968
|
+
This plugin name is :``qft.full`` which can be used as the key on
|
969
|
+
an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
|
970
|
+
|
971
|
+
The plugin supports the following additional options:
|
972
|
+
|
973
|
+
* reverse_qubits (bool): Whether to synthesize the "QFT" operation (if ``False``,
|
974
|
+
which is the default) or the "QFT-with-reversal" operation (if ``True``).
|
975
|
+
Some implementation of the ``QFTGate`` include a layer of swap gates at the end
|
976
|
+
of the synthesized circuit, which can in principle be dropped if the ``QFTGate``
|
977
|
+
itself is the last gate in the circuit.
|
978
|
+
* approximation_degree (int): The degree of approximation (0 for no approximation).
|
979
|
+
It is possible to implement the QFT approximately by ignoring
|
980
|
+
controlled-phase rotations with the angle beneath a threshold. This is discussed
|
981
|
+
in more detail in [1] or [2].
|
982
|
+
* insert_barriers (bool): If True, barriers are inserted as visualization improvement.
|
983
|
+
* inverse (bool): If True, the inverse Fourier transform is constructed.
|
984
|
+
* name (str): The name of the circuit.
|
985
|
+
|
986
|
+
References:
|
987
|
+
1. Adriano Barenco, Artur Ekert, Kalle-Antti Suominen, and Päivi Törmä,
|
988
|
+
*Approximate Quantum Fourier Transform and Decoherence*,
|
989
|
+
Physical Review A (1996).
|
990
|
+
`arXiv:quant-ph/9601018 [quant-ph] <https://arxiv.org/abs/quant-ph/9601018>`_
|
991
|
+
2. Donny Cheung,
|
992
|
+
*Improved Bounds for the Approximate QFT* (2004),
|
993
|
+
`arXiv:quant-ph/0403071 [quant-ph] <https://https://arxiv.org/abs/quant-ph/0403071>`_
|
994
|
+
"""
|
995
|
+
|
996
|
+
def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
|
997
|
+
"""Run synthesis for the given QFTGate."""
|
998
|
+
if not isinstance(high_level_object, QFTGate):
|
999
|
+
raise TranspilerError(
|
1000
|
+
"The synthesis plugin 'qft.full` only applies to objects of type QFTGate."
|
1001
|
+
)
|
1002
|
+
|
1003
|
+
reverse_qubits = options.get("reverse_qubits", False)
|
1004
|
+
approximation_degree = options.get("approximation_degree", 0)
|
1005
|
+
insert_barriers = options.get("insert_barriers", False)
|
1006
|
+
inverse = options.get("inverse", False)
|
1007
|
+
name = options.get("name", None)
|
1008
|
+
|
1009
|
+
decomposition = synth_qft_full(
|
1010
|
+
num_qubits=high_level_object.num_qubits,
|
1011
|
+
do_swaps=not reverse_qubits,
|
1012
|
+
approximation_degree=approximation_degree,
|
1013
|
+
insert_barriers=insert_barriers,
|
1014
|
+
inverse=inverse,
|
1015
|
+
name=name,
|
1016
|
+
)
|
1017
|
+
return decomposition
|
1018
|
+
|
1019
|
+
|
1020
|
+
class QFTSynthesisLine(HighLevelSynthesisPlugin):
|
1021
|
+
"""Synthesis plugin for QFT gates using linear connectivity.
|
1022
|
+
|
1023
|
+
This plugin name is :``qft.line`` which can be used as the key on
|
1024
|
+
an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
|
1025
|
+
|
1026
|
+
The plugin supports the following additional options:
|
1027
|
+
|
1028
|
+
* reverse_qubits (bool): Whether to synthesize the "QFT" operation (if ``False``,
|
1029
|
+
which is the default) or the "QFT-with-reversal" operation (if ``True``).
|
1030
|
+
Some implementation of the ``QFTGate`` include a layer of swap gates at the end
|
1031
|
+
of the synthesized circuit, which can in principle be dropped if the ``QFTGate``
|
1032
|
+
itself is the last gate in the circuit.
|
1033
|
+
* approximation_degree (int): the degree of approximation (0 for no approximation).
|
1034
|
+
It is possible to implement the QFT approximately by ignoring
|
1035
|
+
controlled-phase rotations with the angle beneath a threshold. This is discussed
|
1036
|
+
in more detail in [1] or [2].
|
1037
|
+
|
1038
|
+
References:
|
1039
|
+
1. Adriano Barenco, Artur Ekert, Kalle-Antti Suominen, and Päivi Törmä,
|
1040
|
+
*Approximate Quantum Fourier Transform and Decoherence*,
|
1041
|
+
Physical Review A (1996).
|
1042
|
+
`arXiv:quant-ph/9601018 [quant-ph] <https://arxiv.org/abs/quant-ph/9601018>`_
|
1043
|
+
2. Donny Cheung,
|
1044
|
+
*Improved Bounds for the Approximate QFT* (2004),
|
1045
|
+
`arXiv:quant-ph/0403071 [quant-ph] <https://https://arxiv.org/abs/quant-ph/0403071>`_
|
1046
|
+
"""
|
1047
|
+
|
1048
|
+
def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
|
1049
|
+
"""Run synthesis for the given QFTGate."""
|
1050
|
+
if not isinstance(high_level_object, QFTGate):
|
1051
|
+
raise TranspilerError(
|
1052
|
+
"The synthesis plugin 'qft.line` only applies to objects of type QFTGate."
|
1053
|
+
)
|
1054
|
+
|
1055
|
+
reverse_qubits = options.get("reverse_qubits", False)
|
1056
|
+
approximation_degree = options.get("approximation_degree", 0)
|
1057
|
+
|
1058
|
+
decomposition = synth_qft_line(
|
1059
|
+
num_qubits=high_level_object.num_qubits,
|
1060
|
+
do_swaps=not reverse_qubits,
|
1061
|
+
approximation_degree=approximation_degree,
|
1062
|
+
)
|
1063
|
+
return decomposition
|
1064
|
+
|
1065
|
+
|
890
1066
|
class TokenSwapperSynthesisPermutation(HighLevelSynthesisPlugin):
|
891
1067
|
"""The permutation synthesis plugin based on the token swapper algorithm.
|
892
1068
|
|
@@ -917,7 +1093,6 @@ class TokenSwapperSynthesisPermutation(HighLevelSynthesisPlugin):
|
|
917
1093
|
|
918
1094
|
For more details on the token swapper algorithm, see to the paper:
|
919
1095
|
`arXiv:1902.09102 <https://arxiv.org/abs/1902.09102>`__.
|
920
|
-
|
921
1096
|
"""
|
922
1097
|
|
923
1098
|
def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
|
@@ -698,13 +698,13 @@ class HighLevelSynthesisPluginManager:
|
|
698
698
|
self.plugins_by_op = {}
|
699
699
|
for plugin_name in self.plugins.names():
|
700
700
|
op_name, method_name = plugin_name.split(".")
|
701
|
-
if op_name not in self.plugins_by_op
|
701
|
+
if op_name not in self.plugins_by_op:
|
702
702
|
self.plugins_by_op[op_name] = []
|
703
703
|
self.plugins_by_op[op_name].append(method_name)
|
704
704
|
|
705
705
|
def method_names(self, op_name):
|
706
706
|
"""Returns plugin methods for op_name."""
|
707
|
-
if op_name in self.plugins_by_op
|
707
|
+
if op_name in self.plugins_by_op:
|
708
708
|
return self.plugins_by_op[op_name]
|
709
709
|
else:
|
710
710
|
return []
|