qiskit 2.0.2__cp39-abi3-macosx_11_0_arm64.whl → 2.1.0rc1__cp39-abi3-macosx_11_0_arm64.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.
Files changed (179) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +19 -1
  3. qiskit/_accelerate.abi3.so +0 -0
  4. qiskit/circuit/__init__.py +13 -21
  5. qiskit/circuit/_add_control.py +57 -31
  6. qiskit/circuit/_classical_resource_map.py +4 -0
  7. qiskit/circuit/annotation.py +404 -0
  8. qiskit/circuit/classical/expr/__init__.py +1 -1
  9. qiskit/circuit/classical/expr/expr.py +104 -446
  10. qiskit/circuit/classical/expr/visitors.py +6 -0
  11. qiskit/circuit/classical/types/types.py +7 -130
  12. qiskit/circuit/controlflow/box.py +32 -7
  13. qiskit/circuit/delay.py +11 -9
  14. qiskit/circuit/library/arithmetic/adders/adder.py +5 -5
  15. qiskit/circuit/library/arithmetic/multipliers/multiplier.py +3 -3
  16. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +7 -3
  17. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +23 -15
  18. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +22 -14
  19. qiskit/circuit/library/arithmetic/quadratic_form.py +6 -0
  20. qiskit/circuit/library/arithmetic/weighted_adder.py +43 -24
  21. qiskit/circuit/library/basis_change/qft.py +2 -2
  22. qiskit/circuit/library/blueprintcircuit.py +6 -0
  23. qiskit/circuit/library/boolean_logic/inner_product.py +2 -2
  24. qiskit/circuit/library/boolean_logic/quantum_and.py +2 -2
  25. qiskit/circuit/library/boolean_logic/quantum_or.py +3 -3
  26. qiskit/circuit/library/boolean_logic/quantum_xor.py +2 -2
  27. qiskit/circuit/library/data_preparation/_z_feature_map.py +2 -2
  28. qiskit/circuit/library/data_preparation/_zz_feature_map.py +2 -2
  29. qiskit/circuit/library/data_preparation/pauli_feature_map.py +2 -2
  30. qiskit/circuit/library/fourier_checking.py +2 -2
  31. qiskit/circuit/library/generalized_gates/diagonal.py +5 -1
  32. qiskit/circuit/library/generalized_gates/gms.py +5 -1
  33. qiskit/circuit/library/generalized_gates/linear_function.py +2 -2
  34. qiskit/circuit/library/generalized_gates/permutation.py +5 -1
  35. qiskit/circuit/library/generalized_gates/uc.py +1 -1
  36. qiskit/circuit/library/generalized_gates/unitary.py +21 -2
  37. qiskit/circuit/library/graph_state.py +2 -2
  38. qiskit/circuit/library/grover_operator.py +2 -2
  39. qiskit/circuit/library/hidden_linear_function.py +2 -2
  40. qiskit/circuit/library/iqp.py +2 -2
  41. qiskit/circuit/library/n_local/efficient_su2.py +2 -2
  42. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
  43. qiskit/circuit/library/n_local/excitation_preserving.py +7 -9
  44. qiskit/circuit/library/n_local/n_local.py +4 -3
  45. qiskit/circuit/library/n_local/pauli_two_design.py +2 -2
  46. qiskit/circuit/library/n_local/real_amplitudes.py +2 -2
  47. qiskit/circuit/library/n_local/two_local.py +2 -2
  48. qiskit/circuit/library/overlap.py +2 -2
  49. qiskit/circuit/library/pauli_evolution.py +3 -2
  50. qiskit/circuit/library/phase_estimation.py +2 -2
  51. qiskit/circuit/library/standard_gates/dcx.py +11 -12
  52. qiskit/circuit/library/standard_gates/ecr.py +21 -24
  53. qiskit/circuit/library/standard_gates/equivalence_library.py +232 -96
  54. qiskit/circuit/library/standard_gates/global_phase.py +5 -6
  55. qiskit/circuit/library/standard_gates/h.py +22 -45
  56. qiskit/circuit/library/standard_gates/i.py +1 -1
  57. qiskit/circuit/library/standard_gates/iswap.py +13 -31
  58. qiskit/circuit/library/standard_gates/p.py +19 -26
  59. qiskit/circuit/library/standard_gates/r.py +11 -17
  60. qiskit/circuit/library/standard_gates/rx.py +21 -45
  61. qiskit/circuit/library/standard_gates/rxx.py +7 -22
  62. qiskit/circuit/library/standard_gates/ry.py +21 -39
  63. qiskit/circuit/library/standard_gates/ryy.py +13 -28
  64. qiskit/circuit/library/standard_gates/rz.py +18 -35
  65. qiskit/circuit/library/standard_gates/rzx.py +7 -22
  66. qiskit/circuit/library/standard_gates/rzz.py +7 -19
  67. qiskit/circuit/library/standard_gates/s.py +44 -39
  68. qiskit/circuit/library/standard_gates/swap.py +25 -38
  69. qiskit/circuit/library/standard_gates/sx.py +34 -41
  70. qiskit/circuit/library/standard_gates/t.py +18 -27
  71. qiskit/circuit/library/standard_gates/u.py +8 -24
  72. qiskit/circuit/library/standard_gates/u1.py +28 -52
  73. qiskit/circuit/library/standard_gates/u2.py +9 -9
  74. qiskit/circuit/library/standard_gates/u3.py +24 -40
  75. qiskit/circuit/library/standard_gates/x.py +190 -336
  76. qiskit/circuit/library/standard_gates/xx_minus_yy.py +12 -50
  77. qiskit/circuit/library/standard_gates/xx_plus_yy.py +13 -52
  78. qiskit/circuit/library/standard_gates/y.py +19 -23
  79. qiskit/circuit/library/standard_gates/z.py +31 -38
  80. qiskit/circuit/parameter.py +14 -5
  81. qiskit/circuit/parameterexpression.py +109 -75
  82. qiskit/circuit/quantumcircuit.py +168 -98
  83. qiskit/circuit/quantumcircuitdata.py +1 -0
  84. qiskit/circuit/random/__init__.py +37 -2
  85. qiskit/circuit/random/utils.py +445 -56
  86. qiskit/circuit/tools/pi_check.py +5 -13
  87. qiskit/compiler/transpiler.py +1 -1
  88. qiskit/converters/circuit_to_instruction.py +2 -2
  89. qiskit/dagcircuit/dagnode.py +8 -3
  90. qiskit/primitives/__init__.py +2 -2
  91. qiskit/primitives/base/base_estimator.py +2 -2
  92. qiskit/primitives/containers/data_bin.py +0 -3
  93. qiskit/primitives/containers/observables_array.py +192 -108
  94. qiskit/primitives/primitive_job.py +29 -10
  95. qiskit/providers/fake_provider/generic_backend_v2.py +2 -0
  96. qiskit/qasm3/__init__.py +106 -12
  97. qiskit/qasm3/ast.py +15 -1
  98. qiskit/qasm3/exporter.py +59 -36
  99. qiskit/qasm3/printer.py +12 -0
  100. qiskit/qpy/__init__.py +183 -7
  101. qiskit/qpy/binary_io/circuits.py +256 -24
  102. qiskit/qpy/binary_io/parse_sympy_repr.py +5 -0
  103. qiskit/qpy/binary_io/schedules.py +12 -32
  104. qiskit/qpy/binary_io/value.py +36 -18
  105. qiskit/qpy/common.py +11 -3
  106. qiskit/qpy/formats.py +17 -1
  107. qiskit/qpy/interface.py +52 -12
  108. qiskit/qpy/type_keys.py +7 -1
  109. qiskit/quantum_info/__init__.py +10 -0
  110. qiskit/quantum_info/operators/__init__.py +1 -0
  111. qiskit/quantum_info/operators/symplectic/__init__.py +1 -0
  112. qiskit/quantum_info/operators/symplectic/clifford_circuits.py +26 -0
  113. qiskit/quantum_info/operators/symplectic/pauli.py +2 -2
  114. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +1 -1
  115. qiskit/result/sampled_expval.py +3 -1
  116. qiskit/synthesis/__init__.py +10 -0
  117. qiskit/synthesis/arithmetic/__init__.py +1 -1
  118. qiskit/synthesis/arithmetic/adders/__init__.py +1 -0
  119. qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +6 -2
  120. qiskit/synthesis/arithmetic/adders/rv_ripple_carry_adder.py +156 -0
  121. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +14 -126
  122. qiskit/synthesis/discrete_basis/solovay_kitaev.py +161 -121
  123. qiskit/synthesis/evolution/lie_trotter.py +10 -7
  124. qiskit/synthesis/evolution/product_formula.py +10 -7
  125. qiskit/synthesis/evolution/qdrift.py +10 -7
  126. qiskit/synthesis/evolution/suzuki_trotter.py +10 -7
  127. qiskit/synthesis/multi_controlled/__init__.py +4 -0
  128. qiskit/synthesis/multi_controlled/mcx_synthesis.py +402 -178
  129. qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +14 -15
  130. qiskit/synthesis/qft/qft_decompose_lnn.py +7 -25
  131. qiskit/synthesis/unitary/qsd.py +80 -9
  132. qiskit/transpiler/__init__.py +19 -8
  133. qiskit/transpiler/instruction_durations.py +2 -20
  134. qiskit/transpiler/passes/__init__.py +4 -2
  135. qiskit/transpiler/passes/layout/dense_layout.py +26 -6
  136. qiskit/transpiler/passes/layout/disjoint_utils.py +1 -166
  137. qiskit/transpiler/passes/layout/sabre_layout.py +22 -3
  138. qiskit/transpiler/passes/layout/sabre_pre_layout.py +1 -1
  139. qiskit/transpiler/passes/layout/vf2_layout.py +49 -13
  140. qiskit/transpiler/passes/layout/vf2_utils.py +13 -1
  141. qiskit/transpiler/passes/optimization/__init__.py +1 -1
  142. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +2 -1
  143. qiskit/transpiler/passes/optimization/optimize_clifford_t.py +68 -0
  144. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +3 -9
  145. qiskit/transpiler/passes/routing/sabre_swap.py +12 -2
  146. qiskit/transpiler/passes/routing/star_prerouting.py +106 -81
  147. qiskit/transpiler/passes/scheduling/__init__.py +1 -1
  148. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  149. qiskit/transpiler/passes/scheduling/padding/__init__.py +1 -0
  150. qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py +876 -0
  151. qiskit/transpiler/passes/synthesis/__init__.py +1 -0
  152. qiskit/transpiler/passes/synthesis/clifford_unitary_synth_plugin.py +123 -0
  153. qiskit/transpiler/passes/synthesis/hls_plugins.py +472 -92
  154. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +27 -22
  155. qiskit/transpiler/passmanager_config.py +3 -0
  156. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +149 -28
  157. qiskit/transpiler/preset_passmanagers/common.py +101 -0
  158. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +6 -0
  159. qiskit/transpiler/preset_passmanagers/level3.py +2 -2
  160. qiskit/utils/optionals.py +6 -5
  161. qiskit/visualization/circuit/_utils.py +5 -3
  162. qiskit/visualization/circuit/latex.py +9 -2
  163. qiskit/visualization/circuit/matplotlib.py +26 -4
  164. qiskit/visualization/circuit/qcstyle.py +9 -157
  165. qiskit/visualization/dag/__init__.py +13 -0
  166. qiskit/visualization/dag/dagstyle.py +103 -0
  167. qiskit/visualization/dag/styles/__init__.py +13 -0
  168. qiskit/visualization/dag/styles/color.json +10 -0
  169. qiskit/visualization/dag/styles/plain.json +5 -0
  170. qiskit/visualization/dag_visualization.py +169 -98
  171. qiskit/visualization/style.py +223 -0
  172. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/METADATA +14 -13
  173. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/RECORD +177 -168
  174. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/entry_points.txt +6 -0
  175. qiskit/synthesis/discrete_basis/commutator_decompose.py +0 -265
  176. qiskit/synthesis/discrete_basis/gate_sequence.py +0 -421
  177. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/WHEEL +0 -0
  178. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/licenses/LICENSE.txt +0 -0
  179. {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(dag, scale=0.7, filename=None, style="color"):
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): 'plain': B&W graph
88
- 'color' (default): color input/output/op nodes
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
- :include-source:
103
- :nofigs:
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
- dag_drawer(dag)
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 = {"dpi": str(100 * scale)}
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
- n["color"] = "black"
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 + ": " + str(node.name) + " (" + str(args)[1:-1].replace("'", "") + ")"
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["style"] = "filled"
171
- n["fillcolor"] = "grey"
240
+ n["fillcolor"] = style["barriercolor"]
172
241
  elif getattr(node.op, "_directive", False):
