qiskit 1.0.2__cp38-abi3-win32.whl → 1.1.0__cp38-abi3-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qiskit/VERSION.txt +1 -1
- qiskit/__init__.py +27 -16
- qiskit/_accelerate.pyd +0 -0
- qiskit/_numpy_compat.py +73 -0
- qiskit/assembler/__init__.py +5 -10
- qiskit/assembler/disassemble.py +5 -6
- qiskit/circuit/__init__.py +1061 -232
- qiskit/circuit/_classical_resource_map.py +10 -6
- qiskit/circuit/_utils.py +18 -8
- qiskit/circuit/annotated_operation.py +21 -0
- qiskit/circuit/barrier.py +10 -13
- qiskit/circuit/bit.py +0 -1
- qiskit/circuit/classical/__init__.py +2 -2
- qiskit/circuit/classical/expr/__init__.py +39 -5
- qiskit/circuit/classical/expr/constructors.py +84 -1
- qiskit/circuit/classical/expr/expr.py +83 -13
- qiskit/circuit/classical/expr/visitors.py +83 -0
- qiskit/circuit/classical/types/__init__.py +5 -4
- qiskit/circuit/classicalfunction/__init__.py +1 -0
- qiskit/circuit/commutation_checker.py +86 -51
- qiskit/circuit/controlflow/_builder_utils.py +9 -1
- qiskit/circuit/controlflow/break_loop.py +8 -22
- qiskit/circuit/controlflow/builder.py +116 -1
- qiskit/circuit/controlflow/continue_loop.py +8 -22
- qiskit/circuit/controlflow/control_flow.py +47 -8
- qiskit/circuit/controlflow/for_loop.py +8 -23
- qiskit/circuit/controlflow/if_else.py +13 -27
- qiskit/circuit/controlflow/switch_case.py +14 -21
- qiskit/circuit/controlflow/while_loop.py +9 -23
- qiskit/circuit/controlledgate.py +2 -2
- qiskit/circuit/delay.py +7 -5
- qiskit/circuit/gate.py +20 -7
- qiskit/circuit/instruction.py +31 -30
- qiskit/circuit/instructionset.py +9 -22
- qiskit/circuit/library/__init__.py +3 -13
- qiskit/circuit/library/arithmetic/integer_comparator.py +2 -2
- qiskit/circuit/library/arithmetic/quadratic_form.py +3 -2
- qiskit/circuit/library/blueprintcircuit.py +29 -7
- qiskit/circuit/library/data_preparation/state_preparation.py +6 -5
- qiskit/circuit/library/generalized_gates/diagonal.py +5 -4
- qiskit/circuit/library/generalized_gates/isometry.py +51 -254
- qiskit/circuit/library/generalized_gates/pauli.py +2 -2
- qiskit/circuit/library/generalized_gates/permutation.py +4 -1
- qiskit/circuit/library/generalized_gates/rv.py +15 -11
- qiskit/circuit/library/generalized_gates/uc.py +2 -98
- qiskit/circuit/library/generalized_gates/unitary.py +9 -4
- qiskit/circuit/library/hamiltonian_gate.py +11 -5
- qiskit/circuit/library/n_local/efficient_su2.py +5 -5
- qiskit/circuit/library/n_local/n_local.py +100 -49
- qiskit/circuit/library/n_local/two_local.py +3 -59
- qiskit/circuit/library/overlap.py +3 -3
- qiskit/circuit/library/phase_oracle.py +1 -1
- qiskit/circuit/library/quantum_volume.py +39 -38
- qiskit/circuit/library/standard_gates/equivalence_library.py +50 -0
- qiskit/circuit/library/standard_gates/global_phase.py +4 -2
- qiskit/circuit/library/standard_gates/i.py +1 -2
- qiskit/circuit/library/standard_gates/iswap.py +1 -2
- qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +11 -5
- qiskit/circuit/library/standard_gates/p.py +31 -15
- qiskit/circuit/library/standard_gates/r.py +4 -3
- qiskit/circuit/library/standard_gates/rx.py +7 -4
- qiskit/circuit/library/standard_gates/rxx.py +4 -3
- qiskit/circuit/library/standard_gates/ry.py +7 -4
- qiskit/circuit/library/standard_gates/ryy.py +4 -3
- qiskit/circuit/library/standard_gates/rz.py +7 -4
- qiskit/circuit/library/standard_gates/rzx.py +4 -3
- qiskit/circuit/library/standard_gates/rzz.py +4 -3
- qiskit/circuit/library/standard_gates/s.py +4 -8
- qiskit/circuit/library/standard_gates/t.py +2 -4
- qiskit/circuit/library/standard_gates/u.py +16 -11
- qiskit/circuit/library/standard_gates/u1.py +6 -2
- qiskit/circuit/library/standard_gates/u2.py +4 -2
- qiskit/circuit/library/standard_gates/u3.py +9 -5
- qiskit/circuit/library/standard_gates/x.py +22 -11
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +4 -3
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +7 -5
- qiskit/circuit/library/standard_gates/z.py +1 -2
- qiskit/circuit/measure.py +4 -1
- qiskit/circuit/operation.py +13 -8
- qiskit/circuit/parameter.py +11 -6
- qiskit/circuit/quantumcircuit.py +1910 -260
- qiskit/circuit/quantumcircuitdata.py +2 -2
- qiskit/circuit/reset.py +5 -2
- qiskit/circuit/store.py +95 -0
- qiskit/compiler/assembler.py +22 -22
- qiskit/compiler/transpiler.py +63 -112
- qiskit/converters/__init__.py +17 -2
- qiskit/converters/circuit_to_dag.py +7 -0
- qiskit/converters/circuit_to_dagdependency_v2.py +47 -0
- qiskit/converters/circuit_to_gate.py +2 -0
- qiskit/converters/circuit_to_instruction.py +22 -0
- qiskit/converters/dag_to_circuit.py +4 -0
- qiskit/converters/dag_to_dagdependency_v2.py +44 -0
- qiskit/dagcircuit/collect_blocks.py +15 -10
- qiskit/dagcircuit/dagcircuit.py +434 -124
- qiskit/dagcircuit/dagdependency.py +19 -12
- qiskit/dagcircuit/dagdependency_v2.py +641 -0
- qiskit/dagcircuit/dagdepnode.py +19 -16
- qiskit/dagcircuit/dagnode.py +14 -4
- qiskit/passmanager/passmanager.py +11 -11
- qiskit/primitives/__init__.py +22 -12
- qiskit/primitives/backend_estimator.py +3 -5
- qiskit/primitives/backend_estimator_v2.py +410 -0
- qiskit/primitives/backend_sampler_v2.py +287 -0
- qiskit/primitives/base/base_estimator.py +4 -9
- qiskit/primitives/base/base_sampler.py +2 -2
- qiskit/primitives/containers/__init__.py +6 -4
- qiskit/primitives/containers/bit_array.py +293 -2
- qiskit/primitives/containers/data_bin.py +123 -50
- qiskit/primitives/containers/estimator_pub.py +10 -3
- qiskit/primitives/containers/observables_array.py +2 -2
- qiskit/primitives/containers/pub_result.py +1 -1
- qiskit/primitives/containers/sampler_pub.py +19 -3
- qiskit/primitives/containers/sampler_pub_result.py +74 -0
- qiskit/primitives/containers/shape.py +4 -4
- qiskit/primitives/statevector_estimator.py +4 -4
- qiskit/primitives/statevector_sampler.py +7 -12
- qiskit/providers/__init__.py +65 -34
- qiskit/providers/backend.py +2 -2
- qiskit/providers/backend_compat.py +8 -10
- qiskit/providers/basic_provider/__init__.py +2 -23
- qiskit/providers/basic_provider/basic_provider_tools.py +67 -31
- qiskit/providers/basic_provider/basic_simulator.py +81 -21
- qiskit/providers/fake_provider/__init__.py +1 -1
- qiskit/providers/fake_provider/fake_1q.py +1 -1
- qiskit/providers/fake_provider/fake_backend.py +3 -408
- qiskit/providers/fake_provider/generic_backend_v2.py +26 -14
- qiskit/providers/models/__init__.py +2 -2
- qiskit/providers/provider.py +16 -0
- qiskit/pulse/builder.py +4 -1
- qiskit/pulse/parameter_manager.py +60 -4
- qiskit/pulse/schedule.py +29 -13
- qiskit/pulse/utils.py +61 -20
- qiskit/qasm2/__init__.py +1 -5
- qiskit/qasm2/parse.py +1 -4
- qiskit/qasm3/__init__.py +42 -5
- qiskit/qasm3/ast.py +19 -0
- qiskit/qasm3/exporter.py +178 -106
- qiskit/qasm3/printer.py +27 -5
- qiskit/qobj/converters/pulse_instruction.py +6 -6
- qiskit/qpy/__init__.py +299 -67
- qiskit/qpy/binary_io/circuits.py +216 -47
- qiskit/qpy/binary_io/schedules.py +42 -36
- qiskit/qpy/binary_io/value.py +201 -22
- qiskit/qpy/common.py +1 -1
- qiskit/qpy/exceptions.py +20 -0
- qiskit/qpy/formats.py +29 -0
- qiskit/qpy/type_keys.py +21 -0
- qiskit/quantum_info/analysis/distance.py +3 -3
- qiskit/quantum_info/analysis/make_observable.py +2 -1
- qiskit/quantum_info/analysis/z2_symmetries.py +2 -1
- qiskit/quantum_info/operators/channel/chi.py +9 -8
- qiskit/quantum_info/operators/channel/choi.py +10 -9
- qiskit/quantum_info/operators/channel/kraus.py +2 -1
- qiskit/quantum_info/operators/channel/ptm.py +10 -9
- qiskit/quantum_info/operators/channel/quantum_channel.py +2 -1
- qiskit/quantum_info/operators/channel/stinespring.py +2 -1
- qiskit/quantum_info/operators/channel/superop.py +12 -11
- qiskit/quantum_info/operators/channel/transformations.py +12 -11
- qiskit/quantum_info/operators/dihedral/dihedral.py +5 -4
- qiskit/quantum_info/operators/operator.py +43 -30
- qiskit/quantum_info/operators/scalar_op.py +10 -9
- qiskit/quantum_info/operators/symplectic/base_pauli.py +70 -59
- qiskit/quantum_info/operators/symplectic/clifford.py +36 -9
- qiskit/quantum_info/operators/symplectic/pauli.py +53 -6
- qiskit/quantum_info/operators/symplectic/pauli_list.py +36 -14
- qiskit/quantum_info/operators/symplectic/random.py +3 -2
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +61 -36
- qiskit/quantum_info/states/densitymatrix.py +13 -13
- qiskit/quantum_info/states/stabilizerstate.py +3 -3
- qiskit/quantum_info/states/statevector.py +14 -13
- qiskit/quantum_info/states/utils.py +5 -3
- qiskit/result/__init__.py +6 -0
- qiskit/result/mitigation/correlated_readout_mitigator.py +3 -2
- qiskit/result/mitigation/local_readout_mitigator.py +2 -1
- qiskit/result/mitigation/utils.py +3 -2
- qiskit/scheduler/__init__.py +10 -1
- qiskit/scheduler/methods/__init__.py +1 -8
- qiskit/synthesis/__init__.py +3 -6
- qiskit/synthesis/discrete_basis/commutator_decompose.py +2 -2
- qiskit/synthesis/evolution/lie_trotter.py +7 -14
- qiskit/synthesis/evolution/qdrift.py +3 -4
- qiskit/synthesis/linear/cnot_synth.py +1 -3
- qiskit/synthesis/linear/linear_circuits_utils.py +1 -1
- qiskit/synthesis/linear_phase/cz_depth_lnn.py +4 -18
- qiskit/synthesis/permutation/__init__.py +1 -0
- qiskit/synthesis/permutation/permutation_reverse_lnn.py +90 -0
- qiskit/synthesis/qft/qft_decompose_lnn.py +2 -6
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +165 -954
- qiskit/synthesis/two_qubit/xx_decompose/circuits.py +13 -12
- qiskit/synthesis/two_qubit/xx_decompose/decomposer.py +7 -1
- qiskit/synthesis/unitary/aqc/__init__.py +1 -1
- qiskit/synthesis/unitary/aqc/cnot_structures.py +2 -1
- qiskit/synthesis/unitary/aqc/fast_gradient/fast_gradient.py +2 -1
- qiskit/synthesis/unitary/qsd.py +3 -2
- qiskit/transpiler/__init__.py +7 -3
- qiskit/transpiler/layout.py +140 -61
- qiskit/transpiler/passes/__init__.py +10 -2
- qiskit/transpiler/passes/basis/basis_translator.py +9 -4
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
- qiskit/transpiler/passes/calibration/rzx_builder.py +2 -1
- qiskit/transpiler/passes/layout/apply_layout.py +8 -3
- qiskit/transpiler/passes/layout/sabre_layout.py +15 -3
- qiskit/transpiler/passes/layout/set_layout.py +1 -1
- qiskit/transpiler/passes/optimization/__init__.py +2 -0
- qiskit/transpiler/passes/optimization/commutation_analysis.py +2 -2
- qiskit/transpiler/passes/optimization/commutative_cancellation.py +1 -1
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +1 -1
- qiskit/transpiler/passes/optimization/cx_cancellation.py +10 -0
- qiskit/transpiler/passes/optimization/elide_permutations.py +114 -0
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +9 -3
- qiskit/transpiler/passes/optimization/optimize_annotated.py +248 -12
- qiskit/transpiler/passes/optimization/remove_final_reset.py +37 -0
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +1 -3
- qiskit/transpiler/passes/routing/__init__.py +1 -0
- qiskit/transpiler/passes/routing/basic_swap.py +13 -2
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +8 -1
- qiskit/transpiler/passes/routing/lookahead_swap.py +7 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +10 -6
- qiskit/transpiler/passes/routing/star_prerouting.py +417 -0
- qiskit/transpiler/passes/routing/stochastic_swap.py +24 -8
- qiskit/transpiler/passes/scheduling/__init__.py +1 -1
- qiskit/transpiler/passes/scheduling/alap.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/align_measures.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +9 -6
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +8 -0
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +13 -4
- qiskit/transpiler/passes/scheduling/asap.py +1 -2
- qiskit/transpiler/passes/scheduling/base_scheduler.py +21 -2
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +26 -4
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +24 -2
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +28 -4
- qiskit/transpiler/passes/synthesis/aqc_plugin.py +2 -2
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +120 -13
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +162 -55
- qiskit/transpiler/passes/utils/gates_basis.py +3 -3
- qiskit/transpiler/passmanager.py +44 -1
- qiskit/transpiler/preset_passmanagers/__init__.py +3 -3
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +34 -16
- qiskit/transpiler/preset_passmanagers/common.py +4 -6
- qiskit/transpiler/preset_passmanagers/plugin.py +9 -1
- qiskit/utils/__init__.py +3 -2
- qiskit/utils/optionals.py +6 -2
- qiskit/utils/parallel.py +24 -15
- qiskit/visualization/array.py +1 -1
- qiskit/visualization/bloch.py +2 -3
- qiskit/visualization/circuit/matplotlib.py +44 -14
- qiskit/visualization/circuit/text.py +38 -18
- qiskit/visualization/counts_visualization.py +3 -6
- qiskit/visualization/dag_visualization.py +6 -7
- qiskit/visualization/gate_map.py +9 -1
- qiskit/visualization/pulse_v2/interface.py +8 -3
- qiskit/visualization/state_visualization.py +3 -2
- qiskit/visualization/timeline/interface.py +18 -8
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/METADATA +12 -8
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/RECORD +261 -251
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/WHEEL +1 -1
- qiskit/_qasm2.pyd +0 -0
- qiskit/_qasm3.pyd +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/entry_points.txt +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/top_level.txt +0 -0
@@ -16,7 +16,6 @@ N-Qubit Sparse Pauli Operator class.
|
|
16
16
|
from __future__ import annotations
|
17
17
|
from typing import TYPE_CHECKING, List
|
18
18
|
|
19
|
-
from collections import defaultdict
|
20
19
|
from collections.abc import Mapping, Sequence, Iterable
|
21
20
|
from numbers import Number
|
22
21
|
from copy import deepcopy
|
@@ -24,7 +23,13 @@ from copy import deepcopy
|
|
24
23
|
import numpy as np
|
25
24
|
import rustworkx as rx
|
26
25
|
|
27
|
-
from qiskit._accelerate.sparse_pauli_op import
|
26
|
+
from qiskit._accelerate.sparse_pauli_op import (
|
27
|
+
ZXPaulis,
|
28
|
+
decompose_dense,
|
29
|
+
to_matrix_dense,
|
30
|
+
to_matrix_sparse,
|
31
|
+
unordered_unique,
|
32
|
+
)
|
28
33
|
from qiskit.circuit.parameter import Parameter
|
29
34
|
from qiskit.circuit.parameterexpression import ParameterExpression
|
30
35
|
from qiskit.circuit.parametertable import ParameterView
|
@@ -143,7 +148,12 @@ class SparsePauliOp(LinearOp):
|
|
143
148
|
if coeffs is None:
|
144
149
|
coeffs = np.ones(pauli_list.size, dtype=complex)
|
145
150
|
else:
|
146
|
-
|
151
|
+
coeffs_asarray = np.asarray(coeffs, dtype=dtype)
|
152
|
+
coeffs = (
|
153
|
+
coeffs_asarray.copy()
|
154
|
+
if copy and np.may_share_memory(coeffs, coeffs_asarray)
|
155
|
+
else coeffs_asarray
|
156
|
+
)
|
147
157
|
|
148
158
|
if ignore_pauli_phase:
|
149
159
|
# Fast path used in copy operations, where the phase of the PauliList is already known
|
@@ -167,10 +177,11 @@ class SparsePauliOp(LinearOp):
|
|
167
177
|
# Initialize LinearOp
|
168
178
|
super().__init__(num_qubits=self._pauli_list.num_qubits)
|
169
179
|
|
170
|
-
def __array__(self, dtype=None):
|
171
|
-
if
|
172
|
-
|
173
|
-
|
180
|
+
def __array__(self, dtype=None, copy=None):
|
181
|
+
if copy is False:
|
182
|
+
raise ValueError("unable to avoid copy while creating an array as requested")
|
183
|
+
arr = self.to_matrix()
|
184
|
+
return arr if dtype is None else arr.astype(dtype, copy=False)
|
174
185
|
|
175
186
|
def __repr__(self):
|
176
187
|
prefix = "SparsePauliOp("
|
@@ -920,24 +931,39 @@ class SparsePauliOp(LinearOp):
|
|
920
931
|
return labels
|
921
932
|
return labels.tolist()
|
922
933
|
|
923
|
-
def to_matrix(self, sparse: bool = False) -> np.ndarray:
|
934
|
+
def to_matrix(self, sparse: bool = False, force_serial: bool = False) -> np.ndarray:
|
924
935
|
"""Convert to a dense or sparse matrix.
|
925
936
|
|
926
937
|
Args:
|
927
|
-
sparse
|
928
|
-
|
938
|
+
sparse: if ``True`` return a sparse CSR matrix, otherwise return dense Numpy
|
939
|
+
array (the default).
|
940
|
+
force_serial: if ``True``, use an unthreaded implementation, regardless of the state of
|
941
|
+
the `Qiskit threading-control environment variables
|
942
|
+
<https://docs.quantum.ibm.com/start/configure-qiskit-local#environment-variables>`__.
|
943
|
+
By default, this will use threaded parallelism over the available CPUs.
|
929
944
|
|
930
945
|
Returns:
|
931
946
|
array: A dense matrix if `sparse=False`.
|
932
947
|
csr_matrix: A sparse matrix in CSR format if `sparse=True`.
|
933
948
|
"""
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
949
|
+
if self.coeffs.dtype == object:
|
950
|
+
# Fallback to slow Python-space method.
|
951
|
+
return sum(self.matrix_iter(sparse=sparse))
|
952
|
+
|
953
|
+
pauli_list = self.paulis
|
954
|
+
zx = ZXPaulis(
|
955
|
+
pauli_list.x.astype(np.bool_),
|
956
|
+
pauli_list.z.astype(np.bool_),
|
957
|
+
pauli_list.phase.astype(np.uint8),
|
958
|
+
self.coeffs.astype(np.complex128),
|
959
|
+
)
|
960
|
+
if sparse:
|
961
|
+
from scipy.sparse import csr_matrix
|
962
|
+
|
963
|
+
data, indices, indptr = to_matrix_sparse(zx, force_serial=force_serial)
|
964
|
+
side = 1 << self.num_qubits
|
965
|
+
return csr_matrix((data, indices, indptr), shape=(side, side))
|
966
|
+
return to_matrix_dense(zx, force_serial=force_serial)
|
941
967
|
|
942
968
|
def to_operator(self) -> Operator:
|
943
969
|
"""Convert to a matrix Operator object"""
|
@@ -1000,22 +1026,23 @@ class SparsePauliOp(LinearOp):
|
|
1000
1026
|
|
1001
1027
|
return MatrixIterator(self)
|
1002
1028
|
|
1003
|
-
def
|
1004
|
-
"""
|
1029
|
+
def noncommutation_graph(self, qubit_wise: bool) -> rx.PyGraph:
|
1030
|
+
"""Create the non-commutation graph of this SparsePauliOp.
|
1031
|
+
|
1032
|
+
This transforms the measurement operator grouping problem into graph coloring problem. The
|
1033
|
+
constructed graph contains one node for each Pauli. The nodes will be connecting for any two
|
1034
|
+
Pauli terms that do _not_ commute.
|
1005
1035
|
|
1006
1036
|
Args:
|
1007
1037
|
qubit_wise (bool): whether the commutation rule is applied to the whole operator,
|
1008
1038
|
or on a per-qubit basis.
|
1009
1039
|
|
1010
1040
|
Returns:
|
1011
|
-
rustworkx.PyGraph:
|
1041
|
+
rustworkx.PyGraph: the non-commutation graph with nodes for each Pauli and edges
|
1042
|
+
indicating a non-commutation relation. Each node will hold the index of the Pauli
|
1043
|
+
term it corresponds to in its data. The edges of the graph hold no data.
|
1012
1044
|
"""
|
1013
|
-
|
1014
|
-
edges = self.paulis._noncommutation_graph(qubit_wise)
|
1015
|
-
graph = rx.PyGraph()
|
1016
|
-
graph.add_nodes_from(range(self.size))
|
1017
|
-
graph.add_edges_from_no_data(edges)
|
1018
|
-
return graph
|
1045
|
+
return self.paulis.noncommutation_graph(qubit_wise)
|
1019
1046
|
|
1020
1047
|
def group_commuting(self, qubit_wise: bool = False) -> list[SparsePauliOp]:
|
1021
1048
|
"""Partition a SparsePauliOp into sets of commuting Pauli strings.
|
@@ -1039,13 +1066,7 @@ class SparsePauliOp(LinearOp):
|
|
1039
1066
|
list[SparsePauliOp]: List of SparsePauliOp where each SparsePauliOp contains
|
1040
1067
|
commuting Pauli operators.
|
1041
1068
|
"""
|
1042
|
-
|
1043
|
-
graph = self._create_graph(qubit_wise)
|
1044
|
-
# Keys in coloring_dict are nodes, values are colors
|
1045
|
-
coloring_dict = rx.graph_greedy_color(graph)
|
1046
|
-
groups = defaultdict(list)
|
1047
|
-
for idx, color in coloring_dict.items():
|
1048
|
-
groups[color].append(idx)
|
1069
|
+
groups = self.paulis._commuting_groups(qubit_wise)
|
1049
1070
|
return [self[group] for group in groups.values()]
|
1050
1071
|
|
1051
1072
|
@property
|
@@ -1118,7 +1139,6 @@ class SparsePauliOp(LinearOp):
|
|
1118
1139
|
specified will be applied without any expansion. If layout is
|
1119
1140
|
None, the operator will be expanded to the given number of qubits.
|
1120
1141
|
|
1121
|
-
|
1122
1142
|
Returns:
|
1123
1143
|
A new :class:`.SparsePauliOp` with the provided layout applied
|
1124
1144
|
"""
|
@@ -1138,10 +1158,15 @@ class SparsePauliOp(LinearOp):
|
|
1138
1158
|
f"applied to a {n_qubits} qubit operator"
|
1139
1159
|
)
|
1140
1160
|
n_qubits = num_qubits
|
1141
|
-
if layout is not None and any(x >= n_qubits for x in layout):
|
1142
|
-
raise QiskitError("Provided layout contains indices outside the number of qubits.")
|
1143
1161
|
if layout is None:
|
1144
1162
|
layout = list(range(self.num_qubits))
|
1163
|
+
else:
|
1164
|
+
if any(x < 0 or x >= n_qubits for x in layout):
|
1165
|
+
raise QiskitError("Provided layout contains indices outside the number of qubits.")
|
1166
|
+
if len(set(layout)) != len(layout):
|
1167
|
+
raise QiskitError("Provided layout contains duplicate indices.")
|
1168
|
+
if self.num_qubits == 0:
|
1169
|
+
return type(self)(["I" * n_qubits] * self.size, self.coeffs)
|
1145
1170
|
new_op = type(self)("I" * n_qubits)
|
1146
1171
|
return new_op.compose(self, qargs=layout)
|
1147
1172
|
|
@@ -15,10 +15,11 @@ DensityMatrix quantum state class.
|
|
15
15
|
"""
|
16
16
|
|
17
17
|
from __future__ import annotations
|
18
|
-
import copy
|
18
|
+
import copy as _copy
|
19
19
|
from numbers import Number
|
20
20
|
import numpy as np
|
21
21
|
|
22
|
+
from qiskit import _numpy_compat
|
22
23
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
23
24
|
from qiskit.circuit.instruction import Instruction
|
24
25
|
from qiskit.exceptions import QiskitError
|
@@ -110,10 +111,9 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
110
111
|
raise QiskitError("Invalid DensityMatrix input: not a square matrix.")
|
111
112
|
super().__init__(op_shape=OpShape.auto(shape=self._data.shape, dims_l=dims, dims_r=dims))
|
112
113
|
|
113
|
-
def __array__(self, dtype=None):
|
114
|
-
if dtype
|
115
|
-
|
116
|
-
return self.data
|
114
|
+
def __array__(self, dtype=None, copy=_numpy_compat.COPY_ONLY_IF_NEEDED):
|
115
|
+
dtype = self.data.dtype if dtype is None else dtype
|
116
|
+
return np.array(self.data, dtype=dtype, copy=copy)
|
117
117
|
|
118
118
|
def __eq__(self, other):
|
119
119
|
return super().__eq__(other) and np.allclose(
|
@@ -241,7 +241,7 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
241
241
|
"""
|
242
242
|
if not isinstance(other, DensityMatrix):
|
243
243
|
other = DensityMatrix(other)
|
244
|
-
ret =
|
244
|
+
ret = _copy.copy(self)
|
245
245
|
ret._data = np.kron(self._data, other._data)
|
246
246
|
ret._op_shape = self._op_shape.tensor(other._op_shape)
|
247
247
|
return ret
|
@@ -260,7 +260,7 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
260
260
|
"""
|
261
261
|
if not isinstance(other, DensityMatrix):
|
262
262
|
other = DensityMatrix(other)
|
263
|
-
ret =
|
263
|
+
ret = _copy.copy(self)
|
264
264
|
ret._data = np.kron(other._data, self._data)
|
265
265
|
ret._op_shape = self._op_shape.expand(other._op_shape)
|
266
266
|
return ret
|
@@ -281,7 +281,7 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
281
281
|
if not isinstance(other, DensityMatrix):
|
282
282
|
other = DensityMatrix(other)
|
283
283
|
self._op_shape._validate_add(other._op_shape)
|
284
|
-
ret =
|
284
|
+
ret = _copy.copy(self)
|
285
285
|
ret._data = self.data + other.data
|
286
286
|
return ret
|
287
287
|
|
@@ -299,7 +299,7 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
299
299
|
"""
|
300
300
|
if not isinstance(other, Number):
|
301
301
|
raise QiskitError("other is not a number")
|
302
|
-
ret =
|
302
|
+
ret = _copy.copy(self)
|
303
303
|
ret._data = other * self.data
|
304
304
|
return ret
|
305
305
|
|
@@ -356,7 +356,7 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
356
356
|
Returns:
|
357
357
|
DensityMatrix: the state with reversed subsystem order.
|
358
358
|
"""
|
359
|
-
ret =
|
359
|
+
ret = _copy.copy(self)
|
360
360
|
axes = tuple(range(self._op_shape._num_qargs_l - 1, -1, -1))
|
361
361
|
axes = axes + tuple(len(axes) + i for i in axes)
|
362
362
|
ret._data = np.reshape(
|
@@ -523,7 +523,7 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
523
523
|
"""
|
524
524
|
if qargs is None:
|
525
525
|
# Resetting all qubits does not require sampling or RNG
|
526
|
-
ret =
|
526
|
+
ret = _copy.copy(self)
|
527
527
|
state = np.zeros(self._op_shape.shape, dtype=complex)
|
528
528
|
state[0, 0] = 1
|
529
529
|
ret._data = state
|
@@ -715,7 +715,7 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
715
715
|
new_shape._dims_r = new_shape._dims_l
|
716
716
|
new_shape._num_qargs_r = new_shape._num_qargs_l
|
717
717
|
|
718
|
-
ret =
|
718
|
+
ret = _copy.copy(self)
|
719
719
|
if qargs is None:
|
720
720
|
# Evolution on full matrix
|
721
721
|
op_mat = other.data
|
@@ -792,7 +792,7 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
792
792
|
"""Return a new statevector by applying an instruction."""
|
793
793
|
if isinstance(obj, QuantumCircuit):
|
794
794
|
obj = obj.to_instruction()
|
795
|
-
vec =
|
795
|
+
vec = _copy.copy(self)
|
796
796
|
vec._append_instruction(obj, qargs=qargs)
|
797
797
|
return vec
|
798
798
|
|
@@ -415,7 +415,7 @@ class StabilizerState(QuantumState):
|
|
415
415
|
outcome_prob = 1.0
|
416
416
|
probs = {} # probabilities dictionary
|
417
417
|
|
418
|
-
self.
|
418
|
+
self._get_probabilities(qubits, outcome, outcome_prob, probs)
|
419
419
|
|
420
420
|
if decimals is not None:
|
421
421
|
for key, value in probs.items():
|
@@ -644,7 +644,7 @@ class StabilizerState(QuantumState):
|
|
644
644
|
# -----------------------------------------------------------------------
|
645
645
|
# Helper functions for calculating the probabilities
|
646
646
|
# -----------------------------------------------------------------------
|
647
|
-
def
|
647
|
+
def _get_probabilities(self, qubits, outcome, outcome_prob, probs):
|
648
648
|
"""Recursive helper function for calculating the probabilities"""
|
649
649
|
|
650
650
|
qubit_for_branching = -1
|
@@ -679,4 +679,4 @@ class StabilizerState(QuantumState):
|
|
679
679
|
stab_cpy._measure_and_update(
|
680
680
|
qubits[len(qubits) - qubit_for_branching - 1], single_qubit_outcome
|
681
681
|
)
|
682
|
-
stab_cpy.
|
682
|
+
stab_cpy._get_probabilities(qubits, new_outcome, 0.5 * outcome_prob, probs)
|
@@ -14,12 +14,14 @@
|
|
14
14
|
Statevector quantum state class.
|
15
15
|
"""
|
16
16
|
from __future__ import annotations
|
17
|
-
import copy
|
17
|
+
import copy as _copy
|
18
|
+
import math
|
18
19
|
import re
|
19
20
|
from numbers import Number
|
20
21
|
|
21
22
|
import numpy as np
|
22
23
|
|
24
|
+
from qiskit import _numpy_compat
|
23
25
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
24
26
|
from qiskit.circuit.instruction import Instruction
|
25
27
|
from qiskit.exceptions import QiskitError
|
@@ -103,10 +105,9 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
103
105
|
raise QiskitError("Invalid input: not a vector or column-vector.")
|
104
106
|
super().__init__(op_shape=OpShape.auto(shape=shape, dims_l=dims, num_qubits_r=0))
|
105
107
|
|
106
|
-
def __array__(self, dtype=None):
|
107
|
-
if dtype
|
108
|
-
|
109
|
-
return self.data
|
108
|
+
def __array__(self, dtype=None, copy=_numpy_compat.COPY_ONLY_IF_NEEDED):
|
109
|
+
dtype = self.data.dtype if dtype is None else dtype
|
110
|
+
return np.array(self.data, dtype=dtype, copy=copy)
|
110
111
|
|
111
112
|
def __eq__(self, other):
|
112
113
|
return super().__eq__(other) and np.allclose(
|
@@ -276,7 +277,7 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
276
277
|
"""
|
277
278
|
if not isinstance(other, Statevector):
|
278
279
|
other = Statevector(other)
|
279
|
-
ret =
|
280
|
+
ret = _copy.copy(self)
|
280
281
|
ret._op_shape = self._op_shape.tensor(other._op_shape)
|
281
282
|
ret._data = np.kron(self._data, other._data)
|
282
283
|
return ret
|
@@ -317,7 +318,7 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
317
318
|
"""
|
318
319
|
if not isinstance(other, Statevector):
|
319
320
|
other = Statevector(other)
|
320
|
-
ret =
|
321
|
+
ret = _copy.copy(self)
|
321
322
|
ret._op_shape = self._op_shape.expand(other._op_shape)
|
322
323
|
ret._data = np.kron(other._data, self._data)
|
323
324
|
return ret
|
@@ -338,7 +339,7 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
338
339
|
if not isinstance(other, Statevector):
|
339
340
|
other = Statevector(other)
|
340
341
|
self._op_shape._validate_add(other._op_shape)
|
341
|
-
ret =
|
342
|
+
ret = _copy.copy(self)
|
342
343
|
ret._data = self.data + other.data
|
343
344
|
return ret
|
344
345
|
|
@@ -356,7 +357,7 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
356
357
|
"""
|
357
358
|
if not isinstance(other, Number):
|
358
359
|
raise QiskitError("other is not a number")
|
359
|
-
ret =
|
360
|
+
ret = _copy.copy(self)
|
360
361
|
ret._data = other * self.data
|
361
362
|
return ret
|
362
363
|
|
@@ -381,7 +382,7 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
381
382
|
qargs = getattr(other, "qargs", None)
|
382
383
|
|
383
384
|
# Get return vector
|
384
|
-
ret =
|
385
|
+
ret = _copy.copy(self)
|
385
386
|
|
386
387
|
# Evolution by a circuit or instruction
|
387
388
|
if isinstance(other, QuantumCircuit):
|
@@ -447,7 +448,7 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
447
448
|
Returns:
|
448
449
|
Statevector: the Statevector with reversed subsystem order.
|
449
450
|
"""
|
450
|
-
ret =
|
451
|
+
ret = _copy.copy(self)
|
451
452
|
axes = tuple(range(self._op_shape._num_qargs_l - 1, -1, -1))
|
452
453
|
ret._data = np.reshape(
|
453
454
|
np.transpose(np.reshape(self.data, self._op_shape.tensor_shape), axes),
|
@@ -618,7 +619,7 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
618
619
|
"""
|
619
620
|
if qargs is None:
|
620
621
|
# Resetting all qubits does not require sampling or RNG
|
621
|
-
ret =
|
622
|
+
ret = _copy.copy(self)
|
622
623
|
state = np.zeros(self._op_shape.shape, dtype=complex)
|
623
624
|
state[0] = 1
|
624
625
|
ret._data = state
|
@@ -702,7 +703,7 @@ class Statevector(QuantumState, TolerancesMixin):
|
|
702
703
|
state = Statevector(data)
|
703
704
|
if xy_states:
|
704
705
|
# Apply hadamards to all qubits in X eigenstates
|
705
|
-
x_mat = np.array([[1, 1], [1, -1]], dtype=complex) /
|
706
|
+
x_mat = np.array([[1, 1], [1, -1]], dtype=complex) / math.sqrt(2)
|
706
707
|
# Apply S.H to qubits in Y eigenstates
|
707
708
|
y_mat = np.dot(np.diag([1, 1j]), x_mat)
|
708
709
|
for qubit, char in enumerate(reversed(label)):
|
@@ -15,6 +15,7 @@ Quantum information utility functions for states.
|
|
15
15
|
"""
|
16
16
|
|
17
17
|
from __future__ import annotations
|
18
|
+
import math
|
18
19
|
|
19
20
|
import numpy as np
|
20
21
|
|
@@ -102,17 +103,18 @@ def shannon_entropy(pvec: list | np.ndarray, base: int = 2) -> float:
|
|
102
103
|
if base == 2:
|
103
104
|
|
104
105
|
def logfn(x):
|
105
|
-
return -x *
|
106
|
+
return -x * math.log2(x)
|
106
107
|
|
107
108
|
elif base == np.e:
|
108
109
|
|
109
110
|
def logfn(x):
|
110
|
-
return -x *
|
111
|
+
return -x * math.log(x)
|
111
112
|
|
112
113
|
else:
|
114
|
+
log_base = math.log(base)
|
113
115
|
|
114
116
|
def logfn(x):
|
115
|
-
return -x *
|
117
|
+
return -x * math.log(x) / log_base
|
116
118
|
|
117
119
|
h_val = 0.0
|
118
120
|
for x in pvec:
|
qiskit/result/__init__.py
CHANGED
@@ -17,6 +17,9 @@ Experiment Results (:mod:`qiskit.result`)
|
|
17
17
|
|
18
18
|
.. currentmodule:: qiskit.result
|
19
19
|
|
20
|
+
Core classes
|
21
|
+
============
|
22
|
+
|
20
23
|
.. autosummary::
|
21
24
|
:toctree: ../stubs/
|
22
25
|
|
@@ -24,6 +27,9 @@ Experiment Results (:mod:`qiskit.result`)
|
|
24
27
|
ResultError
|
25
28
|
Counts
|
26
29
|
|
30
|
+
Marginalization
|
31
|
+
===============
|
32
|
+
|
27
33
|
.. autofunction:: marginal_counts
|
28
34
|
.. autofunction:: marginal_distribution
|
29
35
|
.. autofunction:: marginal_memory
|
@@ -13,6 +13,7 @@
|
|
13
13
|
Readout mitigator class based on the A-matrix inversion method
|
14
14
|
"""
|
15
15
|
|
16
|
+
import math
|
16
17
|
from typing import Optional, List, Tuple, Iterable, Callable, Union, Dict
|
17
18
|
import numpy as np
|
18
19
|
|
@@ -46,7 +47,7 @@ class CorrelatedReadoutMitigator(BaseReadoutMitigator):
|
|
46
47
|
if np.any(assignment_matrix < 0) or not np.allclose(np.sum(assignment_matrix, axis=0), 1):
|
47
48
|
raise QiskitError("Assignment matrix columns must be valid probability distributions")
|
48
49
|
assignment_matrix = np.asarray(assignment_matrix, dtype=float)
|
49
|
-
matrix_qubits_num = int(
|
50
|
+
matrix_qubits_num = int(math.log2(assignment_matrix.shape[0]))
|
50
51
|
if qubits is None:
|
51
52
|
self._num_qubits = matrix_qubits_num
|
52
53
|
self._qubits = range(self._num_qubits)
|
@@ -260,7 +261,7 @@ class CorrelatedReadoutMitigator(BaseReadoutMitigator):
|
|
260
261
|
float: the standard deviation upper bound.
|
261
262
|
"""
|
262
263
|
gamma = self._compute_gamma()
|
263
|
-
return gamma /
|
264
|
+
return gamma / math.sqrt(shots)
|
264
265
|
|
265
266
|
@property
|
266
267
|
def qubits(self) -> Tuple[int]:
|
@@ -14,6 +14,7 @@ Readout mitigator class based on the 1-qubit local tensored mitigation method
|
|
14
14
|
"""
|
15
15
|
|
16
16
|
|
17
|
+
import math
|
17
18
|
from typing import Optional, List, Tuple, Iterable, Callable, Union, Dict
|
18
19
|
import numpy as np
|
19
20
|
|
@@ -288,7 +289,7 @@ class LocalReadoutMitigator(BaseReadoutMitigator):
|
|
288
289
|
float: the standard deviation upper bound.
|
289
290
|
"""
|
290
291
|
gamma = self._compute_gamma(qubits=qubits)
|
291
|
-
return gamma /
|
292
|
+
return gamma / math.sqrt(shots)
|
292
293
|
|
293
294
|
def _from_backend(self, backend, qubits):
|
294
295
|
"""Calculates amats from backend properties readout_error"""
|
@@ -14,6 +14,7 @@ Readout mitigation data handling utils
|
|
14
14
|
"""
|
15
15
|
|
16
16
|
import logging
|
17
|
+
import math
|
17
18
|
from typing import Optional, List, Tuple, Dict
|
18
19
|
import numpy as np
|
19
20
|
|
@@ -55,7 +56,7 @@ def expval_with_stddev(coeffs: np.ndarray, probs: np.ndarray, shots: int) -> Tup
|
|
55
56
|
"(%f). Setting standard deviation of result to 0.",
|
56
57
|
variance,
|
57
58
|
)
|
58
|
-
calc_stddev =
|
59
|
+
calc_stddev = math.sqrt(variance) if variance > 0 else 0.0
|
59
60
|
return [expval, calc_stddev]
|
60
61
|
|
61
62
|
|
@@ -63,7 +64,7 @@ def stddev(probs, shots):
|
|
63
64
|
"""Calculate stddev dict"""
|
64
65
|
ret = {}
|
65
66
|
for key, prob in probs.items():
|
66
|
-
std_err =
|
67
|
+
std_err = math.sqrt(prob * (1 - prob) / shots)
|
67
68
|
ret[key] = std_err
|
68
69
|
return ret
|
69
70
|
|
qiskit/scheduler/__init__.py
CHANGED
@@ -19,13 +19,22 @@ Circuit Scheduler (:mod:`qiskit.scheduler`)
|
|
19
19
|
|
20
20
|
A circuit scheduler compiles a circuit program to a pulse program.
|
21
21
|
|
22
|
+
Core API
|
23
|
+
========
|
24
|
+
|
22
25
|
.. autoclass:: ScheduleConfig
|
23
26
|
|
24
27
|
.. currentmodule:: qiskit.scheduler.schedule_circuit
|
25
28
|
.. autofunction:: schedule_circuit
|
26
29
|
.. currentmodule:: qiskit.scheduler
|
27
30
|
|
28
|
-
|
31
|
+
Pulse scheduling methods
|
32
|
+
========================
|
33
|
+
|
34
|
+
.. currentmodule:: qiskit.scheduler.methods
|
35
|
+
.. autofunction:: as_soon_as_possible
|
36
|
+
.. autofunction:: as_late_as_possible
|
37
|
+
.. currentmodule:: qiskit.scheduler
|
29
38
|
"""
|
30
39
|
from qiskit.scheduler import schedule_circuit
|
31
40
|
from qiskit.scheduler.config import ScheduleConfig
|
@@ -10,13 +10,6 @@
|
|
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
|
-
"""
|
14
|
-
.. currentmodule:: qiskit.scheduler.methods
|
15
|
-
|
16
|
-
Pulse scheduling methods.
|
17
|
-
|
18
|
-
.. autofunction:: as_soon_as_possible
|
19
|
-
.. autofunction:: as_late_as_possible
|
20
|
-
"""
|
13
|
+
"""Scheduling methods."""
|
21
14
|
|
22
15
|
from qiskit.scheduler.methods.basic import as_soon_as_possible, as_late_as_possible
|
qiskit/synthesis/__init__.py
CHANGED
@@ -51,6 +51,7 @@ Permutation Synthesis
|
|
51
51
|
.. autofunction:: synth_permutation_depth_lnn_kms
|
52
52
|
.. autofunction:: synth_permutation_basic
|
53
53
|
.. autofunction:: synth_permutation_acg
|
54
|
+
.. autofunction:: synth_permutation_reverse_lnn_kms
|
54
55
|
|
55
56
|
Clifford Synthesis
|
56
57
|
==================
|
@@ -98,12 +99,7 @@ Decomposition of general :math:`2^n \times 2^n` unitary matrices for any number
|
|
98
99
|
|
99
100
|
.. autofunction:: qs_decomposition
|
100
101
|
|
101
|
-
The Approximate Quantum Compiler is available
|
102
|
-
|
103
|
-
.. autosummary::
|
104
|
-
:toctree: ../stubs/
|
105
|
-
|
106
|
-
qiskit.synthesis.unitary.aqc
|
102
|
+
The Approximate Quantum Compiler is available as the module :mod:`qiskit.synthesis.unitary.aqc`.
|
107
103
|
|
108
104
|
One-Qubit Synthesis
|
109
105
|
===================
|
@@ -140,6 +136,7 @@ from .permutation import (
|
|
140
136
|
synth_permutation_depth_lnn_kms,
|
141
137
|
synth_permutation_basic,
|
142
138
|
synth_permutation_acg,
|
139
|
+
synth_permutation_reverse_lnn_kms,
|
143
140
|
)
|
144
141
|
from .linear import (
|
145
142
|
synth_cnot_count_full_pmh,
|
@@ -92,8 +92,8 @@ def _solve_decomposition_angle(matrix: np.ndarray) -> float:
|
|
92
92
|
lhs = math.sin(angle / 2)
|
93
93
|
|
94
94
|
def objective(phi):
|
95
|
-
sin_sq =
|
96
|
-
return 2 * sin_sq *
|
95
|
+
sin_sq = math.sin(phi.item() / 2) ** 2
|
96
|
+
return 2 * sin_sq * math.sqrt(1 - sin_sq**2) - lhs
|
97
97
|
|
98
98
|
decomposition_angle = fsolve(objective, angle)[0]
|
99
99
|
return decomposition_angle
|
@@ -76,7 +76,6 @@ class LieTrotter(ProductFormula):
|
|
76
76
|
|
77
77
|
# construct the evolution circuit
|
78
78
|
evolution_circuit = QuantumCircuit(operators[0].num_qubits)
|
79
|
-
first_barrier = False
|
80
79
|
|
81
80
|
if not isinstance(operators, list):
|
82
81
|
pauli_list = [(Pauli(op), np.real(coeff)) for op, coeff in operators.to_list()]
|
@@ -86,20 +85,14 @@ class LieTrotter(ProductFormula):
|
|
86
85
|
# if we only evolve a single Pauli we don't need to additionally wrap it
|
87
86
|
wrap = not (len(pauli_list) == 1 and self.reps == 1)
|
88
87
|
|
89
|
-
for
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
else:
|
96
|
-
first_barrier = True
|
97
|
-
|
98
|
-
evolution_circuit.compose(
|
99
|
-
self.atomic_evolution(op, coeff * time / self.reps), wrap=wrap, inplace=True
|
100
|
-
)
|
88
|
+
for i, (op, coeff) in enumerate(pauli_list):
|
89
|
+
evolution_circuit.compose(
|
90
|
+
self.atomic_evolution(op, coeff * time / self.reps), wrap=wrap, inplace=True
|
91
|
+
)
|
92
|
+
if self.insert_barriers and i != len(pauli_list) - 1:
|
93
|
+
evolution_circuit.barrier()
|
101
94
|
|
102
|
-
return evolution_circuit
|
95
|
+
return evolution_circuit.repeat(self.reps).decompose()
|
103
96
|
|
104
97
|
@property
|
105
98
|
def settings(self) -> Dict[str, Any]:
|
@@ -12,6 +12,7 @@
|
|
12
12
|
|
13
13
|
"""QDrift Class"""
|
14
14
|
|
15
|
+
import math
|
15
16
|
from typing import Union, Optional, Callable
|
16
17
|
import numpy as np
|
17
18
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
@@ -73,7 +74,7 @@ class QDrift(ProductFormula):
|
|
73
74
|
weights = np.abs(coeffs)
|
74
75
|
lambd = np.sum(weights)
|
75
76
|
|
76
|
-
num_gates =
|
77
|
+
num_gates = math.ceil(2 * (lambd**2) * (time**2) * self.reps)
|
77
78
|
# The protocol calls for the removal of the individual coefficients,
|
78
79
|
# and multiplication by a constant evolution time.
|
79
80
|
evolution_time = lambd * time / num_gates
|
@@ -83,8 +84,6 @@ class QDrift(ProductFormula):
|
|
83
84
|
size=(num_gates,),
|
84
85
|
p=weights / lambd,
|
85
86
|
)
|
86
|
-
# Update the coefficients of sampled_ops
|
87
|
-
self.sampled_ops = [(op, evolution_time) for op, coeff in self.sampled_ops]
|
88
87
|
|
89
88
|
# pylint: disable=cyclic-import
|
90
89
|
from qiskit.circuit.library.pauli_evolution import PauliEvolutionGate
|
@@ -94,7 +93,7 @@ class QDrift(ProductFormula):
|
|
94
93
|
insert_barriers=self.insert_barriers, atomic_evolution=self.atomic_evolution
|
95
94
|
)
|
96
95
|
evolution_circuit = PauliEvolutionGate(
|
97
|
-
sum(SparsePauliOp(op) for op, coeff in self.sampled_ops),
|
96
|
+
sum(SparsePauliOp(np.sign(coeff) * op) for op, coeff in self.sampled_ops),
|
98
97
|
time=evolution_time,
|
99
98
|
synthesis=lie_trotter,
|
100
99
|
).definition
|