superquantx 0.1.0__py3-none-any.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.
- superquantx/__init__.py +321 -0
- superquantx/algorithms/__init__.py +55 -0
- superquantx/algorithms/base_algorithm.py +413 -0
- superquantx/algorithms/hybrid_classifier.py +628 -0
- superquantx/algorithms/qaoa.py +406 -0
- superquantx/algorithms/quantum_agents.py +1006 -0
- superquantx/algorithms/quantum_kmeans.py +575 -0
- superquantx/algorithms/quantum_nn.py +544 -0
- superquantx/algorithms/quantum_pca.py +499 -0
- superquantx/algorithms/quantum_svm.py +346 -0
- superquantx/algorithms/vqe.py +553 -0
- superquantx/algorithms.py +863 -0
- superquantx/backends/__init__.py +265 -0
- superquantx/backends/base_backend.py +321 -0
- superquantx/backends/braket_backend.py +420 -0
- superquantx/backends/cirq_backend.py +466 -0
- superquantx/backends/ocean_backend.py +491 -0
- superquantx/backends/pennylane_backend.py +419 -0
- superquantx/backends/qiskit_backend.py +451 -0
- superquantx/backends/simulator_backend.py +455 -0
- superquantx/backends/tket_backend.py +519 -0
- superquantx/circuits.py +447 -0
- superquantx/cli/__init__.py +28 -0
- superquantx/cli/commands.py +528 -0
- superquantx/cli/main.py +254 -0
- superquantx/client.py +298 -0
- superquantx/config.py +326 -0
- superquantx/exceptions.py +287 -0
- superquantx/gates.py +588 -0
- superquantx/logging_config.py +347 -0
- superquantx/measurements.py +702 -0
- superquantx/ml.py +936 -0
- superquantx/noise.py +760 -0
- superquantx/utils/__init__.py +83 -0
- superquantx/utils/benchmarking.py +523 -0
- superquantx/utils/classical_utils.py +575 -0
- superquantx/utils/feature_mapping.py +467 -0
- superquantx/utils/optimization.py +410 -0
- superquantx/utils/quantum_utils.py +456 -0
- superquantx/utils/visualization.py +654 -0
- superquantx/version.py +33 -0
- superquantx-0.1.0.dist-info/METADATA +365 -0
- superquantx-0.1.0.dist-info/RECORD +46 -0
- superquantx-0.1.0.dist-info/WHEEL +4 -0
- superquantx-0.1.0.dist-info/entry_points.txt +2 -0
- superquantx-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,654 @@
|
|
1
|
+
"""Visualization utilities for quantum machine learning.
|
2
|
+
|
3
|
+
This module provides functions to visualize quantum circuits, optimization results,
|
4
|
+
quantum states, and other quantum machine learning concepts.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Any, Dict, List, Optional
|
8
|
+
|
9
|
+
import numpy as np
|
10
|
+
|
11
|
+
|
12
|
+
try:
|
13
|
+
import matplotlib.patches as patches
|
14
|
+
import matplotlib.pyplot as plt
|
15
|
+
import seaborn as sns
|
16
|
+
from matplotlib.colors import Normalize
|
17
|
+
HAS_MATPLOTLIB = True
|
18
|
+
except ImportError:
|
19
|
+
HAS_MATPLOTLIB = False
|
20
|
+
|
21
|
+
try:
|
22
|
+
import plotly.express as px
|
23
|
+
import plotly.graph_objects as go
|
24
|
+
from plotly.subplots import make_subplots
|
25
|
+
HAS_PLOTLY = True
|
26
|
+
except ImportError:
|
27
|
+
HAS_PLOTLY = False
|
28
|
+
|
29
|
+
|
30
|
+
def visualize_results(
|
31
|
+
results: Dict[str, Any],
|
32
|
+
plot_type: str = 'optimization',
|
33
|
+
backend: str = 'matplotlib',
|
34
|
+
save_path: Optional[str] = None,
|
35
|
+
**kwargs
|
36
|
+
) -> None:
|
37
|
+
"""Visualize quantum machine learning results.
|
38
|
+
|
39
|
+
Args:
|
40
|
+
results: Results dictionary from algorithm execution
|
41
|
+
plot_type: Type of plot ('optimization', 'classification', 'regression')
|
42
|
+
backend: Plotting backend ('matplotlib' or 'plotly')
|
43
|
+
save_path: Path to save the plot
|
44
|
+
**kwargs: Additional plotting arguments
|
45
|
+
|
46
|
+
"""
|
47
|
+
if backend == 'matplotlib' and not HAS_MATPLOTLIB:
|
48
|
+
raise ImportError("matplotlib is required for matplotlib backend")
|
49
|
+
if backend == 'plotly' and not HAS_PLOTLY:
|
50
|
+
raise ImportError("plotly is required for plotly backend")
|
51
|
+
|
52
|
+
if plot_type == 'optimization':
|
53
|
+
plot_optimization_history(results, backend=backend, save_path=save_path, **kwargs)
|
54
|
+
elif plot_type == 'classification':
|
55
|
+
plot_classification_results(results, backend=backend, save_path=save_path, **kwargs)
|
56
|
+
elif plot_type == 'regression':
|
57
|
+
plot_regression_results(results, backend=backend, save_path=save_path, **kwargs)
|
58
|
+
else:
|
59
|
+
raise ValueError(f"Unknown plot type: {plot_type}")
|
60
|
+
|
61
|
+
|
62
|
+
def plot_optimization_history(
|
63
|
+
results: Dict[str, Any],
|
64
|
+
backend: str = 'matplotlib',
|
65
|
+
save_path: Optional[str] = None,
|
66
|
+
**kwargs
|
67
|
+
) -> None:
|
68
|
+
"""Plot optimization history from algorithm results.
|
69
|
+
|
70
|
+
Args:
|
71
|
+
results: Results containing 'cost_history' or similar
|
72
|
+
backend: Plotting backend
|
73
|
+
save_path: Path to save the plot
|
74
|
+
**kwargs: Additional plotting arguments
|
75
|
+
|
76
|
+
"""
|
77
|
+
# Extract cost history
|
78
|
+
cost_history = None
|
79
|
+
if 'cost_history' in results:
|
80
|
+
cost_history = results['cost_history']
|
81
|
+
elif 'loss_history' in results:
|
82
|
+
cost_history = results['loss_history']
|
83
|
+
elif 'objective_history' in results:
|
84
|
+
cost_history = results['objective_history']
|
85
|
+
|
86
|
+
if cost_history is None:
|
87
|
+
raise ValueError("No optimization history found in results")
|
88
|
+
|
89
|
+
if backend == 'matplotlib':
|
90
|
+
_plot_optimization_matplotlib(cost_history, save_path, **kwargs)
|
91
|
+
elif backend == 'plotly':
|
92
|
+
_plot_optimization_plotly(cost_history, save_path, **kwargs)
|
93
|
+
else:
|
94
|
+
raise ValueError(f"Unknown backend: {backend}")
|
95
|
+
|
96
|
+
|
97
|
+
def plot_circuit(
|
98
|
+
circuit_data: Dict[str, Any],
|
99
|
+
backend: str = 'matplotlib',
|
100
|
+
save_path: Optional[str] = None,
|
101
|
+
**kwargs
|
102
|
+
) -> None:
|
103
|
+
"""Plot quantum circuit diagram.
|
104
|
+
|
105
|
+
Args:
|
106
|
+
circuit_data: Circuit information dictionary
|
107
|
+
backend: Plotting backend
|
108
|
+
save_path: Path to save the plot
|
109
|
+
**kwargs: Additional plotting arguments
|
110
|
+
|
111
|
+
"""
|
112
|
+
if backend == 'matplotlib':
|
113
|
+
_plot_circuit_matplotlib(circuit_data, save_path, **kwargs)
|
114
|
+
elif backend == 'plotly':
|
115
|
+
_plot_circuit_plotly(circuit_data, save_path, **kwargs)
|
116
|
+
else:
|
117
|
+
raise ValueError(f"Unknown backend: {backend}")
|
118
|
+
|
119
|
+
|
120
|
+
def plot_quantum_state(
|
121
|
+
state_vector: np.ndarray,
|
122
|
+
backend: str = 'matplotlib',
|
123
|
+
representation: str = 'bar',
|
124
|
+
save_path: Optional[str] = None,
|
125
|
+
**kwargs
|
126
|
+
) -> None:
|
127
|
+
"""Plot quantum state vector.
|
128
|
+
|
129
|
+
Args:
|
130
|
+
state_vector: Complex quantum state vector
|
131
|
+
backend: Plotting backend
|
132
|
+
representation: How to represent state ('bar', 'phase', 'bloch')
|
133
|
+
save_path: Path to save the plot
|
134
|
+
**kwargs: Additional plotting arguments
|
135
|
+
|
136
|
+
"""
|
137
|
+
if backend == 'matplotlib':
|
138
|
+
_plot_state_matplotlib(state_vector, representation, save_path, **kwargs)
|
139
|
+
elif backend == 'plotly':
|
140
|
+
_plot_state_plotly(state_vector, representation, save_path, **kwargs)
|
141
|
+
else:
|
142
|
+
raise ValueError(f"Unknown backend: {backend}")
|
143
|
+
|
144
|
+
|
145
|
+
def plot_bloch_sphere(
|
146
|
+
state_vector: np.ndarray,
|
147
|
+
backend: str = 'matplotlib',
|
148
|
+
save_path: Optional[str] = None,
|
149
|
+
**kwargs
|
150
|
+
) -> None:
|
151
|
+
"""Plot quantum state on Bloch sphere (for single qubit states).
|
152
|
+
|
153
|
+
Args:
|
154
|
+
state_vector: Single qubit state vector [α, β]
|
155
|
+
backend: Plotting backend
|
156
|
+
save_path: Path to save the plot
|
157
|
+
**kwargs: Additional plotting arguments
|
158
|
+
|
159
|
+
"""
|
160
|
+
if len(state_vector) != 2:
|
161
|
+
raise ValueError("Bloch sphere visualization only supports single qubit states")
|
162
|
+
|
163
|
+
# Convert to Bloch vector
|
164
|
+
bloch_vector = _state_to_bloch_vector(state_vector)
|
165
|
+
|
166
|
+
if backend == 'matplotlib':
|
167
|
+
_plot_bloch_matplotlib(bloch_vector, save_path, **kwargs)
|
168
|
+
elif backend == 'plotly':
|
169
|
+
_plot_bloch_plotly(bloch_vector, save_path, **kwargs)
|
170
|
+
else:
|
171
|
+
raise ValueError(f"Unknown backend: {backend}")
|
172
|
+
|
173
|
+
|
174
|
+
def plot_classification_results(
|
175
|
+
results: Dict[str, Any],
|
176
|
+
backend: str = 'matplotlib',
|
177
|
+
save_path: Optional[str] = None,
|
178
|
+
**kwargs
|
179
|
+
) -> None:
|
180
|
+
"""Plot classification results including confusion matrix and metrics."""
|
181
|
+
if backend == 'matplotlib':
|
182
|
+
_plot_classification_matplotlib(results, save_path, **kwargs)
|
183
|
+
elif backend == 'plotly':
|
184
|
+
_plot_classification_plotly(results, save_path, **kwargs)
|
185
|
+
else:
|
186
|
+
raise ValueError(f"Unknown backend: {backend}")
|
187
|
+
|
188
|
+
|
189
|
+
def plot_regression_results(
|
190
|
+
results: Dict[str, Any],
|
191
|
+
backend: str = 'matplotlib',
|
192
|
+
save_path: Optional[str] = None,
|
193
|
+
**kwargs
|
194
|
+
) -> None:
|
195
|
+
"""Plot regression results including predictions vs actual."""
|
196
|
+
if backend == 'matplotlib':
|
197
|
+
_plot_regression_matplotlib(results, save_path, **kwargs)
|
198
|
+
elif backend == 'plotly':
|
199
|
+
_plot_regression_plotly(results, save_path, **kwargs)
|
200
|
+
else:
|
201
|
+
raise ValueError(f"Unknown backend: {backend}")
|
202
|
+
|
203
|
+
|
204
|
+
# Matplotlib implementations
|
205
|
+
def _plot_optimization_matplotlib(
|
206
|
+
cost_history: List[float],
|
207
|
+
save_path: Optional[str] = None,
|
208
|
+
**kwargs
|
209
|
+
) -> None:
|
210
|
+
"""Plot optimization history using matplotlib."""
|
211
|
+
plt.figure(figsize=kwargs.get('figsize', (10, 6)))
|
212
|
+
plt.plot(cost_history, linewidth=2, color=kwargs.get('color', 'blue'))
|
213
|
+
plt.xlabel('Iteration')
|
214
|
+
plt.ylabel('Cost')
|
215
|
+
plt.title('Optimization History')
|
216
|
+
plt.grid(True, alpha=0.3)
|
217
|
+
|
218
|
+
if save_path:
|
219
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
220
|
+
else:
|
221
|
+
plt.show()
|
222
|
+
|
223
|
+
|
224
|
+
def _plot_circuit_matplotlib(
|
225
|
+
circuit_data: Dict[str, Any],
|
226
|
+
save_path: Optional[str] = None,
|
227
|
+
**kwargs
|
228
|
+
) -> None:
|
229
|
+
"""Plot circuit diagram using matplotlib."""
|
230
|
+
n_qubits = circuit_data.get('n_qubits', 4)
|
231
|
+
gates = circuit_data.get('gates', [])
|
232
|
+
|
233
|
+
fig, ax = plt.subplots(figsize=(12, 2 * n_qubits))
|
234
|
+
|
235
|
+
# Draw qubit lines
|
236
|
+
for i in range(n_qubits):
|
237
|
+
ax.plot([0, 10], [i, i], 'k-', linewidth=2)
|
238
|
+
ax.text(-0.5, i, f'q{i}', ha='right', va='center', fontsize=12)
|
239
|
+
|
240
|
+
# Draw gates (simplified representation)
|
241
|
+
gate_positions = np.linspace(1, 9, len(gates)) if gates else []
|
242
|
+
|
243
|
+
for pos, gate in zip(gate_positions, gates):
|
244
|
+
gate_type = gate.get('type', 'X')
|
245
|
+
qubit = gate.get('qubit', 0)
|
246
|
+
|
247
|
+
# Draw gate box
|
248
|
+
rect = patches.Rectangle(
|
249
|
+
(pos - 0.2, qubit - 0.2),
|
250
|
+
0.4, 0.4,
|
251
|
+
facecolor='lightblue',
|
252
|
+
edgecolor='black'
|
253
|
+
)
|
254
|
+
ax.add_patch(rect)
|
255
|
+
ax.text(pos, qubit, gate_type, ha='center', va='center', fontsize=10)
|
256
|
+
|
257
|
+
ax.set_xlim(-1, 11)
|
258
|
+
ax.set_ylim(-0.5, n_qubits - 0.5)
|
259
|
+
ax.set_aspect('equal')
|
260
|
+
ax.axis('off')
|
261
|
+
ax.set_title('Quantum Circuit')
|
262
|
+
|
263
|
+
if save_path:
|
264
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
265
|
+
else:
|
266
|
+
plt.show()
|
267
|
+
|
268
|
+
|
269
|
+
def _plot_state_matplotlib(
|
270
|
+
state_vector: np.ndarray,
|
271
|
+
representation: str,
|
272
|
+
save_path: Optional[str] = None,
|
273
|
+
**kwargs
|
274
|
+
) -> None:
|
275
|
+
"""Plot quantum state using matplotlib."""
|
276
|
+
n_states = len(state_vector)
|
277
|
+
|
278
|
+
if representation == 'bar':
|
279
|
+
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))
|
280
|
+
|
281
|
+
# Amplitudes
|
282
|
+
amplitudes = np.abs(state_vector)
|
283
|
+
ax1.bar(range(n_states), amplitudes, color='skyblue')
|
284
|
+
ax1.set_xlabel('Basis State')
|
285
|
+
ax1.set_ylabel('Amplitude')
|
286
|
+
ax1.set_title('State Amplitudes')
|
287
|
+
|
288
|
+
# Phases
|
289
|
+
phases = np.angle(state_vector)
|
290
|
+
ax2.bar(range(n_states), phases, color='orange')
|
291
|
+
ax2.set_xlabel('Basis State')
|
292
|
+
ax2.set_ylabel('Phase (radians)')
|
293
|
+
ax2.set_title('State Phases')
|
294
|
+
|
295
|
+
elif representation == 'phase':
|
296
|
+
# Phase-amplitude plot
|
297
|
+
amplitudes = np.abs(state_vector)
|
298
|
+
phases = np.angle(state_vector)
|
299
|
+
|
300
|
+
plt.figure(figsize=(10, 8))
|
301
|
+
scatter = plt.scatter(phases, amplitudes, s=100, alpha=0.7)
|
302
|
+
plt.xlabel('Phase (radians)')
|
303
|
+
plt.ylabel('Amplitude')
|
304
|
+
plt.title('Quantum State (Phase-Amplitude)')
|
305
|
+
|
306
|
+
# Add state labels
|
307
|
+
for i, (phase, amp) in enumerate(zip(phases, amplitudes)):
|
308
|
+
if amp > 0.01: # Only label significant amplitudes
|
309
|
+
plt.annotate(f'|{i}⟩', (phase, amp), xytext=(5, 5),
|
310
|
+
textcoords='offset points')
|
311
|
+
|
312
|
+
if save_path:
|
313
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
314
|
+
else:
|
315
|
+
plt.show()
|
316
|
+
|
317
|
+
|
318
|
+
def _plot_bloch_matplotlib(
|
319
|
+
bloch_vector: np.ndarray,
|
320
|
+
save_path: Optional[str] = None,
|
321
|
+
**kwargs
|
322
|
+
) -> None:
|
323
|
+
"""Plot Bloch sphere using matplotlib."""
|
324
|
+
fig = plt.figure(figsize=(10, 8))
|
325
|
+
ax = fig.add_subplot(111, projection='3d')
|
326
|
+
|
327
|
+
# Draw sphere
|
328
|
+
u = np.linspace(0, 2 * np.pi, 50)
|
329
|
+
v = np.linspace(0, np.pi, 50)
|
330
|
+
x_sphere = np.outer(np.cos(u), np.sin(v))
|
331
|
+
y_sphere = np.outer(np.sin(u), np.sin(v))
|
332
|
+
z_sphere = np.outer(np.ones(np.size(u)), np.cos(v))
|
333
|
+
|
334
|
+
ax.plot_surface(x_sphere, y_sphere, z_sphere, alpha=0.1, color='lightblue')
|
335
|
+
|
336
|
+
# Draw axes
|
337
|
+
ax.plot([0, 1], [0, 0], [0, 0], 'k-', linewidth=2)
|
338
|
+
ax.plot([0, 0], [0, 1], [0, 0], 'k-', linewidth=2)
|
339
|
+
ax.plot([0, 0], [0, 0], [0, 1], 'k-', linewidth=2)
|
340
|
+
|
341
|
+
# Draw state vector
|
342
|
+
x, y, z = bloch_vector
|
343
|
+
ax.quiver(0, 0, 0, x, y, z, color='red', arrow_length_ratio=0.1, linewidth=3)
|
344
|
+
ax.scatter([x], [y], [z], color='red', s=100)
|
345
|
+
|
346
|
+
# Labels
|
347
|
+
ax.text(1.1, 0, 0, 'X')
|
348
|
+
ax.text(0, 1.1, 0, 'Y')
|
349
|
+
ax.text(0, 0, 1.1, 'Z')
|
350
|
+
|
351
|
+
ax.set_xlabel('X')
|
352
|
+
ax.set_ylabel('Y')
|
353
|
+
ax.set_zlabel('Z')
|
354
|
+
ax.set_title('Bloch Sphere')
|
355
|
+
|
356
|
+
if save_path:
|
357
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
358
|
+
else:
|
359
|
+
plt.show()
|
360
|
+
|
361
|
+
|
362
|
+
def _plot_classification_matplotlib(
|
363
|
+
results: Dict[str, Any],
|
364
|
+
save_path: Optional[str] = None,
|
365
|
+
**kwargs
|
366
|
+
) -> None:
|
367
|
+
"""Plot classification results using matplotlib."""
|
368
|
+
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
|
369
|
+
|
370
|
+
# Confusion matrix
|
371
|
+
if 'confusion_matrix' in results:
|
372
|
+
cm = results['confusion_matrix']
|
373
|
+
sns.heatmap(cm, annot=True, fmt='d', ax=axes[0, 0])
|
374
|
+
axes[0, 0].set_title('Confusion Matrix')
|
375
|
+
axes[0, 0].set_xlabel('Predicted')
|
376
|
+
axes[0, 0].set_ylabel('Actual')
|
377
|
+
|
378
|
+
# Training history
|
379
|
+
if 'cost_history' in results:
|
380
|
+
axes[0, 1].plot(results['cost_history'])
|
381
|
+
axes[0, 1].set_title('Training Cost')
|
382
|
+
axes[0, 1].set_xlabel('Iteration')
|
383
|
+
axes[0, 1].set_ylabel('Cost')
|
384
|
+
|
385
|
+
# Accuracy metrics
|
386
|
+
if 'metrics' in results:
|
387
|
+
metrics = results['metrics']
|
388
|
+
metric_names = list(metrics.keys())
|
389
|
+
metric_values = list(metrics.values())
|
390
|
+
|
391
|
+
axes[1, 0].bar(metric_names, metric_values)
|
392
|
+
axes[1, 0].set_title('Performance Metrics')
|
393
|
+
axes[1, 0].set_ylabel('Score')
|
394
|
+
plt.setp(axes[1, 0].xaxis.get_majorticklabels(), rotation=45)
|
395
|
+
|
396
|
+
# Feature importance (if available)
|
397
|
+
if 'feature_importance' in results:
|
398
|
+
importance = results['feature_importance']
|
399
|
+
axes[1, 1].bar(range(len(importance)), importance)
|
400
|
+
axes[1, 1].set_title('Feature Importance')
|
401
|
+
axes[1, 1].set_xlabel('Feature Index')
|
402
|
+
axes[1, 1].set_ylabel('Importance')
|
403
|
+
|
404
|
+
plt.tight_layout()
|
405
|
+
|
406
|
+
if save_path:
|
407
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
408
|
+
else:
|
409
|
+
plt.show()
|
410
|
+
|
411
|
+
|
412
|
+
def _plot_regression_matplotlib(
|
413
|
+
results: Dict[str, Any],
|
414
|
+
save_path: Optional[str] = None,
|
415
|
+
**kwargs
|
416
|
+
) -> None:
|
417
|
+
"""Plot regression results using matplotlib."""
|
418
|
+
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
|
419
|
+
|
420
|
+
# Predictions vs Actual
|
421
|
+
if 'y_pred' in results and 'y_true' in results:
|
422
|
+
y_pred = results['y_pred']
|
423
|
+
y_true = results['y_true']
|
424
|
+
|
425
|
+
axes[0, 0].scatter(y_true, y_pred, alpha=0.6)
|
426
|
+
axes[0, 0].plot([y_true.min(), y_true.max()], [y_true.min(), y_true.max()], 'r--')
|
427
|
+
axes[0, 0].set_xlabel('True Values')
|
428
|
+
axes[0, 0].set_ylabel('Predictions')
|
429
|
+
axes[0, 0].set_title('Predictions vs Actual')
|
430
|
+
|
431
|
+
# Residuals
|
432
|
+
if 'y_pred' in results and 'y_true' in results:
|
433
|
+
residuals = y_true - y_pred
|
434
|
+
axes[0, 1].scatter(y_pred, residuals, alpha=0.6)
|
435
|
+
axes[0, 1].axhline(y=0, color='r', linestyle='--')
|
436
|
+
axes[0, 1].set_xlabel('Predictions')
|
437
|
+
axes[0, 1].set_ylabel('Residuals')
|
438
|
+
axes[0, 1].set_title('Residual Plot')
|
439
|
+
|
440
|
+
# Training history
|
441
|
+
if 'cost_history' in results:
|
442
|
+
axes[1, 0].plot(results['cost_history'])
|
443
|
+
axes[1, 0].set_title('Training Cost')
|
444
|
+
axes[1, 0].set_xlabel('Iteration')
|
445
|
+
axes[1, 0].set_ylabel('Cost')
|
446
|
+
|
447
|
+
# Error metrics
|
448
|
+
if 'metrics' in results:
|
449
|
+
metrics = results['metrics']
|
450
|
+
metric_names = list(metrics.keys())
|
451
|
+
metric_values = list(metrics.values())
|
452
|
+
|
453
|
+
axes[1, 1].bar(metric_names, metric_values)
|
454
|
+
axes[1, 1].set_title('Error Metrics')
|
455
|
+
axes[1, 1].set_ylabel('Error')
|
456
|
+
plt.setp(axes[1, 1].xaxis.get_majorticklabels(), rotation=45)
|
457
|
+
|
458
|
+
plt.tight_layout()
|
459
|
+
|
460
|
+
if save_path:
|
461
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
462
|
+
else:
|
463
|
+
plt.show()
|
464
|
+
|
465
|
+
|
466
|
+
# Plotly implementations (simplified)
|
467
|
+
def _plot_optimization_plotly(
|
468
|
+
cost_history: List[float],
|
469
|
+
save_path: Optional[str] = None,
|
470
|
+
**kwargs
|
471
|
+
) -> None:
|
472
|
+
"""Plot optimization history using plotly."""
|
473
|
+
fig = go.Figure()
|
474
|
+
fig.add_trace(go.Scatter(
|
475
|
+
y=cost_history,
|
476
|
+
mode='lines',
|
477
|
+
name='Cost',
|
478
|
+
line=dict(width=3)
|
479
|
+
))
|
480
|
+
fig.update_layout(
|
481
|
+
title='Optimization History',
|
482
|
+
xaxis_title='Iteration',
|
483
|
+
yaxis_title='Cost'
|
484
|
+
)
|
485
|
+
|
486
|
+
if save_path:
|
487
|
+
fig.write_html(save_path)
|
488
|
+
else:
|
489
|
+
fig.show()
|
490
|
+
|
491
|
+
|
492
|
+
def _plot_circuit_plotly(
|
493
|
+
circuit_data: Dict[str, Any],
|
494
|
+
save_path: Optional[str] = None,
|
495
|
+
**kwargs
|
496
|
+
) -> None:
|
497
|
+
"""Plot circuit using plotly (simplified)."""
|
498
|
+
# This would require more complex implementation
|
499
|
+
# For now, just create a placeholder
|
500
|
+
fig = go.Figure()
|
501
|
+
fig.add_annotation(
|
502
|
+
text="Circuit visualization with Plotly not fully implemented",
|
503
|
+
x=0.5, y=0.5,
|
504
|
+
xref="paper", yref="paper",
|
505
|
+
showarrow=False
|
506
|
+
)
|
507
|
+
|
508
|
+
if save_path:
|
509
|
+
fig.write_html(save_path)
|
510
|
+
else:
|
511
|
+
fig.show()
|
512
|
+
|
513
|
+
|
514
|
+
def _plot_state_plotly(
|
515
|
+
state_vector: np.ndarray,
|
516
|
+
representation: str,
|
517
|
+
save_path: Optional[str] = None,
|
518
|
+
**kwargs
|
519
|
+
) -> None:
|
520
|
+
"""Plot state using plotly."""
|
521
|
+
amplitudes = np.abs(state_vector)
|
522
|
+
phases = np.angle(state_vector)
|
523
|
+
|
524
|
+
fig = make_subplots(rows=2, cols=1,
|
525
|
+
subplot_titles=['Amplitudes', 'Phases'])
|
526
|
+
|
527
|
+
fig.add_trace(go.Bar(y=amplitudes, name='Amplitudes'), row=1, col=1)
|
528
|
+
fig.add_trace(go.Bar(y=phases, name='Phases'), row=2, col=1)
|
529
|
+
|
530
|
+
fig.update_layout(title='Quantum State Vector')
|
531
|
+
|
532
|
+
if save_path:
|
533
|
+
fig.write_html(save_path)
|
534
|
+
else:
|
535
|
+
fig.show()
|
536
|
+
|
537
|
+
|
538
|
+
def _plot_bloch_plotly(
|
539
|
+
bloch_vector: np.ndarray,
|
540
|
+
save_path: Optional[str] = None,
|
541
|
+
**kwargs
|
542
|
+
) -> None:
|
543
|
+
"""Plot Bloch sphere using plotly."""
|
544
|
+
# Create sphere
|
545
|
+
u = np.linspace(0, 2 * np.pi, 20)
|
546
|
+
v = np.linspace(0, np.pi, 20)
|
547
|
+
x_sphere = np.outer(np.cos(u), np.sin(v))
|
548
|
+
y_sphere = np.outer(np.sin(u), np.sin(v))
|
549
|
+
z_sphere = np.outer(np.ones(np.size(u)), np.cos(v))
|
550
|
+
|
551
|
+
fig = go.Figure()
|
552
|
+
|
553
|
+
# Add sphere surface
|
554
|
+
fig.add_trace(go.Surface(
|
555
|
+
x=x_sphere, y=y_sphere, z=z_sphere,
|
556
|
+
opacity=0.1, showscale=False,
|
557
|
+
colorscale=[[0, 'lightblue'], [1, 'lightblue']]
|
558
|
+
))
|
559
|
+
|
560
|
+
# Add state vector
|
561
|
+
x, y, z = bloch_vector
|
562
|
+
fig.add_trace(go.Scatter3d(
|
563
|
+
x=[0, x], y=[0, y], z=[0, z],
|
564
|
+
mode='lines+markers',
|
565
|
+
line=dict(width=5, color='red'),
|
566
|
+
marker=dict(size=8, color='red')
|
567
|
+
))
|
568
|
+
|
569
|
+
fig.update_layout(
|
570
|
+
title='Bloch Sphere',
|
571
|
+
scene=dict(
|
572
|
+
xaxis_title='X',
|
573
|
+
yaxis_title='Y',
|
574
|
+
zaxis_title='Z'
|
575
|
+
)
|
576
|
+
)
|
577
|
+
|
578
|
+
if save_path:
|
579
|
+
fig.write_html(save_path)
|
580
|
+
else:
|
581
|
+
fig.show()
|
582
|
+
|
583
|
+
|
584
|
+
def _plot_classification_plotly(
|
585
|
+
results: Dict[str, Any],
|
586
|
+
save_path: Optional[str] = None,
|
587
|
+
**kwargs
|
588
|
+
) -> None:
|
589
|
+
"""Plot classification results using plotly."""
|
590
|
+
# Simplified implementation
|
591
|
+
fig = make_subplots(rows=2, cols=2)
|
592
|
+
|
593
|
+
if 'cost_history' in results:
|
594
|
+
fig.add_trace(
|
595
|
+
go.Scatter(y=results['cost_history'], name='Cost'),
|
596
|
+
row=1, col=1
|
597
|
+
)
|
598
|
+
|
599
|
+
fig.update_layout(title='Classification Results')
|
600
|
+
|
601
|
+
if save_path:
|
602
|
+
fig.write_html(save_path)
|
603
|
+
else:
|
604
|
+
fig.show()
|
605
|
+
|
606
|
+
|
607
|
+
def _plot_regression_plotly(
|
608
|
+
results: Dict[str, Any],
|
609
|
+
save_path: Optional[str] = None,
|
610
|
+
**kwargs
|
611
|
+
) -> None:
|
612
|
+
"""Plot regression results using plotly."""
|
613
|
+
# Simplified implementation
|
614
|
+
fig = make_subplots(rows=2, cols=2)
|
615
|
+
|
616
|
+
if 'cost_history' in results:
|
617
|
+
fig.add_trace(
|
618
|
+
go.Scatter(y=results['cost_history'], name='Cost'),
|
619
|
+
row=1, col=1
|
620
|
+
)
|
621
|
+
|
622
|
+
if 'y_pred' in results and 'y_true' in results:
|
623
|
+
fig.add_trace(
|
624
|
+
go.Scatter(
|
625
|
+
x=results['y_true'],
|
626
|
+
y=results['y_pred'],
|
627
|
+
mode='markers',
|
628
|
+
name='Predictions vs Actual'
|
629
|
+
),
|
630
|
+
row=1, col=2
|
631
|
+
)
|
632
|
+
|
633
|
+
fig.update_layout(title='Regression Results')
|
634
|
+
|
635
|
+
if save_path:
|
636
|
+
fig.write_html(save_path)
|
637
|
+
else:
|
638
|
+
fig.show()
|
639
|
+
|
640
|
+
|
641
|
+
def _state_to_bloch_vector(state_vector: np.ndarray) -> np.ndarray:
|
642
|
+
"""Convert single qubit state to Bloch vector."""
|
643
|
+
# Normalize state
|
644
|
+
state = state_vector / np.linalg.norm(state_vector)
|
645
|
+
|
646
|
+
# Extract amplitudes
|
647
|
+
alpha, beta = state[0], state[1]
|
648
|
+
|
649
|
+
# Compute Bloch vector components
|
650
|
+
x = 2 * np.real(np.conj(alpha) * beta)
|
651
|
+
y = 2 * np.imag(np.conj(alpha) * beta)
|
652
|
+
z = np.abs(alpha)**2 - np.abs(beta)**2
|
653
|
+
|
654
|
+
return np.array([x, y, z])
|
superquantx/version.py
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
"""Version information for SuperQuantX."""
|
2
|
+
|
3
|
+
__version__ = "0.1.0"
|
4
|
+
__version_info__ = (0, 1, 0)
|
5
|
+
|
6
|
+
# Release information
|
7
|
+
__release_date__ = "2024-09-06"
|
8
|
+
__release_name__ = "Agentic AI Genesis"
|
9
|
+
|
10
|
+
# Build information - will be updated during CI/CD
|
11
|
+
__build__ = "dev"
|
12
|
+
__commit__ = "unknown"
|
13
|
+
|
14
|
+
def get_version_string() -> str:
|
15
|
+
"""Get formatted version string with build info."""
|
16
|
+
version_str = __version__
|
17
|
+
if __build__ != "release":
|
18
|
+
version_str += f"+{__build__}"
|
19
|
+
if __commit__ != "unknown":
|
20
|
+
version_str += f".{__commit__[:8]}"
|
21
|
+
return version_str
|
22
|
+
|
23
|
+
def get_full_version_info() -> dict:
|
24
|
+
"""Get complete version information."""
|
25
|
+
return {
|
26
|
+
"version": __version__,
|
27
|
+
"version_info": __version_info__,
|
28
|
+
"release_date": __release_date__,
|
29
|
+
"release_name": __release_name__,
|
30
|
+
"build": __build__,
|
31
|
+
"commit": __commit__,
|
32
|
+
"full_version": get_version_string(),
|
33
|
+
}
|