173
- n["style"] = "filled"
174
- n["fillcolor"] = "red"
242
+ n["fillcolor"] = style["directivecolor"]
175
243
  elif getattr(node.op, "condition", None):
176
- condition = node.op.condition
177
- if isinstance(condition, expr.Expr):
178
- cond_txt = " (cond: [Expr]) ("
179
- elif isinstance(condition[0], ClassicalRegister):
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 = {"dpi": str(100 * scale)}
255
+ graph_attrs.update({"dpi": str(100 * scale)})
212
256
 
213
257
  def node_attr_func(node):
214
- if style == "plain":
215
- return {}
216
- if style == "color":
217
- n = {}
218
- if isinstance(node, DAGOpNode):
219
- n["label"] = node.name
220
- n["color"] = "blue"
221
- n["style"] = "filled"
222
- n["fillcolor"] = "lightblue"
223
- if isinstance(node, DAGInNode):
224
- if isinstance(node.wire, Qubit):
225
- label = register_bit_labels.get(
226
- node.wire, f"q_{dag.find_bit(node.wire).index}"
227
- )
228
- elif isinstance(node.wire, Clbit):
229
- label = register_bit_labels.get(
230
- node.wire, f"c_{dag.find_bit(node.wire).index}"
231
- )
232
- else:
233
- label = str(node.wire.name)
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
- n["label"] = label
236
- n["color"] = "black"
237
- n["style"] = "filled"
238
- n["fillcolor"] = "green"
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 isinstance(node.wire, Qubit):
241
- label = register_bit_labels.get(
242
- node.wire, f"q[{dag.find_bit(node.wire).index}]"
243
- )
244
- elif isinstance(node.wire, Clbit):
245
- label = register_bit_labels.get(
246
- node.wire, f"c[{dag.find_bit(node.wire).index}]"
247
- )
248
- else:
249
- label = str(node.wire.name)
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.0.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://docs.quantum.ibm.com
9
- Project-URL: API Reference, https://docs.quantum.ibm.com/api/qiskit
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://docs.quantum.ibm.com/api/qiskit/release-notes
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
  [![License](https://img.shields.io/github/license/Qiskit/qiskit.svg?)](https://opensource.org/licenses/Apache-2.0) <!--- long-description-skip-begin -->
59
60
  [![Current Release](https://img.shields.io/github/release/Qiskit/qiskit.svg?logo=Qiskit)](https://github.com/Qiskit/qiskit/releases)
60
- <!-- [![Extended Support Release](https://img.shields.io/github/v/release/Qiskit/qiskit?sort=semver&filter=0.*&logo=Qiskit&label=extended%20support)](https://github.com/Qiskit/qiskit/releases?q=tag%3A0) -->
61
+ [![Extended Support Release](https://img.shields.io/github/v/release/Qiskit/qiskit?sort=semver&filter=1.*&logo=Qiskit&label=extended%20support)](https://github.com/Qiskit/qiskit/releases?q=tag%3A1)
61
62
  [![Downloads](https://img.shields.io/pypi/dm/qiskit.svg)](https://pypi.org/project/qiskit/)
62
63
  [![Coverage Status](https://coveralls.io/repos/github/Qiskit/qiskit/badge.svg?branch=main)](https://coveralls.io/github/Qiskit/qiskit?branch=main)
63
64
  ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/qiskit)
@@ -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://docs.quantum.ibm.com/>
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://docs.quantum.ibm.com/guides/install-qiskit-source).
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://docs.quantum.ibm.com/api/qiskit/transpiler), and Qiskit includes transpiler passes for synthesis, optimization, mapping, and scheduling.
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://docs.quantum.ibm.com/api/qiskit/release-notes).
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