superquantx 0.1.0__py3-none-any.whl → 0.1.1__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 +24 -12
- superquantx/algorithms/__init__.py +1 -1
- superquantx/algorithms/base_algorithm.py +36 -36
- superquantx/algorithms/hybrid_classifier.py +22 -22
- superquantx/algorithms/qaoa.py +29 -28
- superquantx/algorithms/quantum_agents.py +57 -56
- superquantx/algorithms/quantum_kmeans.py +17 -17
- superquantx/algorithms/quantum_nn.py +18 -18
- superquantx/algorithms/quantum_pca.py +26 -26
- superquantx/algorithms/quantum_svm.py +26 -25
- superquantx/algorithms/vqe.py +40 -39
- superquantx/algorithms.py +56 -55
- superquantx/backends/__init__.py +12 -12
- superquantx/backends/base_backend.py +25 -24
- superquantx/backends/braket_backend.py +21 -21
- superquantx/backends/cirq_backend.py +26 -26
- superquantx/backends/ocean_backend.py +38 -38
- superquantx/backends/pennylane_backend.py +12 -11
- superquantx/backends/qiskit_backend.py +12 -12
- superquantx/backends/simulator_backend.py +31 -17
- superquantx/backends/tket_backend.py +23 -23
- superquantx/circuits.py +25 -25
- superquantx/cli/commands.py +6 -7
- superquantx/cli/main.py +5 -6
- superquantx/client.py +42 -42
- superquantx/config.py +14 -14
- superquantx/datasets/__init__.py +58 -0
- superquantx/datasets/molecular.py +307 -0
- superquantx/datasets/preprocessing.py +279 -0
- superquantx/datasets/quantum_datasets.py +277 -0
- superquantx/datasets/synthetic.py +300 -0
- superquantx/exceptions.py +29 -29
- superquantx/gates.py +26 -26
- superquantx/logging_config.py +29 -29
- superquantx/measurements.py +53 -54
- superquantx/ml.py +51 -52
- superquantx/noise.py +49 -49
- superquantx/utils/benchmarking.py +41 -36
- superquantx/utils/classical_utils.py +32 -32
- superquantx/utils/feature_mapping.py +40 -35
- superquantx/utils/optimization.py +28 -26
- superquantx/utils/quantum_utils.py +47 -48
- superquantx/utils/visualization.py +49 -49
- superquantx/version.py +3 -3
- {superquantx-0.1.0.dist-info → superquantx-0.1.1.dist-info}/METADATA +18 -16
- superquantx-0.1.1.dist-info/RECORD +51 -0
- superquantx-0.1.1.dist-info/licenses/LICENSE +180 -0
- superquantx-0.1.0.dist-info/RECORD +0 -46
- superquantx-0.1.0.dist-info/licenses/LICENSE +0 -21
- {superquantx-0.1.0.dist-info → superquantx-0.1.1.dist-info}/WHEEL +0 -0
- {superquantx-0.1.0.dist-info → superquantx-0.1.1.dist-info}/entry_points.txt +0 -0
superquantx/measurements.py
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
import json
|
5
5
|
from collections import Counter, defaultdict
|
6
|
-
from typing import Any
|
6
|
+
from typing import Any
|
7
7
|
|
8
8
|
import matplotlib.pyplot as plt
|
9
9
|
import numpy as np
|
@@ -14,10 +14,10 @@ class MeasurementResult(BaseModel):
|
|
14
14
|
"""Represents the result of quantum measurements
|
15
15
|
"""
|
16
16
|
|
17
|
-
counts:
|
17
|
+
counts: dict[str, int] = Field(..., description="Measurement outcome counts")
|
18
18
|
shots: int = Field(..., description="Total number of shots")
|
19
|
-
memory:
|
20
|
-
metadata:
|
19
|
+
memory: list[str] | None = Field(default=None, description="Individual shot outcomes")
|
20
|
+
metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
21
21
|
|
22
22
|
def model_post_init(self, __context):
|
23
23
|
"""Validate measurement result"""
|
@@ -25,21 +25,21 @@ class MeasurementResult(BaseModel):
|
|
25
25
|
raise ValueError("Sum of counts must equal total shots")
|
26
26
|
|
27
27
|
@property
|
28
|
-
def probabilities(self) ->
|
28
|
+
def probabilities(self) -> dict[str, float]:
|
29
29
|
"""Get measurement probabilities"""
|
30
30
|
return {outcome: count / self.shots for outcome, count in self.counts.items()}
|
31
31
|
|
32
32
|
@property
|
33
|
-
def most_frequent(self) ->
|
33
|
+
def most_frequent(self) -> tuple[str, int]:
|
34
34
|
"""Get most frequent measurement outcome"""
|
35
35
|
return max(self.counts.items(), key=lambda x: x[1])
|
36
36
|
|
37
|
-
def marginal_counts(self, qubits:
|
37
|
+
def marginal_counts(self, qubits: list[int]) -> dict[str, int]:
|
38
38
|
"""Get marginal counts for specific qubits
|
39
|
-
|
39
|
+
|
40
40
|
Args:
|
41
41
|
qubits: List of qubit indices to marginalize over
|
42
|
-
|
42
|
+
|
43
43
|
Returns:
|
44
44
|
Marginal counts dictionary
|
45
45
|
|
@@ -55,10 +55,10 @@ class MeasurementResult(BaseModel):
|
|
55
55
|
|
56
56
|
def expectation_value(self, observable: str) -> float:
|
57
57
|
"""Calculate expectation value for Pauli observable
|
58
|
-
|
58
|
+
|
59
59
|
Args:
|
60
60
|
observable: Pauli string (e.g., "ZZI")
|
61
|
-
|
61
|
+
|
62
62
|
Returns:
|
63
63
|
Expectation value
|
64
64
|
|
@@ -94,16 +94,16 @@ class MeasurementResult(BaseModel):
|
|
94
94
|
def plot_histogram(
|
95
95
|
self,
|
96
96
|
title: str = "Measurement Results",
|
97
|
-
figsize:
|
97
|
+
figsize: tuple[int, int] = (10, 6),
|
98
98
|
max_outcomes: int = 20
|
99
99
|
) -> plt.Figure:
|
100
100
|
"""Plot measurement histogram
|
101
|
-
|
101
|
+
|
102
102
|
Args:
|
103
103
|
title: Plot title
|
104
104
|
figsize: Figure size
|
105
105
|
max_outcomes: Maximum number of outcomes to show
|
106
|
-
|
106
|
+
|
107
107
|
Returns:
|
108
108
|
Matplotlib figure
|
109
109
|
|
@@ -117,7 +117,7 @@ class MeasurementResult(BaseModel):
|
|
117
117
|
if len(sorted_outcomes) > max_outcomes:
|
118
118
|
sorted_outcomes = sorted_outcomes[:max_outcomes]
|
119
119
|
|
120
|
-
outcomes, counts = zip(*sorted_outcomes) if sorted_outcomes else ([], [])
|
120
|
+
outcomes, counts = zip(*sorted_outcomes, strict=False) if sorted_outcomes else ([], [])
|
121
121
|
|
122
122
|
ax.bar(range(len(outcomes)), counts)
|
123
123
|
ax.set_xlabel('Measurement Outcome')
|
@@ -129,7 +129,7 @@ class MeasurementResult(BaseModel):
|
|
129
129
|
plt.tight_layout()
|
130
130
|
return fig
|
131
131
|
|
132
|
-
def to_dict(self) ->
|
132
|
+
def to_dict(self) -> dict[str, Any]:
|
133
133
|
"""Convert to dictionary"""
|
134
134
|
return {
|
135
135
|
"counts": self.counts,
|
@@ -143,7 +143,7 @@ class MeasurementResult(BaseModel):
|
|
143
143
|
return json.dumps(self.to_dict(), indent=indent)
|
144
144
|
|
145
145
|
@classmethod
|
146
|
-
def from_dict(cls, data:
|
146
|
+
def from_dict(cls, data: dict[str, Any]) -> "MeasurementResult":
|
147
147
|
"""Create from dictionary"""
|
148
148
|
return cls(**data)
|
149
149
|
|
@@ -176,15 +176,15 @@ class QuantumMeasurement:
|
|
176
176
|
"""Quantum measurement operations and analysis
|
177
177
|
"""
|
178
178
|
|
179
|
-
def __init__(self, backend:
|
179
|
+
def __init__(self, backend: str | None = "simulator"):
|
180
180
|
"""Initialize measurement system
|
181
|
-
|
181
|
+
|
182
182
|
Args:
|
183
183
|
backend: Quantum backend for measurements
|
184
184
|
|
185
185
|
"""
|
186
186
|
self.backend = backend
|
187
|
-
self.measurement_history:
|
187
|
+
self.measurement_history: list[MeasurementResult] = []
|
188
188
|
|
189
189
|
def measure_circuit(
|
190
190
|
self,
|
@@ -193,12 +193,12 @@ class QuantumMeasurement:
|
|
193
193
|
memory: bool = False
|
194
194
|
) -> MeasurementResult:
|
195
195
|
"""Measure quantum circuit
|
196
|
-
|
196
|
+
|
197
197
|
Args:
|
198
198
|
circuit: Quantum circuit to measure
|
199
199
|
shots: Number of measurement shots
|
200
200
|
memory: Whether to store individual shot outcomes
|
201
|
-
|
201
|
+
|
202
202
|
Returns:
|
203
203
|
Measurement result
|
204
204
|
|
@@ -206,7 +206,6 @@ class QuantumMeasurement:
|
|
206
206
|
# This would interface with actual quantum hardware/simulator
|
207
207
|
# For now, create simulated results
|
208
208
|
|
209
|
-
num_classical_bits = circuit.num_classical_bits
|
210
209
|
|
211
210
|
# Simulate measurement outcomes
|
212
211
|
if self.backend == "simulator":
|
@@ -232,7 +231,7 @@ class QuantumMeasurement:
|
|
232
231
|
self.measurement_history.append(result)
|
233
232
|
return result
|
234
233
|
|
235
|
-
def _simulate_measurements(self, circuit: "QuantumCircuit", shots: int) ->
|
234
|
+
def _simulate_measurements(self, circuit: "QuantumCircuit", shots: int) -> dict[str, int]:
|
236
235
|
"""Simulate measurement outcomes"""
|
237
236
|
num_bits = circuit.num_classical_bits
|
238
237
|
|
@@ -245,7 +244,7 @@ class QuantumMeasurement:
|
|
245
244
|
|
246
245
|
return dict(Counter(outcomes))
|
247
246
|
|
248
|
-
def _execute_measurements(self, circuit: "QuantumCircuit", shots: int) ->
|
247
|
+
def _execute_measurements(self, circuit: "QuantumCircuit", shots: int) -> dict[str, int]:
|
249
248
|
"""Execute measurements on quantum hardware"""
|
250
249
|
# This would interface with quantum hardware via client
|
251
250
|
# Placeholder for now
|
@@ -258,12 +257,12 @@ class QuantumMeasurement:
|
|
258
257
|
shots: int = 1024
|
259
258
|
) -> float:
|
260
259
|
"""Measure expectation value of Pauli observable
|
261
|
-
|
260
|
+
|
262
261
|
Args:
|
263
262
|
circuit: Quantum circuit (without measurements)
|
264
263
|
observable: Pauli string observable
|
265
264
|
shots: Number of shots
|
266
|
-
|
265
|
+
|
267
266
|
Returns:
|
268
267
|
Expectation value
|
269
268
|
|
@@ -306,16 +305,16 @@ class QuantumMeasurement:
|
|
306
305
|
def tomography_measurements(
|
307
306
|
self,
|
308
307
|
circuit: "QuantumCircuit",
|
309
|
-
qubits:
|
308
|
+
qubits: list[int] | None = None,
|
310
309
|
shots_per_measurement: int = 1024
|
311
|
-
) ->
|
310
|
+
) -> dict[str, MeasurementResult]:
|
312
311
|
"""Perform quantum state tomography measurements
|
313
|
-
|
312
|
+
|
314
313
|
Args:
|
315
314
|
circuit: Quantum circuit to tomographically reconstruct
|
316
315
|
qubits: Qubits to perform tomography on (default: all)
|
317
316
|
shots_per_measurement: Shots per Pauli measurement
|
318
|
-
|
317
|
+
|
319
318
|
Returns:
|
320
319
|
Dictionary of measurement results for each Pauli basis
|
321
320
|
|
@@ -354,7 +353,7 @@ class QuantumMeasurement:
|
|
354
353
|
self,
|
355
354
|
circuit: "QuantumCircuit",
|
356
355
|
pauli_string: str,
|
357
|
-
qubits:
|
356
|
+
qubits: list[int]
|
358
357
|
) -> "QuantumCircuit":
|
359
358
|
"""Prepare circuit for tomography measurement"""
|
360
359
|
measurement_circuit = circuit.copy()
|
@@ -379,13 +378,13 @@ class QuantumMeasurement:
|
|
379
378
|
|
380
379
|
def reconstruct_state(
|
381
380
|
self,
|
382
|
-
tomography_results:
|
381
|
+
tomography_results: dict[str, MeasurementResult]
|
383
382
|
) -> np.ndarray:
|
384
383
|
"""Reconstruct quantum state from tomography measurements
|
385
|
-
|
384
|
+
|
386
385
|
Args:
|
387
386
|
tomography_results: Results from tomography_measurements
|
388
|
-
|
387
|
+
|
389
388
|
Returns:
|
390
389
|
Reconstructed density matrix
|
391
390
|
|
@@ -410,11 +409,11 @@ class QuantumMeasurement:
|
|
410
409
|
state2: np.ndarray
|
411
410
|
) -> float:
|
412
411
|
"""Calculate quantum state fidelity
|
413
|
-
|
412
|
+
|
414
413
|
Args:
|
415
414
|
state1: First quantum state (vector or density matrix)
|
416
415
|
state2: Second quantum state (vector or density matrix)
|
417
|
-
|
416
|
+
|
418
417
|
Returns:
|
419
418
|
Fidelity between states
|
420
419
|
|
@@ -447,11 +446,11 @@ class QuantumMeasurement:
|
|
447
446
|
state2: np.ndarray
|
448
447
|
) -> float:
|
449
448
|
"""Calculate trace distance between quantum states
|
450
|
-
|
449
|
+
|
451
450
|
Args:
|
452
451
|
state1: First quantum state
|
453
452
|
state2: Second quantum state
|
454
|
-
|
453
|
+
|
455
454
|
Returns:
|
456
455
|
Trace distance
|
457
456
|
|
@@ -478,15 +477,15 @@ class QuantumMeasurement:
|
|
478
477
|
depth: int,
|
479
478
|
trials: int = 100,
|
480
479
|
shots_per_trial: int = 1024
|
481
|
-
) ->
|
480
|
+
) -> dict[str, Any]:
|
482
481
|
"""Perform quantum volume benchmark
|
483
|
-
|
482
|
+
|
484
483
|
Args:
|
485
484
|
num_qubits: Number of qubits
|
486
485
|
depth: Circuit depth
|
487
486
|
trials: Number of random circuits to test
|
488
487
|
shots_per_trial: Shots per circuit
|
489
|
-
|
488
|
+
|
490
489
|
Returns:
|
491
490
|
Quantum volume benchmark results
|
492
491
|
|
@@ -557,13 +556,13 @@ class ResultAnalyzer:
|
|
557
556
|
def compare_results(
|
558
557
|
results1: MeasurementResult,
|
559
558
|
results2: MeasurementResult
|
560
|
-
) ->
|
559
|
+
) -> dict[str, float]:
|
561
560
|
"""Compare two measurement results
|
562
|
-
|
561
|
+
|
563
562
|
Args:
|
564
563
|
results1: First measurement result
|
565
564
|
results2: Second measurement result
|
566
|
-
|
565
|
+
|
567
566
|
Returns:
|
568
567
|
Comparison metrics
|
569
568
|
|
@@ -603,17 +602,17 @@ class ResultAnalyzer:
|
|
603
602
|
|
604
603
|
@staticmethod
|
605
604
|
def error_mitigation_zero_noise_extrapolation(
|
606
|
-
noise_levels:
|
607
|
-
measurement_results:
|
605
|
+
noise_levels: list[float],
|
606
|
+
measurement_results: list[MeasurementResult],
|
608
607
|
observable: str = "Z"
|
609
|
-
) ->
|
608
|
+
) -> tuple[float, dict[str, Any]]:
|
610
609
|
"""Perform zero-noise extrapolation error mitigation
|
611
|
-
|
610
|
+
|
612
611
|
Args:
|
613
612
|
noise_levels: List of noise levels (e.g., [1, 2, 3])
|
614
613
|
measurement_results: Results for each noise level
|
615
614
|
observable: Observable to extrapolate
|
616
|
-
|
615
|
+
|
617
616
|
Returns:
|
618
617
|
Zero-noise extrapolated value and fitting info
|
619
618
|
|
@@ -670,21 +669,21 @@ class ResultAnalyzer:
|
|
670
669
|
|
671
670
|
@staticmethod
|
672
671
|
def readout_error_mitigation(
|
673
|
-
calibration_results:
|
672
|
+
calibration_results: dict[str, MeasurementResult],
|
674
673
|
measurement_result: MeasurementResult
|
675
674
|
) -> MeasurementResult:
|
676
675
|
"""Apply readout error mitigation
|
677
|
-
|
676
|
+
|
678
677
|
Args:
|
679
678
|
calibration_results: Results from measuring |0⟩ and |1⟩ states
|
680
679
|
measurement_result: Result to correct
|
681
|
-
|
680
|
+
|
682
681
|
Returns:
|
683
682
|
Error-mitigated result
|
684
683
|
|
685
684
|
"""
|
686
685
|
# Build calibration matrix
|
687
|
-
|
686
|
+
len(next(iter(calibration_results.keys())))
|
688
687
|
|
689
688
|
# This is a simplified implementation
|
690
689
|
# Full readout error mitigation would build complete confusion matrix
|
superquantx/ml.py
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
"""
|
3
3
|
|
4
4
|
from abc import ABC, abstractmethod
|
5
|
-
from typing import Dict, List, Optional
|
6
5
|
|
7
6
|
import numpy as np
|
8
7
|
from scipy.optimize import minimize
|
@@ -20,7 +19,7 @@ class QuantumFeatureMap(ABC):
|
|
20
19
|
|
21
20
|
def __init__(self, num_qubits: int, num_features: int):
|
22
21
|
"""Initialize feature map
|
23
|
-
|
22
|
+
|
24
23
|
Args:
|
25
24
|
num_qubits: Number of qubits
|
26
25
|
num_features: Number of input features
|
@@ -32,10 +31,10 @@ class QuantumFeatureMap(ABC):
|
|
32
31
|
@abstractmethod
|
33
32
|
def map_features(self, x: np.ndarray) -> QuantumCircuit:
|
34
33
|
"""Map classical features to quantum state
|
35
|
-
|
34
|
+
|
36
35
|
Args:
|
37
36
|
x: Feature vector
|
38
|
-
|
37
|
+
|
39
38
|
Returns:
|
40
39
|
Quantum circuit encoding the features
|
41
40
|
|
@@ -51,10 +50,10 @@ class AngleEmbeddingFeatureMap(QuantumFeatureMap):
|
|
51
50
|
self,
|
52
51
|
num_qubits: int,
|
53
52
|
num_features: int,
|
54
|
-
rotation_gates:
|
53
|
+
rotation_gates: list[str] = None
|
55
54
|
):
|
56
55
|
"""Initialize angle embedding
|
57
|
-
|
56
|
+
|
58
57
|
Args:
|
59
58
|
num_qubits: Number of qubits
|
60
59
|
num_features: Number of features
|
@@ -117,7 +116,7 @@ class IQPFeatureMap(QuantumFeatureMap):
|
|
117
116
|
|
118
117
|
def __init__(self, num_qubits: int, num_features: int, degree: int = 2):
|
119
118
|
"""Initialize IQP feature map
|
120
|
-
|
119
|
+
|
121
120
|
Args:
|
122
121
|
num_qubits: Number of qubits
|
123
122
|
num_features: Number of features
|
@@ -158,10 +157,10 @@ class QuantumKernel:
|
|
158
157
|
def __init__(
|
159
158
|
self,
|
160
159
|
feature_map: QuantumFeatureMap,
|
161
|
-
client:
|
160
|
+
client: SuperQuantXClient | None = None
|
162
161
|
):
|
163
162
|
"""Initialize quantum kernel
|
164
|
-
|
163
|
+
|
165
164
|
Args:
|
166
165
|
feature_map: Quantum feature map
|
167
166
|
client: SuperQuantX client for execution
|
@@ -172,11 +171,11 @@ class QuantumKernel:
|
|
172
171
|
|
173
172
|
def kernel_matrix(self, X1: np.ndarray, X2: np.ndarray = None) -> np.ndarray:
|
174
173
|
"""Compute quantum kernel matrix
|
175
|
-
|
174
|
+
|
176
175
|
Args:
|
177
176
|
X1: First set of data points
|
178
177
|
X2: Second set of data points (default: same as X1)
|
179
|
-
|
178
|
+
|
180
179
|
Returns:
|
181
180
|
Kernel matrix K[i,j] = ⟨φ(x_i)|φ(x_j)⟩
|
182
181
|
|
@@ -194,11 +193,11 @@ class QuantumKernel:
|
|
194
193
|
|
195
194
|
def _kernel_value(self, x1: np.ndarray, x2: np.ndarray) -> float:
|
196
195
|
"""Compute kernel value between two data points
|
197
|
-
|
196
|
+
|
198
197
|
Args:
|
199
198
|
x1: First data point
|
200
199
|
x2: Second data point
|
201
|
-
|
200
|
+
|
202
201
|
Returns:
|
203
202
|
Kernel value ⟨φ(x1)|φ(x2)⟩
|
204
203
|
|
@@ -260,7 +259,7 @@ class QuantumKernel:
|
|
260
259
|
|
261
260
|
return kernel_circuit
|
262
261
|
|
263
|
-
def _inverse_gate(self, gate: QuantumGate, mapped_qubits:
|
262
|
+
def _inverse_gate(self, gate: QuantumGate, mapped_qubits: list[int]) -> QuantumGate:
|
264
263
|
"""Create inverse gate with mapped qubits"""
|
265
264
|
# Simplified inverse gate creation
|
266
265
|
inverse_params = [-p for p in gate.parameters] if gate.parameters else []
|
@@ -305,7 +304,7 @@ class QuantumSVM(BaseEstimator, ClassifierMixin):
|
|
305
304
|
C: float = 1.0
|
306
305
|
):
|
307
306
|
"""Initialize Quantum SVM
|
308
|
-
|
307
|
+
|
309
308
|
Args:
|
310
309
|
quantum_kernel: Quantum kernel for classification
|
311
310
|
C: Regularization parameter
|
@@ -316,19 +315,19 @@ class QuantumSVM(BaseEstimator, ClassifierMixin):
|
|
316
315
|
self.is_fitted_ = False
|
317
316
|
|
318
317
|
# Will be set during training
|
319
|
-
self.support_vectors_:
|
320
|
-
self.support_:
|
321
|
-
self.alpha_:
|
322
|
-
self.intercept_:
|
323
|
-
self.classes_:
|
318
|
+
self.support_vectors_: np.ndarray | None = None
|
319
|
+
self.support_: np.ndarray | None = None
|
320
|
+
self.alpha_: np.ndarray | None = None
|
321
|
+
self.intercept_: float | None = None
|
322
|
+
self.classes_: np.ndarray | None = None
|
324
323
|
|
325
324
|
def fit(self, X: np.ndarray, y: np.ndarray) -> "QuantumSVM":
|
326
325
|
"""Fit Quantum SVM
|
327
|
-
|
326
|
+
|
328
327
|
Args:
|
329
328
|
X: Training data
|
330
329
|
y: Training labels
|
331
|
-
|
330
|
+
|
332
331
|
Returns:
|
333
332
|
Fitted model
|
334
333
|
|
@@ -411,10 +410,10 @@ class QuantumSVM(BaseEstimator, ClassifierMixin):
|
|
411
410
|
|
412
411
|
def decision_function(self, X: np.ndarray) -> np.ndarray:
|
413
412
|
"""Compute decision function
|
414
|
-
|
413
|
+
|
415
414
|
Args:
|
416
415
|
X: Input data
|
417
|
-
|
416
|
+
|
418
417
|
Returns:
|
419
418
|
Decision function values
|
420
419
|
|
@@ -444,10 +443,10 @@ class QuantumSVM(BaseEstimator, ClassifierMixin):
|
|
444
443
|
|
445
444
|
def predict(self, X: np.ndarray) -> np.ndarray:
|
446
445
|
"""Make predictions
|
447
|
-
|
446
|
+
|
448
447
|
Args:
|
449
448
|
X: Input data
|
450
|
-
|
449
|
+
|
451
450
|
Returns:
|
452
451
|
Predicted labels
|
453
452
|
|
@@ -467,12 +466,12 @@ class QuantumClassifier(BaseEstimator, ClassifierMixin):
|
|
467
466
|
self,
|
468
467
|
feature_map: QuantumFeatureMap,
|
469
468
|
ansatz_layers: int = 2,
|
470
|
-
client:
|
469
|
+
client: SuperQuantXClient | None = None,
|
471
470
|
optimizer: str = "SLSQP",
|
472
471
|
max_iter: int = 1000
|
473
472
|
):
|
474
473
|
"""Initialize quantum classifier
|
475
|
-
|
474
|
+
|
476
475
|
Args:
|
477
476
|
feature_map: Quantum feature map
|
478
477
|
ansatz_layers: Number of variational layers
|
@@ -488,8 +487,8 @@ class QuantumClassifier(BaseEstimator, ClassifierMixin):
|
|
488
487
|
self.max_iter = max_iter
|
489
488
|
|
490
489
|
self.is_fitted_ = False
|
491
|
-
self.parameters_:
|
492
|
-
self.classes_:
|
490
|
+
self.parameters_: np.ndarray | None = None
|
491
|
+
self.classes_: np.ndarray | None = None
|
493
492
|
self.label_encoder_ = LabelEncoder()
|
494
493
|
|
495
494
|
def _create_circuit(self, x: np.ndarray, parameters: np.ndarray) -> QuantumCircuit:
|
@@ -581,11 +580,11 @@ class QuantumClassifier(BaseEstimator, ClassifierMixin):
|
|
581
580
|
|
582
581
|
def fit(self, X: np.ndarray, y: np.ndarray) -> "QuantumClassifier":
|
583
582
|
"""Fit quantum classifier
|
584
|
-
|
583
|
+
|
585
584
|
Args:
|
586
585
|
X: Training data
|
587
586
|
y: Training labels
|
588
|
-
|
587
|
+
|
589
588
|
Returns:
|
590
589
|
Fitted model
|
591
590
|
|
@@ -613,10 +612,10 @@ class QuantumClassifier(BaseEstimator, ClassifierMixin):
|
|
613
612
|
|
614
613
|
def predict_proba(self, X: np.ndarray) -> np.ndarray:
|
615
614
|
"""Predict class probabilities
|
616
|
-
|
615
|
+
|
617
616
|
Args:
|
618
617
|
X: Input data
|
619
|
-
|
618
|
+
|
620
619
|
Returns:
|
621
620
|
Class probabilities
|
622
621
|
|
@@ -628,10 +627,10 @@ class QuantumClassifier(BaseEstimator, ClassifierMixin):
|
|
628
627
|
|
629
628
|
def predict(self, X: np.ndarray) -> np.ndarray:
|
630
629
|
"""Make predictions
|
631
|
-
|
630
|
+
|
632
631
|
Args:
|
633
632
|
X: Input data
|
634
|
-
|
633
|
+
|
635
634
|
Returns:
|
636
635
|
Predicted labels
|
637
636
|
|
@@ -649,11 +648,11 @@ class QuantumRegressor(BaseEstimator, RegressorMixin):
|
|
649
648
|
self,
|
650
649
|
feature_map: QuantumFeatureMap,
|
651
650
|
ansatz_layers: int = 2,
|
652
|
-
client:
|
651
|
+
client: SuperQuantXClient | None = None,
|
653
652
|
optimizer: str = "SLSQP"
|
654
653
|
):
|
655
654
|
"""Initialize quantum regressor
|
656
|
-
|
655
|
+
|
657
656
|
Args:
|
658
657
|
feature_map: Quantum feature map
|
659
658
|
ansatz_layers: Number of variational layers
|
@@ -667,7 +666,7 @@ class QuantumRegressor(BaseEstimator, RegressorMixin):
|
|
667
666
|
self.optimizer = optimizer
|
668
667
|
|
669
668
|
self.is_fitted_ = False
|
670
|
-
self.parameters_:
|
669
|
+
self.parameters_: np.ndarray | None = None
|
671
670
|
self.scaler_ = StandardScaler()
|
672
671
|
|
673
672
|
def _create_circuit(self, x: np.ndarray, parameters: np.ndarray) -> QuantumCircuit:
|
@@ -720,11 +719,11 @@ class QuantumRegressor(BaseEstimator, RegressorMixin):
|
|
720
719
|
|
721
720
|
def fit(self, X: np.ndarray, y: np.ndarray) -> "QuantumRegressor":
|
722
721
|
"""Fit quantum regressor
|
723
|
-
|
722
|
+
|
724
723
|
Args:
|
725
724
|
X: Training data
|
726
725
|
y: Training targets
|
727
|
-
|
726
|
+
|
728
727
|
Returns:
|
729
728
|
Fitted model
|
730
729
|
|
@@ -755,10 +754,10 @@ class QuantumRegressor(BaseEstimator, RegressorMixin):
|
|
755
754
|
|
756
755
|
def predict(self, X: np.ndarray) -> np.ndarray:
|
757
756
|
"""Make predictions
|
758
|
-
|
757
|
+
|
759
758
|
Args:
|
760
759
|
X: Input data
|
761
|
-
|
760
|
+
|
762
761
|
Returns:
|
763
762
|
Predicted values
|
764
763
|
|
@@ -783,10 +782,10 @@ class QuantumGAN:
|
|
783
782
|
num_qubits: int,
|
784
783
|
generator_layers: int = 3,
|
785
784
|
discriminator_layers: int = 2,
|
786
|
-
client:
|
785
|
+
client: SuperQuantXClient | None = None
|
787
786
|
):
|
788
787
|
"""Initialize Quantum GAN
|
789
|
-
|
788
|
+
|
790
789
|
Args:
|
791
790
|
num_qubits: Number of qubits
|
792
791
|
generator_layers: Generator circuit depth
|
@@ -800,8 +799,8 @@ class QuantumGAN:
|
|
800
799
|
self.client = client
|
801
800
|
|
802
801
|
# Parameters will be set during training
|
803
|
-
self.generator_params:
|
804
|
-
self.discriminator_params:
|
802
|
+
self.generator_params: np.ndarray | None = None
|
803
|
+
self.discriminator_params: np.ndarray | None = None
|
805
804
|
|
806
805
|
def create_generator(self, noise: np.ndarray, params: np.ndarray) -> QuantumCircuit:
|
807
806
|
"""Create generator circuit"""
|
@@ -858,14 +857,14 @@ class QuantumGAN:
|
|
858
857
|
training_data: np.ndarray,
|
859
858
|
num_epochs: int = 100,
|
860
859
|
learning_rate: float = 0.01
|
861
|
-
) ->
|
860
|
+
) -> dict[str, list[float]]:
|
862
861
|
"""Train Quantum GAN
|
863
|
-
|
862
|
+
|
864
863
|
Args:
|
865
864
|
training_data: Real training data
|
866
865
|
num_epochs: Number of training epochs
|
867
866
|
learning_rate: Learning rate
|
868
|
-
|
867
|
+
|
869
868
|
Returns:
|
870
869
|
Training history
|
871
870
|
|
@@ -918,7 +917,7 @@ class QuantumGAN:
|
|
918
917
|
|
919
918
|
return circuit
|
920
919
|
|
921
|
-
def generate_samples(self, num_samples: int) ->
|
920
|
+
def generate_samples(self, num_samples: int) -> list[np.ndarray]:
|
922
921
|
"""Generate samples using trained generator"""
|
923
922
|
if self.generator_params is None:
|
924
923
|
raise ValueError("GAN must be trained before generating samples")
|
@@ -926,7 +925,7 @@ class QuantumGAN:
|
|
926
925
|
samples = []
|
927
926
|
for _ in range(num_samples):
|
928
927
|
noise = np.random.uniform(0, 2*np.pi, self.num_qubits)
|
929
|
-
|
928
|
+
self.create_generator(noise, self.generator_params)
|
930
929
|
|
931
930
|
# Extract generated sample (simplified)
|
932
931
|
# Would measure and extract amplitudes in practice
|