qiskit 1.3.0rc2__cp39-abi3-win32.whl → 1.3.1__cp39-abi3-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qiskit/VERSION.txt +1 -1
- qiskit/_accelerate.pyd +0 -0
- qiskit/circuit/add_control.py +110 -92
- qiskit/circuit/library/arithmetic/adders/adder.py +25 -0
- qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +1 -1
- qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +1 -1
- qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +1 -1
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +9 -0
- qiskit/qpy/__init__.py +5 -5
- qiskit/quantum_info/operators/channel/chi.py +9 -9
- qiskit/quantum_info/operators/channel/choi.py +9 -9
- qiskit/quantum_info/operators/channel/ptm.py +9 -9
- qiskit/quantum_info/operators/channel/quantum_channel.py +3 -3
- qiskit/quantum_info/operators/channel/stinespring.py +9 -9
- qiskit/quantum_info/operators/channel/superop.py +5 -9
- qiskit/quantum_info/states/densitymatrix.py +17 -15
- qiskit/quantum_info/states/stabilizerstate.py +7 -6
- qiskit/quantum_info/states/statevector.py +14 -6
- qiskit/transpiler/passes/basis/decompose.py +24 -4
- qiskit/transpiler/passes/optimization/inverse_cancellation.py +2 -0
- qiskit/transpiler/passes/synthesis/hls_plugins.py +89 -21
- {qiskit-1.3.0rc2.dist-info → qiskit-1.3.1.dist-info}/METADATA +12 -12
- {qiskit-1.3.0rc2.dist-info → qiskit-1.3.1.dist-info}/RECORD +27 -27
- {qiskit-1.3.0rc2.dist-info → qiskit-1.3.1.dist-info}/entry_points.txt +1 -1
- {qiskit-1.3.0rc2.dist-info → qiskit-1.3.1.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.3.0rc2.dist-info → qiskit-1.3.1.dist-info}/WHEEL +0 -0
- {qiskit-1.3.0rc2.dist-info → qiskit-1.3.1.dist-info}/top_level.txt +0 -0
@@ -17,6 +17,8 @@ DensityMatrix quantum state class.
|
|
17
17
|
from __future__ import annotations
|
18
18
|
import copy as _copy
|
19
19
|
from numbers import Number
|
20
|
+
from typing import TYPE_CHECKING
|
21
|
+
|
20
22
|
import numpy as np
|
21
23
|
|
22
24
|
from qiskit import _numpy_compat
|
@@ -37,27 +39,27 @@ from qiskit.quantum_info.operators.channel.superop import SuperOp
|
|
37
39
|
from qiskit._accelerate.pauli_expval import density_expval_pauli_no_x, density_expval_pauli_with_x
|
38
40
|
from qiskit.quantum_info.states.statevector import Statevector
|
39
41
|
|
42
|
+
if TYPE_CHECKING:
|
43
|
+
from qiskit import circuit
|
44
|
+
|
40
45
|
|
41
46
|
class DensityMatrix(QuantumState, TolerancesMixin):
|
42
47
|
"""DensityMatrix class"""
|
43
48
|
|
44
49
|
def __init__(
|
45
50
|
self,
|
46
|
-
data: np.ndarray | list | QuantumCircuit | Instruction | QuantumState,
|
51
|
+
data: np.ndarray | list | QuantumCircuit | circuit.instruction.Instruction | QuantumState,
|
47
52
|
dims: int | tuple | list | None = None,
|
48
53
|
):
|
49
54
|
"""Initialize a density matrix object.
|
50
55
|
|
51
56
|
Args:
|
52
|
-
data
|
53
|
-
qiskit.circuit.Instruction):
|
54
|
-
A statevector, quantum instruction or an object with a ``to_operator`` or
|
57
|
+
data: A statevector, quantum instruction or an object with a ``to_operator`` or
|
55
58
|
``to_matrix`` method from which the density matrix can be constructed.
|
56
59
|
If a vector the density matrix is constructed as the projector of that vector.
|
57
60
|
If a quantum instruction, the density matrix is constructed by assuming all
|
58
61
|
qubits are initialized in the zero state.
|
59
|
-
dims
|
60
|
-
of the state (See additional information).
|
62
|
+
dims: The subsystem dimension of the state (See additional information).
|
61
63
|
|
62
64
|
Raises:
|
63
65
|
QiskitError: if input data is not valid.
|
@@ -303,19 +305,17 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
303
305
|
|
304
306
|
def evolve(
|
305
307
|
self,
|
306
|
-
other: Operator | QuantumChannel | Instruction | QuantumCircuit,
|
308
|
+
other: Operator | QuantumChannel | circuit.instruction.Instruction | QuantumCircuit,
|
307
309
|
qargs: list[int] | None = None,
|
308
310
|
) -> DensityMatrix:
|
309
311
|
"""Evolve a quantum state by an operator.
|
310
312
|
|
311
313
|
Args:
|
312
|
-
other
|
313
|
-
|
314
|
-
qargs (list): a list of QuantumState subsystem positions to apply
|
315
|
-
the operator on.
|
314
|
+
other: The operator to evolve by.
|
315
|
+
qargs: a list of QuantumState subsystem positions to apply the operator on.
|
316
316
|
|
317
317
|
Returns:
|
318
|
-
|
318
|
+
The output density matrix.
|
319
319
|
|
320
320
|
Raises:
|
321
321
|
QiskitError: if the operator dimension does not match the
|
@@ -598,7 +598,9 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
598
598
|
return DensityMatrix(state, dims=dims)
|
599
599
|
|
600
600
|
@classmethod
|
601
|
-
def from_instruction(
|
601
|
+
def from_instruction(
|
602
|
+
cls, instruction: circuit.instruction.Instruction | QuantumCircuit
|
603
|
+
) -> DensityMatrix:
|
602
604
|
"""Return the output density matrix of an instruction.
|
603
605
|
|
604
606
|
The statevector is initialized in the state :math:`|{0,\\ldots,0}\\rangle` of
|
@@ -606,10 +608,10 @@ class DensityMatrix(QuantumState, TolerancesMixin):
|
|
606
608
|
by the input instruction, and the output statevector returned.
|
607
609
|
|
608
610
|
Args:
|
609
|
-
instruction
|
611
|
+
instruction: instruction or circuit
|
610
612
|
|
611
613
|
Returns:
|
612
|
-
|
614
|
+
The final density matrix.
|
613
615
|
|
614
616
|
Raises:
|
615
617
|
QiskitError: if the instruction contains invalid instructions for
|
@@ -17,6 +17,7 @@ Stabilizer state class.
|
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
19
|
from collections.abc import Collection
|
20
|
+
from typing import TYPE_CHECKING
|
20
21
|
|
21
22
|
import numpy as np
|
22
23
|
|
@@ -28,6 +29,9 @@ from qiskit.quantum_info.operators.symplectic.clifford_circuits import _append_x
|
|
28
29
|
from qiskit.quantum_info.states.quantum_state import QuantumState
|
29
30
|
from qiskit.circuit import QuantumCircuit, Instruction
|
30
31
|
|
32
|
+
if TYPE_CHECKING:
|
33
|
+
from qiskit import circuit
|
34
|
+
|
31
35
|
|
32
36
|
class StabilizerState(QuantumState):
|
33
37
|
"""StabilizerState class.
|
@@ -79,17 +83,14 @@ class StabilizerState(QuantumState):
|
|
79
83
|
|
80
84
|
def __init__(
|
81
85
|
self,
|
82
|
-
data: StabilizerState | Clifford | Pauli | QuantumCircuit | Instruction,
|
86
|
+
data: StabilizerState | Clifford | Pauli | QuantumCircuit | circuit.instruction.Instruction,
|
83
87
|
validate: bool = True,
|
84
88
|
):
|
85
89
|
"""Initialize a StabilizerState object.
|
86
90
|
|
87
91
|
Args:
|
88
|
-
data
|
89
|
-
|
90
|
-
Data from which the stabilizer state can be constructed.
|
91
|
-
validate (boolean): validate that the stabilizer state data is
|
92
|
-
a valid Clifford.
|
92
|
+
data: Data from which the stabilizer state can be constructed.
|
93
|
+
validate: validate that the stabilizer state data is a valid Clifford.
|
93
94
|
"""
|
94
95
|
|
95
96
|
# Initialize from another StabilizerState
|
@@ -18,6 +18,7 @@ import copy as _copy
|
|
18
18
|
import math
|
19
19
|
import re
|
20
20
|
from numbers import Number
|
21
|
+
from typing import TYPE_CHECKING
|
21
22
|
|
22
23
|
import numpy as np
|
23
24
|
|
@@ -37,27 +38,34 @@ from qiskit._accelerate.pauli_expval import (
|
|
37
38
|
expval_pauli_with_x,
|
38
39
|
)
|
39
40
|
|
41
|
+
if TYPE_CHECKING:
|
42
|
+
from qiskit import circuit
|
43
|
+
|
40
44
|
|
41
45
|
class Statevector(QuantumState, TolerancesMixin):
|
42
46
|
"""Statevector class"""
|
43
47
|
|
44
48
|
def __init__(
|
45
49
|
self,
|
46
|
-
data:
|
50
|
+
data: (
|
51
|
+
np.ndarray
|
52
|
+
| list
|
53
|
+
| Statevector
|
54
|
+
| Operator
|
55
|
+
| QuantumCircuit
|
56
|
+
| circuit.instruction.Instruction
|
57
|
+
),
|
47
58
|
dims: int | tuple | list | None = None,
|
48
59
|
):
|
49
60
|
"""Initialize a statevector object.
|
50
61
|
|
51
62
|
Args:
|
52
|
-
data
|
53
|
-
qiskit.circuit.Instruction):
|
54
|
-
Data from which the statevector can be constructed. This can be either a complex
|
63
|
+
data: Data from which the statevector can be constructed. This can be either a complex
|
55
64
|
vector, another statevector, a ``Operator`` with only one column or a
|
56
65
|
``QuantumCircuit`` or ``Instruction``. If the data is a circuit or instruction,
|
57
66
|
the statevector is constructed by assuming that all qubits are initialized to the
|
58
67
|
zero state.
|
59
|
-
dims
|
60
|
-
the state (See additional information).
|
68
|
+
dims: The subsystem dimension of the state (See additional information).
|
61
69
|
|
62
70
|
Raises:
|
63
71
|
QiskitError: if input data is not valid.
|
@@ -17,8 +17,10 @@ from __future__ import annotations
|
|
17
17
|
from collections.abc import Sequence
|
18
18
|
from typing import Type
|
19
19
|
from fnmatch import fnmatch
|
20
|
+
import warnings
|
20
21
|
|
21
22
|
from qiskit.transpiler.basepasses import TransformationPass
|
23
|
+
from qiskit.transpiler.passes.utils import control_flow
|
22
24
|
from qiskit.dagcircuit.dagnode import DAGOpNode
|
23
25
|
from qiskit.dagcircuit.dagcircuit import DAGCircuit
|
24
26
|
from qiskit.converters.circuit_to_dag import circuit_to_dag
|
@@ -58,7 +60,7 @@ class Decompose(TransformationPass):
|
|
58
60
|
output dag where ``gate`` was expanded.
|
59
61
|
"""
|
60
62
|
# We might use HLS to synthesize objects that do not have a definition
|
61
|
-
hls = HighLevelSynthesis() if self.apply_synthesis else None
|
63
|
+
hls = HighLevelSynthesis(qubits_initially_zero=False) if self.apply_synthesis else None
|
62
64
|
|
63
65
|
# Walk through the DAG and expand each non-basis node
|
64
66
|
for node in dag.op_nodes():
|
@@ -66,12 +68,18 @@ class Decompose(TransformationPass):
|
|
66
68
|
if not self._should_decompose(node):
|
67
69
|
continue
|
68
70
|
|
69
|
-
if
|
71
|
+
if node.is_control_flow():
|
72
|
+
decomposition = control_flow.map_blocks(self.run, node.op)
|
73
|
+
dag.substitute_node(node, decomposition, inplace=True)
|
74
|
+
|
75
|
+
elif getattr(node.op, "definition", None) is None:
|
70
76
|
# if we try to synthesize, turn the node into a DAGCircuit and run HLS
|
71
77
|
if self.apply_synthesis:
|
78
|
+
# note that node_as_dag does not include the condition, which will
|
79
|
+
# be propagated in ``substitute_node_with_dag``
|
72
80
|
node_as_dag = _node_to_dag(node)
|
73
81
|
synthesized = hls.run(node_as_dag)
|
74
|
-
dag.substitute_node_with_dag(node, synthesized)
|
82
|
+
dag.substitute_node_with_dag(node, synthesized, propagate_condition=True)
|
75
83
|
|
76
84
|
# else: no definition and synthesis not enabled, so we do nothing
|
77
85
|
else:
|
@@ -123,9 +131,21 @@ class Decompose(TransformationPass):
|
|
123
131
|
|
124
132
|
|
125
133
|
def _node_to_dag(node: DAGOpNode) -> DAGCircuit:
|
134
|
+
# Control flow is already handled separately, however that does not capture
|
135
|
+
# c_if, which we are treating here. We explicitly ignore the condition attribute,
|
136
|
+
# which will be handled by ``substitute_node_with_dag``, so we create a copy of the node
|
137
|
+
# and set the condition to None. Once ``c_if`` is removed for 2.0, this block can go, too.
|
138
|
+
with warnings.catch_warnings():
|
139
|
+
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
140
|
+
if getattr(node.op, "condition", None) is not None:
|
141
|
+
op = node.op.copy()
|
142
|
+
op.condition = None
|
143
|
+
node = DAGOpNode(op, node.qargs, node.cargs)
|
144
|
+
|
145
|
+
# create new dag and apply the operation
|
126
146
|
dag = DAGCircuit()
|
127
147
|
dag.add_qubits(node.qargs)
|
128
148
|
dag.add_clbits(node.cargs)
|
129
|
-
|
130
149
|
dag.apply_operation_back(node.op, node.qargs, node.cargs)
|
150
|
+
|
131
151
|
return dag
|
@@ -19,6 +19,7 @@ from qiskit.circuit import Gate
|
|
19
19
|
from qiskit.dagcircuit import DAGCircuit
|
20
20
|
from qiskit.transpiler.basepasses import TransformationPass
|
21
21
|
from qiskit.transpiler.exceptions import TranspilerError
|
22
|
+
from qiskit.transpiler.passes.utils import control_flow
|
22
23
|
|
23
24
|
from qiskit._accelerate.inverse_cancellation import inverse_cancellation
|
24
25
|
|
@@ -74,6 +75,7 @@ class InverseCancellation(TransformationPass):
|
|
74
75
|
|
75
76
|
super().__init__()
|
76
77
|
|
78
|
+
@control_flow.trivial_recurse
|
77
79
|
def run(self, dag: DAGCircuit):
|
78
80
|
"""Run the InverseCancellation pass on `dag`.
|
79
81
|
|
@@ -263,11 +263,12 @@ Pauli Evolution Synthesis
|
|
263
263
|
- Targeted connectivity
|
264
264
|
* - ``"rustiq"``
|
265
265
|
- :class:`~.PauliEvolutionSynthesisRustiq`
|
266
|
-
- use
|
266
|
+
- use the synthesis method from `Rustiq circuit synthesis library
|
267
|
+
<https://github.com/smartiel/rustiq-core>`_
|
267
268
|
- all-to-all
|
268
269
|
* - ``"default"``
|
269
270
|
- :class:`~.PauliEvolutionSynthesisDefault`
|
270
|
-
- use
|
271
|
+
- use a diagonalizing Clifford per Pauli term
|
271
272
|
- all-to-all
|
272
273
|
|
273
274
|
.. autosummary::
|
@@ -299,6 +300,10 @@ Modular Adder Synthesis
|
|
299
300
|
- :class:`.ModularAdderSynthesisD00`
|
300
301
|
- 0
|
301
302
|
- a QFT-based adder
|
303
|
+
* - ``"default"``
|
304
|
+
- :class:`~.ModularAdderSynthesisDefault`
|
305
|
+
- any
|
306
|
+
- chooses the best algorithm based on the ancillas available
|
302
307
|
|
303
308
|
.. autosummary::
|
304
309
|
:toctree: ../stubs/
|
@@ -306,6 +311,7 @@ Modular Adder Synthesis
|
|
306
311
|
ModularAdderSynthesisC04
|
307
312
|
ModularAdderSynthesisD00
|
308
313
|
ModularAdderSynthesisV95
|
314
|
+
ModularAdderSynthesisDefault
|
309
315
|
|
310
316
|
Half Adder Synthesis
|
311
317
|
''''''''''''''''''''
|
@@ -329,6 +335,10 @@ Half Adder Synthesis
|
|
329
335
|
- :class:`.HalfAdderSynthesisD00`
|
330
336
|
- 0
|
331
337
|
- a QFT-based adder
|
338
|
+
* - ``"default"``
|
339
|
+
- :class:`~.HalfAdderSynthesisDefault`
|
340
|
+
- any
|
341
|
+
- chooses the best algorithm based on the ancillas available
|
332
342
|
|
333
343
|
.. autosummary::
|
334
344
|
:toctree: ../stubs/
|
@@ -336,6 +346,7 @@ Half Adder Synthesis
|
|
336
346
|
HalfAdderSynthesisC04
|
337
347
|
HalfAdderSynthesisD00
|
338
348
|
HalfAdderSynthesisV95
|
349
|
+
HalfAdderSynthesisDefault
|
339
350
|
|
340
351
|
Full Adder Synthesis
|
341
352
|
''''''''''''''''''''
|
@@ -355,12 +366,17 @@ Full Adder Synthesis
|
|
355
366
|
- :class:`.FullAdderSynthesisV95`
|
356
367
|
- :math:`n-1`, for :math:`n`-bit numbers
|
357
368
|
- a ripple-carry adder
|
369
|
+
* - ``"default"``
|
370
|
+
- :class:`~.FullAdderSynthesisDefault`
|
371
|
+
- any
|
372
|
+
- chooses the best algorithm based on the ancillas available
|
358
373
|
|
359
374
|
.. autosummary::
|
360
375
|
:toctree: ../stubs/
|
361
376
|
|
362
377
|
FullAdderSynthesisC04
|
363
378
|
FullAdderSynthesisV95
|
379
|
+
FullAdderSynthesisDefault
|
364
380
|
|
365
381
|
|
366
382
|
Multiplier Synthesis
|
@@ -375,7 +391,7 @@ Multiplier Synthesis
|
|
375
391
|
- Description
|
376
392
|
* - ``"cumulative"``
|
377
393
|
- :class:`.MultiplierSynthesisH18`
|
378
|
-
- depending on the :class:`.
|
394
|
+
- depending on the :class:`.HalfAdderGate` used
|
379
395
|
- a cumulative adder based on controlled adders
|
380
396
|
* - ``"qft"``
|
381
397
|
- :class:`.MultiplierSynthesisR17`
|
@@ -1211,10 +1227,26 @@ class ModularAdderSynthesisDefault(HighLevelSynthesisPlugin):
|
|
1211
1227
|
if not isinstance(high_level_object, ModularAdderGate):
|
1212
1228
|
return None
|
1213
1229
|
|
1214
|
-
|
1215
|
-
|
1230
|
+
# For up to 5 qubits, the QFT-based adder is best
|
1231
|
+
if high_level_object.num_state_qubits <= 5:
|
1232
|
+
decomposition = ModularAdderSynthesisD00().run(
|
1233
|
+
high_level_object, coupling_map, target, qubits, **options
|
1234
|
+
)
|
1235
|
+
if decomposition is not None:
|
1236
|
+
return decomposition
|
1216
1237
|
|
1217
|
-
|
1238
|
+
# Otherwise, the following decomposition is best (if there are enough ancillas)
|
1239
|
+
if (
|
1240
|
+
decomposition := ModularAdderSynthesisC04().run(
|
1241
|
+
high_level_object, coupling_map, target, qubits, **options
|
1242
|
+
)
|
1243
|
+
) is not None:
|
1244
|
+
return decomposition
|
1245
|
+
|
1246
|
+
# Otherwise, use the QFT-adder again
|
1247
|
+
return ModularAdderSynthesisD00().run(
|
1248
|
+
high_level_object, coupling_map, target, qubits, **options
|
1249
|
+
)
|
1218
1250
|
|
1219
1251
|
|
1220
1252
|
class ModularAdderSynthesisC04(HighLevelSynthesisPlugin):
|
@@ -1263,8 +1295,8 @@ class ModularAdderSynthesisV95(HighLevelSynthesisPlugin):
|
|
1263
1295
|
|
1264
1296
|
num_state_qubits = high_level_object.num_state_qubits
|
1265
1297
|
|
1266
|
-
#
|
1267
|
-
if num_state_qubits
|
1298
|
+
# The synthesis method needs n-1 clean ancilla qubits
|
1299
|
+
if num_state_qubits - 1 > options.get("num_clean_ancillas", 0):
|
1268
1300
|
return None
|
1269
1301
|
|
1270
1302
|
return adder_ripple_v95(num_state_qubits, kind="fixed")
|
@@ -1308,10 +1340,26 @@ class HalfAdderSynthesisDefault(HighLevelSynthesisPlugin):
|
|
1308
1340
|
if not isinstance(high_level_object, HalfAdderGate):
|
1309
1341
|
return None
|
1310
1342
|
|
1311
|
-
|
1312
|
-
|
1343
|
+
# For up to 3 qubits, ripple_v95 is better (if there are enough ancilla qubits)
|
1344
|
+
if high_level_object.num_state_qubits <= 3:
|
1345
|
+
decomposition = HalfAdderSynthesisV95().run(
|
1346
|
+
high_level_object, coupling_map, target, qubits, **options
|
1347
|
+
)
|
1348
|
+
if decomposition is not None:
|
1349
|
+
return decomposition
|
1313
1350
|
|
1314
|
-
|
1351
|
+
# The next best option is to use ripple_c04 (if there are enough ancilla qubits)
|
1352
|
+
if (
|
1353
|
+
decomposition := HalfAdderSynthesisC04().run(
|
1354
|
+
high_level_object, coupling_map, target, qubits, **options
|
1355
|
+
)
|
1356
|
+
) is not None:
|
1357
|
+
return decomposition
|
1358
|
+
|
1359
|
+
# The QFT-based adder does not require ancilla qubits and should always succeed
|
1360
|
+
return HalfAdderSynthesisD00().run(
|
1361
|
+
high_level_object, coupling_map, target, qubits, **options
|
1362
|
+
)
|
1315
1363
|
|
1316
1364
|
|
1317
1365
|
class HalfAdderSynthesisC04(HighLevelSynthesisPlugin):
|
@@ -1359,8 +1407,8 @@ class HalfAdderSynthesisV95(HighLevelSynthesisPlugin):
|
|
1359
1407
|
|
1360
1408
|
num_state_qubits = high_level_object.num_state_qubits
|
1361
1409
|
|
1362
|
-
#
|
1363
|
-
if num_state_qubits
|
1410
|
+
# The synthesis method needs n-1 clean ancilla qubits
|
1411
|
+
if num_state_qubits - 1 > options.get("num_clean_ancillas", 0):
|
1364
1412
|
return None
|
1365
1413
|
|
1366
1414
|
return adder_ripple_v95(num_state_qubits, kind="half")
|
@@ -1380,18 +1428,38 @@ class HalfAdderSynthesisD00(HighLevelSynthesisPlugin):
|
|
1380
1428
|
return adder_qft_d00(high_level_object.num_state_qubits, kind="half")
|
1381
1429
|
|
1382
1430
|
|
1383
|
-
class
|
1431
|
+
class FullAdderSynthesisDefault(HighLevelSynthesisPlugin):
|
1384
1432
|
"""A ripple-carry adder with a carry-in and a carry-out bit.
|
1385
1433
|
|
1386
|
-
This plugin name is:``FullAdder.
|
1434
|
+
This plugin name is:``FullAdder.default`` which can be used as the key on
|
1387
1435
|
an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
|
1436
|
+
"""
|
1388
1437
|
|
1389
|
-
|
1438
|
+
def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
|
1439
|
+
if not isinstance(high_level_object, FullAdderGate):
|
1440
|
+
return None
|
1390
1441
|
|
1391
|
-
|
1442
|
+
# FullAdderSynthesisC04 requires no ancilla qubits and returns better results
|
1443
|
+
# than FullAdderSynthesisV95 in all cases except for n=1.
|
1444
|
+
if high_level_object.num_state_qubits == 1:
|
1445
|
+
decomposition = FullAdderSynthesisV95().run(
|
1446
|
+
high_level_object, coupling_map, target, qubits, **options
|
1447
|
+
)
|
1448
|
+
if decomposition is not None:
|
1449
|
+
return decomposition
|
1450
|
+
|
1451
|
+
return FullAdderSynthesisC04().run(
|
1452
|
+
high_level_object, coupling_map, target, qubits, **options
|
1453
|
+
)
|
1392
1454
|
|
1393
|
-
* ``num_clean_ancillas``: The number of clean auxiliary qubits available.
|
1394
1455
|
|
1456
|
+
class FullAdderSynthesisC04(HighLevelSynthesisPlugin):
|
1457
|
+
"""A ripple-carry adder with a carry-in and a carry-out bit.
|
1458
|
+
|
1459
|
+
This plugin name is:``FullAdder.ripple_c04`` which can be used as the key on
|
1460
|
+
an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
|
1461
|
+
|
1462
|
+
This plugin requires no auxiliary qubits.
|
1395
1463
|
"""
|
1396
1464
|
|
1397
1465
|
def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
|
@@ -1408,7 +1476,7 @@ class FullAdderSynthesisV95(HighLevelSynthesisPlugin):
|
|
1408
1476
|
an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
|
1409
1477
|
|
1410
1478
|
For an adder on 2 registers with :math:`n` qubits each, this plugin requires at
|
1411
|
-
least :math:`n-1` clean auxiliary
|
1479
|
+
least :math:`n-1` clean auxiliary qubits.
|
1412
1480
|
|
1413
1481
|
The plugin supports the following plugin-specific options:
|
1414
1482
|
|
@@ -1421,8 +1489,8 @@ class FullAdderSynthesisV95(HighLevelSynthesisPlugin):
|
|
1421
1489
|
|
1422
1490
|
num_state_qubits = high_level_object.num_state_qubits
|
1423
1491
|
|
1424
|
-
#
|
1425
|
-
if num_state_qubits
|
1492
|
+
# The synthesis method needs n-1 clean ancilla qubits
|
1493
|
+
if num_state_qubits - 1 > options.get("num_clean_ancillas", 0):
|
1426
1494
|
return None
|
1427
1495
|
|
1428
1496
|
return adder_ripple_v95(num_state_qubits, kind="full")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qiskit
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.1
|
4
4
|
Summary: An open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
|
5
5
|
Author-email: Qiskit Development Team <qiskit@us.ibm.com>
|
6
6
|
License: Apache 2.0
|
@@ -120,13 +120,13 @@ we use `measure_all(inplace=False)` to get a copy of the circuit in which all th
|
|
120
120
|
qc_measured = qc_example.measure_all(inplace=False)
|
121
121
|
|
122
122
|
# 3. Execute using the Sampler primitive
|
123
|
-
from qiskit.primitives
|
124
|
-
sampler =
|
125
|
-
job = sampler.run(qc_measured, shots=1000)
|
123
|
+
from qiskit.primitives import StatevectorSampler
|
124
|
+
sampler = StatevectorSampler()
|
125
|
+
job = sampler.run([qc_measured], shots=1000)
|
126
126
|
result = job.result()
|
127
|
-
print(f" >
|
127
|
+
print(f" > Counts: {result[0].data["meas"].get_counts()}")
|
128
128
|
```
|
129
|
-
Running this will give an outcome similar to `{
|
129
|
+
Running this will give an outcome similar to `{'000': 497, '111': 503}` which is `000` 50% of the time and `111` 50% of the time up to statistical fluctuations.
|
130
130
|
To illustrate the power of Estimator, we now use the quantum information toolbox to create the operator $XXY+XYX+YXX-YYY$ and pass it to the `run()` function, along with our quantum circuit. Note the Estimator requires a circuit _**without**_ measurement, so we use the `qc_example` circuit we created earlier.
|
131
131
|
|
132
132
|
```python
|
@@ -135,17 +135,17 @@ from qiskit.quantum_info import SparsePauliOp
|
|
135
135
|
operator = SparsePauliOp.from_list([("XXY", 1), ("XYX", 1), ("YXX", 1), ("YYY", -1)])
|
136
136
|
|
137
137
|
# 3. Execute using the Estimator primitive
|
138
|
-
from qiskit.primitives import
|
139
|
-
estimator =
|
140
|
-
job = estimator.run(qc_example, operator,
|
138
|
+
from qiskit.primitives import StatevectorEstimator
|
139
|
+
estimator = StatevectorEstimator()
|
140
|
+
job = estimator.run([(qc_example, operator)], precision=1e-3)
|
141
141
|
result = job.result()
|
142
|
-
print(f" > Expectation values: {result.
|
142
|
+
print(f" > Expectation values: {result[0].data.evs}")
|
143
143
|
```
|
144
144
|
|
145
145
|
Running this will give the outcome `4`. For fun, try to assign a value of +/- 1 to each single-qubit operator X and Y
|
146
146
|
and see if you can achieve this outcome. (Spoiler alert: this is not possible!)
|
147
147
|
|
148
|
-
Using the Qiskit-provided `qiskit.primitives.
|
148
|
+
Using the Qiskit-provided `qiskit.primitives.StatevectorSampler` and `qiskit.primitives.StatevectorEstimator` will not take you very far.
|
149
149
|
The power of quantum computing cannot be simulated on classical computers and you need to use real quantum hardware to scale to larger quantum circuits.
|
150
150
|
However, running a quantum circuit on hardware requires rewriting to the basis gates and connectivity of the quantum hardware.
|
151
151
|
The tool that does this is the [transpiler](https://docs.quantum.ibm.com/api/qiskit/transpiler), and Qiskit includes transpiler passes for synthesis, optimization, mapping, and scheduling.
|
@@ -160,7 +160,7 @@ qc_transpiled = transpile(qc_example, basis_gates = ['cz', 'sx', 'rz'], coupling
|
|
160
160
|
### Executing your code on real quantum hardware
|
161
161
|
|
162
162
|
Qiskit provides an abstraction layer that lets users run quantum circuits on hardware from any vendor that provides a compatible interface.
|
163
|
-
The best way to use Qiskit is with a runtime environment that provides optimized implementations of `sampler` and `estimator` for a given hardware platform. This runtime may involve using pre- and post-processing, such as optimized transpiler passes with error suppression, error mitigation, and, eventually, error correction built in. A runtime implements `qiskit.primitives.
|
163
|
+
The best way to use Qiskit is with a runtime environment that provides optimized implementations of `sampler` and `estimator` for a given hardware platform. This runtime may involve using pre- and post-processing, such as optimized transpiler passes with error suppression, error mitigation, and, eventually, error correction built in. A runtime implements `qiskit.primitives.BaseSamplerV2` and `qiskit.primitives.BaseEstimatorV2` interfaces. For example,
|
164
164
|
some packages that provide implementations of a runtime primitive implementation are:
|
165
165
|
|
166
166
|
* https://github.com/Qiskit/qiskit-ibm-runtime
|