qiskit 2.0.2__cp39-abi3-win_amd64.whl → 2.1.0rc1__cp39-abi3-win_amd64.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 +19 -1
- qiskit/_accelerate.pyd +0 -0
- qiskit/circuit/__init__.py +13 -21
- qiskit/circuit/_add_control.py +57 -31
- qiskit/circuit/_classical_resource_map.py +4 -0
- qiskit/circuit/annotation.py +404 -0
- qiskit/circuit/classical/expr/__init__.py +1 -1
- qiskit/circuit/classical/expr/expr.py +104 -446
- qiskit/circuit/classical/expr/visitors.py +6 -0
- qiskit/circuit/classical/types/types.py +7 -130
- qiskit/circuit/controlflow/box.py +32 -7
- qiskit/circuit/delay.py +11 -9
- qiskit/circuit/library/arithmetic/adders/adder.py +5 -5
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +3 -3
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +7 -3
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +23 -15
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +22 -14
- qiskit/circuit/library/arithmetic/quadratic_form.py +6 -0
- qiskit/circuit/library/arithmetic/weighted_adder.py +43 -24
- qiskit/circuit/library/basis_change/qft.py +2 -2
- qiskit/circuit/library/blueprintcircuit.py +6 -0
- qiskit/circuit/library/boolean_logic/inner_product.py +2 -2
- qiskit/circuit/library/boolean_logic/quantum_and.py +2 -2
- qiskit/circuit/library/boolean_logic/quantum_or.py +3 -3
- qiskit/circuit/library/boolean_logic/quantum_xor.py +2 -2
- qiskit/circuit/library/data_preparation/_z_feature_map.py +2 -2
- qiskit/circuit/library/data_preparation/_zz_feature_map.py +2 -2
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +2 -2
- qiskit/circuit/library/fourier_checking.py +2 -2
- qiskit/circuit/library/generalized_gates/diagonal.py +5 -1
- qiskit/circuit/library/generalized_gates/gms.py +5 -1
- qiskit/circuit/library/generalized_gates/linear_function.py +2 -2
- qiskit/circuit/library/generalized_gates/permutation.py +5 -1
- qiskit/circuit/library/generalized_gates/uc.py +1 -1
- qiskit/circuit/library/generalized_gates/unitary.py +21 -2
- qiskit/circuit/library/graph_state.py +2 -2
- qiskit/circuit/library/grover_operator.py +2 -2
- qiskit/circuit/library/hidden_linear_function.py +2 -2
- qiskit/circuit/library/iqp.py +2 -2
- qiskit/circuit/library/n_local/efficient_su2.py +2 -2
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
- qiskit/circuit/library/n_local/excitation_preserving.py +7 -9
- qiskit/circuit/library/n_local/n_local.py +4 -3
- qiskit/circuit/library/n_local/pauli_two_design.py +2 -2
- qiskit/circuit/library/n_local/real_amplitudes.py +2 -2
- qiskit/circuit/library/n_local/two_local.py +2 -2
- qiskit/circuit/library/overlap.py +2 -2
- qiskit/circuit/library/pauli_evolution.py +3 -2
- qiskit/circuit/library/phase_estimation.py +2 -2
- qiskit/circuit/library/standard_gates/dcx.py +11 -12
- qiskit/circuit/library/standard_gates/ecr.py +21 -24
- qiskit/circuit/library/standard_gates/equivalence_library.py +232 -96
- qiskit/circuit/library/standard_gates/global_phase.py +5 -6
- qiskit/circuit/library/standard_gates/h.py +22 -45
- qiskit/circuit/library/standard_gates/i.py +1 -1
- qiskit/circuit/library/standard_gates/iswap.py +13 -31
- qiskit/circuit/library/standard_gates/p.py +19 -26
- qiskit/circuit/library/standard_gates/r.py +11 -17
- qiskit/circuit/library/standard_gates/rx.py +21 -45
- qiskit/circuit/library/standard_gates/rxx.py +7 -22
- qiskit/circuit/library/standard_gates/ry.py +21 -39
- qiskit/circuit/library/standard_gates/ryy.py +13 -28
- qiskit/circuit/library/standard_gates/rz.py +18 -35
- qiskit/circuit/library/standard_gates/rzx.py +7 -22
- qiskit/circuit/library/standard_gates/rzz.py +7 -19
- qiskit/circuit/library/standard_gates/s.py +44 -39
- qiskit/circuit/library/standard_gates/swap.py +25 -38
- qiskit/circuit/library/standard_gates/sx.py +34 -41
- qiskit/circuit/library/standard_gates/t.py +18 -27
- qiskit/circuit/library/standard_gates/u.py +8 -24
- qiskit/circuit/library/standard_gates/u1.py +28 -52
- qiskit/circuit/library/standard_gates/u2.py +9 -9
- qiskit/circuit/library/standard_gates/u3.py +24 -40
- qiskit/circuit/library/standard_gates/x.py +190 -336
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +12 -50
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +13 -52
- qiskit/circuit/library/standard_gates/y.py +19 -23
- qiskit/circuit/library/standard_gates/z.py +31 -38
- qiskit/circuit/parameter.py +14 -5
- qiskit/circuit/parameterexpression.py +109 -75
- qiskit/circuit/quantumcircuit.py +168 -98
- qiskit/circuit/quantumcircuitdata.py +1 -0
- qiskit/circuit/random/__init__.py +37 -2
- qiskit/circuit/random/utils.py +445 -56
- qiskit/circuit/tools/pi_check.py +5 -13
- qiskit/compiler/transpiler.py +1 -1
- qiskit/converters/circuit_to_instruction.py +2 -2
- qiskit/dagcircuit/dagnode.py +8 -3
- qiskit/primitives/__init__.py +2 -2
- qiskit/primitives/base/base_estimator.py +2 -2
- qiskit/primitives/containers/data_bin.py +0 -3
- qiskit/primitives/containers/observables_array.py +192 -108
- qiskit/primitives/primitive_job.py +29 -10
- qiskit/providers/fake_provider/generic_backend_v2.py +2 -0
- qiskit/qasm3/__init__.py +106 -12
- qiskit/qasm3/ast.py +15 -1
- qiskit/qasm3/exporter.py +59 -36
- qiskit/qasm3/printer.py +12 -0
- qiskit/qpy/__init__.py +183 -7
- qiskit/qpy/binary_io/circuits.py +256 -24
- qiskit/qpy/binary_io/parse_sympy_repr.py +5 -0
- qiskit/qpy/binary_io/schedules.py +12 -32
- qiskit/qpy/binary_io/value.py +36 -18
- qiskit/qpy/common.py +11 -3
- qiskit/qpy/formats.py +17 -1
- qiskit/qpy/interface.py +52 -12
- qiskit/qpy/type_keys.py +7 -1
- qiskit/quantum_info/__init__.py +10 -0
- qiskit/quantum_info/operators/__init__.py +1 -0
- qiskit/quantum_info/operators/symplectic/__init__.py +1 -0
- qiskit/quantum_info/operators/symplectic/clifford_circuits.py +26 -0
- qiskit/quantum_info/operators/symplectic/pauli.py +2 -2
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +1 -1
- qiskit/result/sampled_expval.py +3 -1
- qiskit/synthesis/__init__.py +10 -0
- qiskit/synthesis/arithmetic/__init__.py +1 -1
- qiskit/synthesis/arithmetic/adders/__init__.py +1 -0
- qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +6 -2
- qiskit/synthesis/arithmetic/adders/rv_ripple_carry_adder.py +156 -0
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +14 -126
- qiskit/synthesis/discrete_basis/solovay_kitaev.py +161 -121
- qiskit/synthesis/evolution/lie_trotter.py +10 -7
- qiskit/synthesis/evolution/product_formula.py +10 -7
- qiskit/synthesis/evolution/qdrift.py +10 -7
- qiskit/synthesis/evolution/suzuki_trotter.py +10 -7
- qiskit/synthesis/multi_controlled/__init__.py +4 -0
- qiskit/synthesis/multi_controlled/mcx_synthesis.py +402 -178
- qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +14 -15
- qiskit/synthesis/qft/qft_decompose_lnn.py +7 -25
- qiskit/synthesis/unitary/qsd.py +80 -9
- qiskit/transpiler/__init__.py +19 -8
- qiskit/transpiler/instruction_durations.py +2 -20
- qiskit/transpiler/passes/__init__.py +4 -2
- qiskit/transpiler/passes/layout/dense_layout.py +26 -6
- qiskit/transpiler/passes/layout/disjoint_utils.py +1 -166
- qiskit/transpiler/passes/layout/sabre_layout.py +22 -3
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +1 -1
- qiskit/transpiler/passes/layout/vf2_layout.py +49 -13
- qiskit/transpiler/passes/layout/vf2_utils.py +13 -1
- qiskit/transpiler/passes/optimization/__init__.py +1 -1
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +2 -1
- qiskit/transpiler/passes/optimization/optimize_clifford_t.py +68 -0
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +3 -9
- qiskit/transpiler/passes/routing/sabre_swap.py +12 -2
- qiskit/transpiler/passes/routing/star_prerouting.py +106 -81
- qiskit/transpiler/passes/scheduling/__init__.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/__init__.py +1 -0
- qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py +876 -0
- qiskit/transpiler/passes/synthesis/__init__.py +1 -0
- qiskit/transpiler/passes/synthesis/clifford_unitary_synth_plugin.py +123 -0
- qiskit/transpiler/passes/synthesis/hls_plugins.py +472 -92
- qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +27 -22
- qiskit/transpiler/passmanager_config.py +3 -0
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +149 -28
- qiskit/transpiler/preset_passmanagers/common.py +101 -0
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +6 -0
- qiskit/transpiler/preset_passmanagers/level3.py +2 -2
- qiskit/utils/optionals.py +6 -5
- qiskit/visualization/circuit/_utils.py +5 -3
- qiskit/visualization/circuit/latex.py +9 -2
- qiskit/visualization/circuit/matplotlib.py +26 -4
- qiskit/visualization/circuit/qcstyle.py +9 -157
- qiskit/visualization/dag/__init__.py +13 -0
- qiskit/visualization/dag/dagstyle.py +103 -0
- qiskit/visualization/dag/styles/__init__.py +13 -0
- qiskit/visualization/dag/styles/color.json +10 -0
- qiskit/visualization/dag/styles/plain.json +5 -0
- qiskit/visualization/dag_visualization.py +169 -98
- qiskit/visualization/style.py +223 -0
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/METADATA +14 -13
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/RECORD +177 -168
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/entry_points.txt +6 -0
- qiskit/synthesis/discrete_basis/commutator_decompose.py +0 -265
- qiskit/synthesis/discrete_basis/gate_sequence.py +0 -421
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/WHEEL +0 -0
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/licenses/LICENSE.txt +0 -0
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/top_level.txt +0 -0
@@ -30,6 +30,9 @@ from qiskit.utils import optionals as _optionals
|
|
30
30
|
from qiskit.exceptions import InvalidFileError
|
31
31
|
from .exceptions import VisualizationError
|
32
32
|
|
33
|
+
from .style import load_style
|
34
|
+
from .dag.dagstyle import DAGStyleDict, DAGDefaultStyle
|
35
|
+
|
33
36
|
|
34
37
|
IMAGE_TYPES = {
|
35
38
|
"canon",
|
@@ -73,7 +76,12 @@ IMAGE_TYPES = {
|
|
73
76
|
|
74
77
|
@_optionals.HAS_GRAPHVIZ.require_in_call
|
75
78
|
@_optionals.HAS_PIL.require_in_call
|
76
|
-
def dag_drawer(
|
79
|
+
def dag_drawer(
|
80
|
+
dag,
|
81
|
+
scale=0.7,
|
82
|
+
filename=None,
|
83
|
+
style="color",
|
84
|
+
):
|
77
85
|
"""Plot the directed acyclic graph (dag) to represent operation dependencies
|
78
86
|
in a quantum circuit.
|
79
87
|
|
@@ -84,8 +92,19 @@ def dag_drawer(dag, scale=0.7, filename=None, style="color"):
|
|
84
92
|
dag (DAGCircuit or DAGDependency): The dag to draw.
|
85
93
|
scale (float): scaling factor
|
86
94
|
filename (str): file path to save image to (format inferred from name)
|
87
|
-
style (str):
|
88
|
-
|
95
|
+
style (dict or str): Style name, file name of style JSON file, or a
|
96
|
+
dictionary specifying the style.
|
97
|
+
|
98
|
+
* The supported style names are 'plain': B&W graph, 'color' (default):
|
99
|
+
(color input/output/op nodes)
|
100
|
+
* If given a JSON file, e.g. ``my_style.json`` or ``my_style`` (the ``.json``
|
101
|
+
extension may be omitted), this function attempts to load the style dictionary
|
102
|
+
from that location. Note, that the JSON file must completely specify the
|
103
|
+
visualization specifications. The file is searched for in
|
104
|
+
``qiskit/visualization/circuit/styles``, the current working directory, and
|
105
|
+
the location specified in ``~/.qiskit/settings.conf``.
|
106
|
+
* If ``None`` the default style ``"color"`` is used or, if given, the default style
|
107
|
+
specified in ``~/.qiskit/settings.conf``.
|
89
108
|
|
90
109
|
Returns:
|
91
110
|
PIL.Image: if in Jupyter notebook and not saving to file,
|
@@ -99,11 +118,10 @@ def dag_drawer(dag, scale=0.7, filename=None, style="color"):
|
|
99
118
|
|
100
119
|
Example:
|
101
120
|
.. plot::
|
102
|
-
|
103
|
-
|
121
|
+
:include-source:
|
122
|
+
:nofigs:
|
104
123
|
|
105
124
|
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
|
106
|
-
from qiskit.dagcircuit import DAGCircuit
|
107
125
|
from qiskit.converters import circuit_to_dag
|
108
126
|
from qiskit.visualization import dag_drawer
|
109
127
|
|
@@ -117,8 +135,16 @@ def dag_drawer(dag, scale=0.7, filename=None, style="color"):
|
|
117
135
|
circ.rz(0.5, q[1])
|
118
136
|
|
119
137
|
dag = circuit_to_dag(circ)
|
120
|
-
|
138
|
+
|
139
|
+
style = {
|
140
|
+
"inputnodecolor": "pink",
|
141
|
+
"outputnodecolor": "lightblue",
|
142
|
+
"opnodecolor": "red",
|
143
|
+
}
|
144
|
+
|
145
|
+
dag_drawer(dag, style=style)
|
121
146
|
"""
|
147
|
+
|
122
148
|
from PIL import Image
|
123
149
|
|
124
150
|
# NOTE: use type str checking to avoid potential cyclical import
|
@@ -130,13 +156,30 @@ def dag_drawer(dag, scale=0.7, filename=None, style="color"):
|
|
130
156
|
for reg in list(dag.qregs.values()) + list(dag.cregs.values())
|
131
157
|
for (idx, bit) in enumerate(reg)
|
132
158
|
}
|
159
|
+
|
160
|
+
graph_attrs = {}
|
161
|
+
if isinstance(style, dict):
|
162
|
+
for attr in ["fontsize", "bgcolor", "dpi", "pad"]:
|
163
|
+
if attr in style:
|
164
|
+
graph_attrs[attr] = str(style[attr])
|
165
|
+
|
166
|
+
style, _ = load_style(
|
167
|
+
style,
|
168
|
+
style_dict=DAGStyleDict,
|
169
|
+
default_style=DAGDefaultStyle(),
|
170
|
+
user_config_opt="circuit_graphviz_style",
|
171
|
+
user_config_path_opt="circuit_graphviz_style_path",
|
172
|
+
raise_error_if_not_found=True,
|
173
|
+
)
|
174
|
+
|
133
175
|
if "DAGDependency" in type_str:
|
134
176
|
# pylint: disable=cyclic-import
|
135
177
|
from qiskit.visualization.circuit._utils import get_bit_reg_index
|
136
178
|
|
137
179
|
qubit_indices = {bit: index for index, bit in enumerate(dag.qubits)}
|
138
180
|
clbit_indices = {bit: index for index, bit in enumerate(dag.clbits)}
|
139
|
-
graph_attrs
|
181
|
+
graph_attrs.update({"dpi": str(100 * scale)})
|
182
|
+
|
140
183
|
dag_dep_circ = dagdependency_to_circuit(dag)
|
141
184
|
|
142
185
|
def node_attr_func(node):
|
@@ -144,63 +187,64 @@ def dag_drawer(dag, scale=0.7, filename=None, style="color"):
|
|
144
187
|
nid_str = str(node._node_id)
|
145
188
|
else:
|
146
189
|
nid_str = str(node.node_id)
|
147
|
-
if style == "plain":
|
148
|
-
return {}
|
149
|
-
if style == "color":
|
150
|
-
n = {}
|
151
|
-
args = []
|
152
|
-
for count, arg in enumerate(node.qargs + node.cargs):
|
153
|
-
if count > 4:
|
154
|
-
args.append("...")
|
155
|
-
break
|
156
|
-
if isinstance(arg, Qubit):
|
157
|
-
f_str = f"q_{qubit_indices[arg]}"
|
158
|
-
elif isinstance(arg, Clbit):
|
159
|
-
f_str = f"c_{clbit_indices[arg]}"
|
160
|
-
else:
|
161
|
-
f_str = f"{arg.index}"
|
162
|
-
arg_str = register_bit_labels.get(arg, f_str)
|
163
|
-
args.append(arg_str)
|
164
190
|
|
165
|
-
|
191
|
+
n = {}
|
192
|
+
args = []
|
193
|
+
for count, arg in enumerate(node.qargs + node.cargs):
|
194
|
+
if count > 4:
|
195
|
+
args.append("...")
|
196
|
+
break
|
197
|
+
if isinstance(arg, Qubit):
|
198
|
+
f_str = f"q_{qubit_indices[arg]}"
|
199
|
+
elif isinstance(arg, Clbit):
|
200
|
+
f_str = f"c_{clbit_indices[arg]}"
|
201
|
+
else:
|
202
|
+
f_str = f"{arg.index}"
|
203
|
+
arg_str = register_bit_labels.get(arg, f_str)
|
204
|
+
args.append(arg_str)
|
205
|
+
|
206
|
+
n["label"] = (
|
207
|
+
nid_str + ": " + str(node.name) + " (" + str(args)[1:-1].replace("'", "") + ")"
|
208
|
+
)
|
209
|
+
if getattr(node.op, "condition", None):
|
210
|
+
condition = node.op.condition
|
211
|
+
if isinstance(condition, expr.Expr):
|
212
|
+
cond_txt = " (cond: [Expr]) ("
|
213
|
+
elif isinstance(condition[0], ClassicalRegister):
|
214
|
+
cond_txt = f" (cond: {condition[0].name}, {int(condition[1])}) ("
|
215
|
+
else:
|
216
|
+
register, bit_index, reg_index = get_bit_reg_index(dag_dep_circ, condition[0])
|
217
|
+
if register is not None:
|
218
|
+
cond_txt = f" (cond: {register.name}[{reg_index}], {int(condition[1])}) ("
|
219
|
+
else:
|
220
|
+
cond_txt = f" (cond: {bit_index}, {int(condition[1])}) ("
|
166
221
|
n["label"] = (
|
167
|
-
nid_str
|
222
|
+
nid_str
|
223
|
+
+ ": "
|
224
|
+
+ str(node.name)
|
225
|
+
+ cond_txt
|
226
|
+
+ str(args)[1:-1].replace("'", "")
|
227
|
+
+ ")"
|
168
228
|
)
|
229
|
+
|
230
|
+
if isinstance(style, dict):
|
231
|
+
n["style"] = "filled"
|
232
|
+
|
233
|
+
if "nodecolor" in style:
|
234
|
+
n["fillcolor"] = style["nodecolor"]
|
235
|
+
|
236
|
+
if "fontsize" in style:
|
237
|
+
n["fontsize"] = str(style["fontsize"])
|
238
|
+
|
169
239
|
if node.name == "barrier":
|
170
|
-
n["
|
171
|
-
n["fillcolor"] = "grey"
|
240
|
+
n["fillcolor"] = style["barriercolor"]
|
172
241
|
elif getattr(node.op, "_directive", False):
|
173
|
-
n["
|
174
|
-
n["fillcolor"] = "red"
|
242
|
+
n["fillcolor"] = style["directivecolor"]
|
175
243
|
elif getattr(node.op, "condition", None):
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
cond_txt = f" (cond: {condition[0].name}, {int(condition[1])}) ("
|
181
|
-
else:
|
182
|
-
register, bit_index, reg_index = get_bit_reg_index(
|
183
|
-
dag_dep_circ, condition[0]
|
184
|
-
)
|
185
|
-
if register is not None:
|
186
|
-
cond_txt = (
|
187
|
-
f" (cond: {register.name}[{reg_index}], {int(condition[1])}) ("
|
188
|
-
)
|
189
|
-
else:
|
190
|
-
cond_txt = f" (cond: {bit_index}, {int(condition[1])}) ("
|
191
|
-
n["style"] = "filled"
|
192
|
-
n["fillcolor"] = "green"
|
193
|
-
n["label"] = (
|
194
|
-
nid_str
|
195
|
-
+ ": "
|
196
|
-
+ str(node.name)
|
197
|
-
+ cond_txt
|
198
|
-
+ str(args)[1:-1].replace("'", "")
|
199
|
-
+ ")"
|
200
|
-
)
|
201
|
-
elif node.name != "measure": # measure is unfilled
|
202
|
-
n["style"] = "filled"
|
203
|
-
n["fillcolor"] = "lightblue"
|
244
|
+
n["fillcolor"] = style["conditioncolor"]
|
245
|
+
elif node.name == "measure":
|
246
|
+
n["fillcolor"] = style["measurecolor"]
|
247
|
+
|
204
248
|
return n
|
205
249
|
else:
|
206
250
|
raise VisualizationError(f"Unrecognized style {style} for the dag_drawer.")
|
@@ -208,55 +252,66 @@ def dag_drawer(dag, scale=0.7, filename=None, style="color"):
|
|
208
252
|
edge_attr_func = None
|
209
253
|
|
210
254
|
else:
|
211
|
-
graph_attrs
|
255
|
+
graph_attrs.update({"dpi": str(100 * scale)})
|
212
256
|
|
213
257
|
def node_attr_func(node):
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
if isinstance(node,
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
258
|
+
n = {}
|
259
|
+
if isinstance(node, DAGOpNode):
|
260
|
+
n["label"] = node.name
|
261
|
+
if isinstance(node, DAGInNode):
|
262
|
+
if isinstance(node.wire, Qubit):
|
263
|
+
label = register_bit_labels.get(node.wire, f"q_{dag.find_bit(node.wire).index}")
|
264
|
+
elif isinstance(node.wire, Clbit):
|
265
|
+
label = register_bit_labels.get(node.wire, f"c_{dag.find_bit(node.wire).index}")
|
266
|
+
else:
|
267
|
+
label = str(node.wire.name)
|
268
|
+
|
269
|
+
n["label"] = label
|
270
|
+
if isinstance(node, DAGOutNode):
|
271
|
+
if isinstance(node.wire, Qubit):
|
272
|
+
label = register_bit_labels.get(
|
273
|
+
node.wire, f"q[{dag.find_bit(node.wire).index}]"
|
274
|
+
)
|
275
|
+
elif isinstance(node.wire, Clbit):
|
276
|
+
label = register_bit_labels.get(
|
277
|
+
node.wire, f"c[{dag.find_bit(node.wire).index}]"
|
278
|
+
)
|
279
|
+
else:
|
280
|
+
label = str(node.wire.name)
|
281
|
+
n["label"] = label
|
282
|
+
|
283
|
+
if isinstance(style, dict):
|
284
|
+
n["style"] = "filled"
|
285
|
+
|
286
|
+
if "nodecolor" in style:
|
287
|
+
n["fillcolor"] = style["nodecolor"]
|
288
|
+
|
289
|
+
if "fontsize" in style:
|
290
|
+
n["fontsize"] = str(style["fontsize"])
|
234
291
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
292
|
+
if isinstance(node, DAGInNode):
|
293
|
+
if "inputnodecolor" in style:
|
294
|
+
n["fillcolor"] = style["inputnodecolor"]
|
295
|
+
if "inputnodefontcolor" in style:
|
296
|
+
n["fontcolor"] = style["inputnodefontcolor"]
|
239
297
|
if isinstance(node, DAGOutNode):
|
240
|
-
if
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
n["label"] = label
|
251
|
-
n["color"] = "black"
|
252
|
-
n["style"] = "filled"
|
253
|
-
n["fillcolor"] = "red"
|
298
|
+
if "outputnodecolor" in style:
|
299
|
+
n["fillcolor"] = style["outputnodecolor"]
|
300
|
+
if "outputnodefontcolor" in style:
|
301
|
+
n["fontcolor"] = style["outputnodefontcolor"]
|
302
|
+
if isinstance(node, DAGOpNode):
|
303
|
+
if "opnodecolor" in style:
|
304
|
+
n["fillcolor"] = style["opnodecolor"]
|
305
|
+
if "opnodefontcolor" in style:
|
306
|
+
n["fontcolor"] = style["opnodefontcolor"]
|
307
|
+
|
254
308
|
return n
|
255
309
|
else:
|
256
310
|
raise VisualizationError(f"Invalid style {style}")
|
257
311
|
|
258
312
|
def edge_attr_func(edge):
|
259
313
|
e = {}
|
314
|
+
|
260
315
|
if isinstance(edge, Qubit):
|
261
316
|
label = register_bit_labels.get(edge, f"q_{dag.find_bit(edge).index}")
|
262
317
|
elif isinstance(edge, Clbit):
|
@@ -264,6 +319,21 @@ def dag_drawer(dag, scale=0.7, filename=None, style="color"):
|
|
264
319
|
else:
|
265
320
|
label = str(edge.name)
|
266
321
|
e["label"] = label
|
322
|
+
|
323
|
+
if isinstance(style, dict):
|
324
|
+
if "edgecolor" in style:
|
325
|
+
e["color"] = style["edgecolor"]
|
326
|
+
if "fontsize" in style:
|
327
|
+
e["fontsize"] = str(style["fontsize"])
|
328
|
+
|
329
|
+
if isinstance(edge, Qubit):
|
330
|
+
if "qubitedgecolor" in style:
|
331
|
+
e["color"] = style["qubitedgecolor"]
|
332
|
+
if isinstance(edge, Clbit):
|
333
|
+
if "clbitedgecolor" in style:
|
334
|
+
e["color"] = style["clbitedgecolor"]
|
335
|
+
return e
|
336
|
+
|
267
337
|
return e
|
268
338
|
|
269
339
|
image_type = "png"
|
@@ -307,6 +377,7 @@ def dag_drawer(dag, scale=0.7, filename=None, style="color"):
|
|
307
377
|
text=True,
|
308
378
|
)
|
309
379
|
return None
|
380
|
+
|
310
381
|
else:
|
311
382
|
return graphviz_draw(
|
312
383
|
dag._multi_graph,
|
@@ -0,0 +1,223 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2025.
|
4
|
+
#
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
+
#
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
11
|
+
# that they have been altered from the originals.
|
12
|
+
|
13
|
+
"""
|
14
|
+
Generic style visualization library.
|
15
|
+
"""
|
16
|
+
|
17
|
+
import json
|
18
|
+
import os
|
19
|
+
from typing import Any, Union
|
20
|
+
from warnings import warn
|
21
|
+
from pathlib import Path
|
22
|
+
|
23
|
+
from qiskit import user_config
|
24
|
+
|
25
|
+
from .exceptions import VisualizationError
|
26
|
+
|
27
|
+
|
28
|
+
class StyleDict(dict):
|
29
|
+
"""
|
30
|
+
Attributes:
|
31
|
+
VALID_FIELDS (set): Set of valid field inputs to a function that supports a style parameter
|
32
|
+
ABBREVIATIONS (dict): Mapping of abbreviation:field for abbreviated inputs to VALID_FIELDS
|
33
|
+
(must exist in VALID FIELDS)
|
34
|
+
NESTED_ATTRS (set): Set of fields that are dictionaries, and need to be updated with .update
|
35
|
+
"""
|
36
|
+
|
37
|
+
VALID_FIELDS = set()
|
38
|
+
ABBREVIATIONS = {}
|
39
|
+
NESTED_ATTRS = set()
|
40
|
+
|
41
|
+
def __setitem__(self, key: Any, value: Any) -> None:
|
42
|
+
# allow using field ABBREVIATIONS
|
43
|
+
if key in self.ABBREVIATIONS:
|
44
|
+
key = self.ABBREVIATIONS[key]
|
45
|
+
|
46
|
+
if key not in self.VALID_FIELDS:
|
47
|
+
warn(
|
48
|
+
f"style option ({key}) is not supported",
|
49
|
+
UserWarning,
|
50
|
+
2,
|
51
|
+
)
|
52
|
+
return super().__setitem__(key, value)
|
53
|
+
|
54
|
+
def __getitem__(self, key: Any) -> Any:
|
55
|
+
# allow using field ABBREVIATIONS
|
56
|
+
if key in self.ABBREVIATIONS:
|
57
|
+
key = self.ABBREVIATIONS[key]
|
58
|
+
|
59
|
+
return super().__getitem__(key)
|
60
|
+
|
61
|
+
def update(self, other):
|
62
|
+
# the attributes "displaycolor" and "displaytext" are dictionaries
|
63
|
+
# themselves, therefore we need to propagate the update down to them
|
64
|
+
for attr in self.NESTED_ATTRS.intersection(other.keys()):
|
65
|
+
if attr in self.keys():
|
66
|
+
self[attr].update(other[attr])
|
67
|
+
else:
|
68
|
+
self[attr] = other[attr]
|
69
|
+
|
70
|
+
super().update((key, value) for key, value in other.items() if key not in self.NESTED_ATTRS)
|
71
|
+
|
72
|
+
|
73
|
+
class DefaultStyle:
|
74
|
+
"""
|
75
|
+
Attributes:
|
76
|
+
DEFAULT_STYLE_NAME (str): style name for the default style
|
77
|
+
STYLE_PATH: file path where DEFAULT_STYLE_NAME.json is located
|
78
|
+
"""
|
79
|
+
|
80
|
+
DEFAULT_STYLE_NAME = None
|
81
|
+
DEFAULT_STYLE_PATH = None
|
82
|
+
|
83
|
+
def __init__(self):
|
84
|
+
raise NotImplementedError()
|
85
|
+
|
86
|
+
|
87
|
+
def load_style(
|
88
|
+
style: Union[dict, str, None],
|
89
|
+
style_dict: type[StyleDict],
|
90
|
+
default_style: DefaultStyle,
|
91
|
+
user_config_opt: str,
|
92
|
+
user_config_path_opt: str,
|
93
|
+
raise_error_if_not_found: bool = False,
|
94
|
+
) -> tuple[StyleDict, float]:
|
95
|
+
"""Utility function to load style from json files.
|
96
|
+
|
97
|
+
Args:
|
98
|
+
style: Depending on the type, this acts differently:
|
99
|
+
|
100
|
+
* If a string, it can specify a supported style name (such
|
101
|
+
as "iqp" or "clifford"). It can also specify the name of
|
102
|
+
a custom color scheme stored as JSON file. This JSON file
|
103
|
+
_must_ specify a complete set of colors.
|
104
|
+
* If a dictionary, it may specify the style name via a
|
105
|
+
``{"name": "<desired style>"}`` entry. If this is not given,
|
106
|
+
the default style will be used. The remaining entries in the
|
107
|
+
dictionary can be used to override certain specs.
|
108
|
+
E.g. ``{"name": "iqp", "ec": "#FF0000"}`` will use the ``"iqp"``
|
109
|
+
color scheme but set the edgecolor to red.
|
110
|
+
style_dict: The class used to define the options for loading styles
|
111
|
+
default_style: DefaultStyle dictionary definition and documentation
|
112
|
+
user_config_opt: User config field in the Qiskit User Configuration File
|
113
|
+
used to define the style loaded
|
114
|
+
user_config_path_opt: User config field in the Qiskit User Configuration File
|
115
|
+
used to define the path to the style loaded
|
116
|
+
raise_error_if_not_found: When True, load_style will throw a VisualizationError
|
117
|
+
if the style parameter file is not found. When False, load_style will load
|
118
|
+
the style passed in by the default_style parameter.
|
119
|
+
|
120
|
+
|
121
|
+
Returns:
|
122
|
+
A tuple containing the style as dictionary and the default font ratio.
|
123
|
+
"""
|
124
|
+
|
125
|
+
default = default_style.DEFAULT_STYLE_NAME
|
126
|
+
|
127
|
+
# if the style is not given, try to load the configured default (if set),
|
128
|
+
# or use the default style
|
129
|
+
config = user_config.get_config()
|
130
|
+
if style is None:
|
131
|
+
if config:
|
132
|
+
style = config.get(user_config_opt, default)
|
133
|
+
else:
|
134
|
+
style = default
|
135
|
+
|
136
|
+
# determine the style name which could also be inside a dictionary, like
|
137
|
+
# style={"name": "clifford", <other settings...>}
|
138
|
+
if isinstance(style, dict):
|
139
|
+
style_name = style.get("name", default)
|
140
|
+
elif isinstance(style, str):
|
141
|
+
if style.endswith(".json"):
|
142
|
+
style_name = style[:-5]
|
143
|
+
else:
|
144
|
+
style_name = style
|
145
|
+
else:
|
146
|
+
warn(
|
147
|
+
f'Unsupported style parameter "{style}" of type {type(style)}. '
|
148
|
+
"Will use the default style.",
|
149
|
+
UserWarning,
|
150
|
+
2,
|
151
|
+
)
|
152
|
+
style_name = default
|
153
|
+
|
154
|
+
if style_name in [default]:
|
155
|
+
current_style = default_style.style
|
156
|
+
else:
|
157
|
+
# Search for file in 'styles' dir, then config_path, and finally the current directory
|
158
|
+
style_name = style_name + ".json"
|
159
|
+
style_paths = []
|
160
|
+
|
161
|
+
default_path = default_style.DEFAULT_STYLE_PATH / style_name
|
162
|
+
style_paths.append(default_path)
|
163
|
+
|
164
|
+
# check configured paths, if there are any
|
165
|
+
if config:
|
166
|
+
config_path = config.get(user_config_path_opt, "")
|
167
|
+
if config_path:
|
168
|
+
for path in config_path:
|
169
|
+
style_paths.append(Path(path) / style_name)
|
170
|
+
|
171
|
+
# check current directory
|
172
|
+
cwd_path = Path("") / style_name
|
173
|
+
style_paths.append(cwd_path)
|
174
|
+
|
175
|
+
for path in style_paths:
|
176
|
+
# expand ~ to the user directory and check if the file exists
|
177
|
+
exp_user = path.expanduser()
|
178
|
+
if os.path.isfile(exp_user):
|
179
|
+
try:
|
180
|
+
with open(exp_user) as infile:
|
181
|
+
json_style = json.load(infile)
|
182
|
+
|
183
|
+
current_style = style_dict(json_style)
|
184
|
+
break
|
185
|
+
except json.JSONDecodeError as err:
|
186
|
+
warn(
|
187
|
+
f"Could not decode JSON in file '{path}': {str(err)}. "
|
188
|
+
"Will use default style.",
|
189
|
+
UserWarning,
|
190
|
+
2,
|
191
|
+
)
|
192
|
+
break
|
193
|
+
except (OSError, FileNotFoundError):
|
194
|
+
warn(
|
195
|
+
f"Error loading JSON file '{path}'. Will use default style.",
|
196
|
+
UserWarning,
|
197
|
+
2,
|
198
|
+
)
|
199
|
+
break
|
200
|
+
else:
|
201
|
+
if raise_error_if_not_found:
|
202
|
+
raise VisualizationError(f"Invalid style {style_name}")
|
203
|
+
|
204
|
+
warn(
|
205
|
+
f"Style JSON file '{style_name}' not found in any of these locations: "
|
206
|
+
f"{', '.join(map(str, style_paths))}. "
|
207
|
+
"Will use default style.",
|
208
|
+
UserWarning,
|
209
|
+
2,
|
210
|
+
)
|
211
|
+
current_style = default_style.style
|
212
|
+
|
213
|
+
# if the style is a dictionary, update the defaults with the new values
|
214
|
+
# this _needs_ to happen after loading by name to cover cases like
|
215
|
+
# style = {"name": "bw", "edgecolor": "#FF0000"}
|
216
|
+
if isinstance(style, dict):
|
217
|
+
current_style.update(style)
|
218
|
+
|
219
|
+
# this is the default font ratio
|
220
|
+
# if the font- or subfont-sizes are changed, the new size is based on this ratio
|
221
|
+
def_font_ratio = 13 / 8
|
222
|
+
|
223
|
+
return current_style, def_font_ratio
|
@@ -1,15 +1,15 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: qiskit
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.1.0rc1
|
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
|
7
7
|
Project-URL: Homepage, https://www.ibm.com/quantum/qiskit
|
8
|
-
Project-URL: Documentation, https://
|
9
|
-
Project-URL: API Reference, https://
|
8
|
+
Project-URL: Documentation, https://quantum.cloud.ibm.com/docs
|
9
|
+
Project-URL: API Reference, https://quantum.cloud.ibm.com/docs/api/qiskit
|
10
10
|
Project-URL: Repository, https://github.com/Qiskit/qiskit
|
11
11
|
Project-URL: Issues, https://github.com/Qiskit/qiskit/issues
|
12
|
-
Project-URL: Changelog, https://
|
12
|
+
Project-URL: Changelog, https://quantum.cloud.ibm.com/docs/api/qiskit/release-notes
|
13
13
|
Keywords: qiskit,quantum circuit,quantum computing,quantum programming language,quantum,sdk
|
14
14
|
Classifier: Environment :: Console
|
15
15
|
Classifier: Intended Audience :: Developers
|
@@ -31,12 +31,9 @@ License-File: LICENSE.txt
|
|
31
31
|
Requires-Dist: rustworkx>=0.15.0
|
32
32
|
Requires-Dist: numpy<3,>=1.17
|
33
33
|
Requires-Dist: scipy>=1.5
|
34
|
-
Requires-Dist: sympy>=1.3
|
35
34
|
Requires-Dist: dill>=0.3
|
36
|
-
Requires-Dist: python-dateutil>=2.8.0
|
37
35
|
Requires-Dist: stevedore>=3.0.0
|
38
36
|
Requires-Dist: typing-extensions
|
39
|
-
Requires-Dist: symengine<0.14,>=0.11
|
40
37
|
Provides-Extra: qasm3-import
|
41
38
|
Requires-Dist: qiskit-qasm3-import>=0.1.0; extra == "qasm3-import"
|
42
39
|
Provides-Extra: visualization
|
@@ -45,19 +42,23 @@ Requires-Dist: pydot; extra == "visualization"
|
|
45
42
|
Requires-Dist: Pillow>=4.2.1; extra == "visualization"
|
46
43
|
Requires-Dist: pylatexenc>=1.4; extra == "visualization"
|
47
44
|
Requires-Dist: seaborn>=0.9.0; extra == "visualization"
|
45
|
+
Requires-Dist: sympy>=1.3; extra == "visualization"
|
48
46
|
Provides-Extra: crosstalk-pass
|
49
47
|
Requires-Dist: z3-solver>=4.7; extra == "crosstalk-pass"
|
50
48
|
Provides-Extra: csp-layout-pass
|
51
49
|
Requires-Dist: python-constraint>=1.4; extra == "csp-layout-pass"
|
50
|
+
Provides-Extra: qpy-compat
|
51
|
+
Requires-Dist: symengine<0.14,>=0.11; extra == "qpy-compat"
|
52
|
+
Requires-Dist: sympy>1.3; extra == "qpy-compat"
|
52
53
|
Provides-Extra: all
|
53
|
-
Requires-Dist: qiskit[crosstalk-pass,csp-layout-pass,qasm3-import,visualization]; extra == "all"
|
54
|
+
Requires-Dist: qiskit[crosstalk-pass,csp-layout-pass,qasm3-import,qpy-compat,visualization]; extra == "all"
|
54
55
|
Dynamic: license-file
|
55
56
|
|
56
57
|
# Qiskit
|
57
58
|
|
58
59
|
[](https://opensource.org/licenses/Apache-2.0) <!--- long-description-skip-begin -->
|
59
60
|
[](https://github.com/Qiskit/qiskit/releases)
|
60
|
-
|
61
|
+
[](https://github.com/Qiskit/qiskit/releases?q=tag%3A1)
|
61
62
|
[](https://pypi.org/project/qiskit/)
|
62
63
|
[](https://coveralls.io/github/Qiskit/qiskit?branch=main)
|
63
64
|

|
@@ -72,7 +73,7 @@ It also contains a transpiler that supports optimizing quantum circuits, and a q
|
|
72
73
|
|
73
74
|
For more details on how to use Qiskit, refer to the documentation located here:
|
74
75
|
|
75
|
-
<https://
|
76
|
+
<https://quantum.cloud.ibm.com/docs/>
|
76
77
|
|
77
78
|
|
78
79
|
## Installation
|
@@ -85,7 +86,7 @@ pip install qiskit
|
|
85
86
|
|
86
87
|
Pip will handle all dependencies automatically and you will always install the latest (and well-tested) version.
|
87
88
|
|
88
|
-
To install from source, follow the instructions in the [documentation](https://
|
89
|
+
To install from source, follow the instructions in the [documentation](https://quantum.cloud.ibm.com/docs/guides/install-qiskit-source).
|
89
90
|
|
90
91
|
## Create your first quantum program in Qiskit
|
91
92
|
|
@@ -146,7 +147,7 @@ and see if you can achieve this outcome. (Spoiler alert: this is not possible!)
|
|
146
147
|
Using the Qiskit-provided `qiskit.primitives.StatevectorSampler` and `qiskit.primitives.StatevectorEstimator` will not take you very far.
|
147
148
|
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.
|
148
149
|
However, running a quantum circuit on hardware requires rewriting to the basis gates and connectivity of the quantum hardware.
|
149
|
-
The tool that does this is the [transpiler](https://
|
150
|
+
The tool that does this is the [transpiler](https://quantum.cloud.ibm.com/docs/api/qiskit/transpiler), and Qiskit includes transpiler passes for synthesis, optimization, mapping, and scheduling.
|
150
151
|
However, it also includes a default compiler, which works very well in most examples.
|
151
152
|
The following code will map the example circuit to the `basis_gates = ["cz", "sx", "rz"]` and a linear chain of qubits $0 \rightarrow 1 \rightarrow 2$ with the `coupling_map = [[0, 1], [1, 2]]`.
|
152
153
|
|
@@ -209,7 +210,7 @@ release.
|
|
209
210
|
|
210
211
|
Additionally, as part of each release, detailed release notes are written to
|
211
212
|
document in detail what has changed as part of a release. This includes any
|
212
|
-
documentation on potential breaking changes on upgrade and new features. See [all release notes here](https://
|
213
|
+
documentation on potential breaking changes on upgrade and new features. See [all release notes here](https://quantum.cloud.ibm.com/docs/api/qiskit/release-notes).
|
213
214
|
|
214
215
|
## Acknowledgements
|
215
216
|
|