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
@@ -7,7 +7,7 @@ including cross-validation, hyperparameter search, and model selection.
|
|
7
7
|
import itertools
|
8
8
|
import time
|
9
9
|
from dataclasses import dataclass
|
10
|
-
from typing import Any
|
10
|
+
from typing import Any
|
11
11
|
|
12
12
|
import numpy as np
|
13
13
|
from sklearn.metrics import accuracy_score, mean_squared_error
|
@@ -18,12 +18,12 @@ from sklearn.model_selection import KFold, StratifiedKFold, train_test_split
|
|
18
18
|
class CrossValidationResult:
|
19
19
|
"""Results from cross-validation."""
|
20
20
|
|
21
|
-
scores:
|
21
|
+
scores: list[float]
|
22
22
|
mean_score: float
|
23
23
|
std_score: float
|
24
|
-
fold_times:
|
24
|
+
fold_times: list[float]
|
25
25
|
mean_time: float
|
26
|
-
best_params:
|
26
|
+
best_params: dict[str, Any] | None = None
|
27
27
|
|
28
28
|
|
29
29
|
def cross_validation(
|
@@ -33,11 +33,11 @@ def cross_validation(
|
|
33
33
|
cv_folds: int = 5,
|
34
34
|
scoring: str = 'accuracy',
|
35
35
|
stratify: bool = True,
|
36
|
-
random_state:
|
36
|
+
random_state: int | None = 42,
|
37
37
|
verbose: bool = False
|
38
38
|
) -> CrossValidationResult:
|
39
39
|
"""Perform k-fold cross-validation on quantum algorithm.
|
40
|
-
|
40
|
+
|
41
41
|
Args:
|
42
42
|
algorithm: Quantum algorithm instance
|
43
43
|
X: Feature matrix
|
@@ -47,12 +47,12 @@ def cross_validation(
|
|
47
47
|
stratify: Whether to use stratified CV for classification
|
48
48
|
random_state: Random seed
|
49
49
|
verbose: Whether to print progress
|
50
|
-
|
50
|
+
|
51
51
|
Returns:
|
52
52
|
CrossValidationResult with scores and timing info
|
53
53
|
|
54
54
|
"""
|
55
|
-
|
55
|
+
len(X)
|
56
56
|
|
57
57
|
# Choose cross-validation strategy
|
58
58
|
if stratify and _is_classification_task(y):
|
@@ -107,17 +107,17 @@ def cross_validation(
|
|
107
107
|
|
108
108
|
def hyperparameter_search(
|
109
109
|
algorithm_class: type,
|
110
|
-
param_grid:
|
110
|
+
param_grid: dict[str, list[Any]],
|
111
111
|
X: np.ndarray,
|
112
112
|
y: np.ndarray,
|
113
113
|
cv_folds: int = 3,
|
114
114
|
scoring: str = 'accuracy',
|
115
115
|
n_jobs: int = 1,
|
116
|
-
random_state:
|
116
|
+
random_state: int | None = 42,
|
117
117
|
verbose: bool = False
|
118
|
-
) ->
|
118
|
+
) -> dict[str, Any]:
|
119
119
|
"""Perform grid search for hyperparameter optimization.
|
120
|
-
|
120
|
+
|
121
121
|
Args:
|
122
122
|
algorithm_class: Quantum algorithm class
|
123
123
|
param_grid: Dictionary of parameter names and values to try
|
@@ -128,7 +128,7 @@ def hyperparameter_search(
|
|
128
128
|
n_jobs: Number of parallel jobs (not implemented)
|
129
129
|
random_state: Random seed
|
130
130
|
verbose: Whether to print progress
|
131
|
-
|
131
|
+
|
132
132
|
Returns:
|
133
133
|
Dictionary with best parameters and results
|
134
134
|
|
@@ -147,7 +147,7 @@ def hyperparameter_search(
|
|
147
147
|
|
148
148
|
for i, param_values in enumerate(param_combinations):
|
149
149
|
# Create parameter dictionary
|
150
|
-
params = dict(zip(param_names, param_values))
|
150
|
+
params = dict(zip(param_names, param_values, strict=False))
|
151
151
|
|
152
152
|
if verbose:
|
153
153
|
print(f"Combination {i+1}/{len(param_combinations)}: {params}")
|
@@ -204,17 +204,17 @@ def hyperparameter_search(
|
|
204
204
|
|
205
205
|
|
206
206
|
def model_selection(
|
207
|
-
algorithms:
|
207
|
+
algorithms: list[tuple[str, type, dict[str, Any]]],
|
208
208
|
X: np.ndarray,
|
209
209
|
y: np.ndarray,
|
210
210
|
cv_folds: int = 5,
|
211
211
|
scoring: str = 'accuracy',
|
212
212
|
test_size: float = 0.2,
|
213
|
-
random_state:
|
213
|
+
random_state: int | None = 42,
|
214
214
|
verbose: bool = False
|
215
|
-
) ->
|
215
|
+
) -> dict[str, Any]:
|
216
216
|
"""Compare multiple algorithms and select the best one.
|
217
|
-
|
217
|
+
|
218
218
|
Args:
|
219
219
|
algorithms: List of (name, class, params) tuples
|
220
220
|
X: Feature matrix
|
@@ -224,7 +224,7 @@ def model_selection(
|
|
224
224
|
test_size: Proportion for test set
|
225
225
|
random_state: Random seed
|
226
226
|
verbose: Whether to print progress
|
227
|
-
|
227
|
+
|
228
228
|
Returns:
|
229
229
|
Dictionary with model selection results
|
230
230
|
|
@@ -311,10 +311,10 @@ def data_splitting(
|
|
311
311
|
val_size: float = 0.15,
|
312
312
|
test_size: float = 0.15,
|
313
313
|
stratify: bool = True,
|
314
|
-
random_state:
|
315
|
-
) ->
|
314
|
+
random_state: int | None = 42
|
315
|
+
) -> tuple[np.ndarray, ...]:
|
316
316
|
"""Split data into train, validation, and test sets.
|
317
|
-
|
317
|
+
|
318
318
|
Args:
|
319
319
|
X: Feature matrix
|
320
320
|
y: Target vector
|
@@ -323,7 +323,7 @@ def data_splitting(
|
|
323
323
|
test_size: Proportion for testing
|
324
324
|
stratify: Whether to stratify splits for classification
|
325
325
|
random_state: Random seed
|
326
|
-
|
326
|
+
|
327
327
|
Returns:
|
328
328
|
Tuple of (X_train, X_val, X_test, y_train, y_val, y_test)
|
329
329
|
|
@@ -355,14 +355,14 @@ def learning_curve_analysis(
|
|
355
355
|
algorithm: Any,
|
356
356
|
X: np.ndarray,
|
357
357
|
y: np.ndarray,
|
358
|
-
train_sizes:
|
358
|
+
train_sizes: list[float] | None = None,
|
359
359
|
cv_folds: int = 5,
|
360
360
|
scoring: str = 'accuracy',
|
361
|
-
random_state:
|
361
|
+
random_state: int | None = 42,
|
362
362
|
verbose: bool = False
|
363
|
-
) ->
|
363
|
+
) -> dict[str, Any]:
|
364
364
|
"""Analyze learning curve by varying training set size.
|
365
|
-
|
365
|
+
|
366
366
|
Args:
|
367
367
|
algorithm: Quantum algorithm instance
|
368
368
|
X: Feature matrix
|
@@ -372,7 +372,7 @@ def learning_curve_analysis(
|
|
372
372
|
scoring: Scoring metric
|
373
373
|
random_state: Random seed
|
374
374
|
verbose: Whether to print progress
|
375
|
-
|
375
|
+
|
376
376
|
Returns:
|
377
377
|
Learning curve analysis results
|
378
378
|
|
@@ -438,10 +438,10 @@ def feature_importance_analysis(
|
|
438
438
|
method: str = 'permutation',
|
439
439
|
n_repeats: int = 10,
|
440
440
|
scoring: str = 'accuracy',
|
441
|
-
random_state:
|
441
|
+
random_state: int | None = 42
|
442
442
|
) -> np.ndarray:
|
443
443
|
"""Analyze feature importance using permutation or other methods.
|
444
|
-
|
444
|
+
|
445
445
|
Args:
|
446
446
|
algorithm: Fitted quantum algorithm
|
447
447
|
X: Feature matrix
|
@@ -450,7 +450,7 @@ def feature_importance_analysis(
|
|
450
450
|
n_repeats: Number of permutation repeats
|
451
451
|
scoring: Scoring metric
|
452
452
|
random_state: Random seed
|
453
|
-
|
453
|
+
|
454
454
|
Returns:
|
455
455
|
Feature importance scores
|
456
456
|
|
@@ -471,7 +471,7 @@ def _permutation_importance(
|
|
471
471
|
y: np.ndarray,
|
472
472
|
n_repeats: int,
|
473
473
|
scoring: str,
|
474
|
-
random_state:
|
474
|
+
random_state: int | None
|
475
475
|
) -> np.ndarray:
|
476
476
|
"""Calculate permutation feature importance."""
|
477
477
|
# Baseline score
|
@@ -5,8 +5,9 @@ which encode classical data into quantum states for machine learning algorithms.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
from abc import ABC, abstractmethod
|
8
|
+
from collections.abc import Callable
|
8
9
|
from dataclasses import dataclass
|
9
|
-
from typing import Any
|
10
|
+
from typing import Any
|
10
11
|
|
11
12
|
import numpy as np
|
12
13
|
|
@@ -21,12 +22,12 @@ class FeatureMapConfig:
|
|
21
22
|
entanglement: str = 'full'
|
22
23
|
parameter_prefix: str = 'x'
|
23
24
|
insert_barriers: bool = False
|
24
|
-
data_map_func:
|
25
|
+
data_map_func: Callable | None = None
|
25
26
|
|
26
27
|
|
27
28
|
class QuantumFeatureMap(ABC):
|
28
29
|
"""Abstract base class for quantum feature maps.
|
29
|
-
|
30
|
+
|
30
31
|
Feature maps encode classical data into quantum states by applying
|
31
32
|
parameterized quantum gates based on the input features.
|
32
33
|
"""
|
@@ -46,16 +47,16 @@ class QuantumFeatureMap(ABC):
|
|
46
47
|
self._parameters = []
|
47
48
|
|
48
49
|
@abstractmethod
|
49
|
-
def _build_circuit(self, parameters: np.ndarray) ->
|
50
|
+
def _build_circuit(self, parameters: np.ndarray) -> dict[str, Any]:
|
50
51
|
"""Build the quantum circuit for the feature map."""
|
51
52
|
pass
|
52
53
|
|
53
|
-
def map_data_point(self, x: np.ndarray) ->
|
54
|
+
def map_data_point(self, x: np.ndarray) -> dict[str, Any]:
|
54
55
|
"""Map a single data point to quantum circuit parameters.
|
55
|
-
|
56
|
+
|
56
57
|
Args:
|
57
58
|
x: Input data point of length n_features
|
58
|
-
|
59
|
+
|
59
60
|
Returns:
|
60
61
|
Circuit representation with parameters
|
61
62
|
|
@@ -68,12 +69,12 @@ class QuantumFeatureMap(ABC):
|
|
68
69
|
|
69
70
|
return self._build_circuit(parameters)
|
70
71
|
|
71
|
-
def map_data(self, X: np.ndarray) ->
|
72
|
+
def map_data(self, X: np.ndarray) -> list[dict[str, Any]]:
|
72
73
|
"""Map multiple data points to quantum circuits.
|
73
|
-
|
74
|
+
|
74
75
|
Args:
|
75
76
|
X: Input data of shape (n_samples, n_features)
|
76
|
-
|
77
|
+
|
77
78
|
Returns:
|
78
79
|
List of circuit representations
|
79
80
|
|
@@ -88,7 +89,7 @@ class QuantumFeatureMap(ABC):
|
|
88
89
|
|
89
90
|
class ZFeatureMap(QuantumFeatureMap):
|
90
91
|
"""Z-axis rotation feature map.
|
91
|
-
|
92
|
+
|
92
93
|
This feature map applies RZ rotations to encode features:
|
93
94
|
RZ(2 * x_i) for each feature x_i
|
94
95
|
"""
|
@@ -101,7 +102,7 @@ class ZFeatureMap(QuantumFeatureMap):
|
|
101
102
|
):
|
102
103
|
super().__init__(n_features, reps, 'none', parameter_prefix)
|
103
104
|
|
104
|
-
def _build_circuit(self, parameters: np.ndarray) ->
|
105
|
+
def _build_circuit(self, parameters: np.ndarray) -> dict[str, Any]:
|
105
106
|
"""Build Z feature map circuit."""
|
106
107
|
gates = []
|
107
108
|
|
@@ -125,9 +126,9 @@ class ZFeatureMap(QuantumFeatureMap):
|
|
125
126
|
|
126
127
|
class ZZFeatureMap(QuantumFeatureMap):
|
127
128
|
"""ZZ entangling feature map.
|
128
|
-
|
129
|
+
|
129
130
|
This feature map uses both single-qubit Z rotations and two-qubit ZZ interactions:
|
130
|
-
- Single qubit: RZ(2 * x_i)
|
131
|
+
- Single qubit: RZ(2 * x_i)
|
131
132
|
- Two qubit: RZZ(2 * x_i * x_j) for entangled qubits
|
132
133
|
"""
|
133
134
|
|
@@ -142,7 +143,7 @@ class ZZFeatureMap(QuantumFeatureMap):
|
|
142
143
|
super().__init__(n_features, reps, entanglement, parameter_prefix)
|
143
144
|
self.alpha = alpha
|
144
145
|
|
145
|
-
def _build_circuit(self, parameters: np.ndarray) ->
|
146
|
+
def _build_circuit(self, parameters: np.ndarray) -> dict[str, Any]:
|
146
147
|
"""Build ZZ feature map circuit."""
|
147
148
|
gates = []
|
148
149
|
|
@@ -180,7 +181,7 @@ class ZZFeatureMap(QuantumFeatureMap):
|
|
180
181
|
'entanglement': self.entanglement
|
181
182
|
}
|
182
183
|
|
183
|
-
def _get_entangling_pairs(self) ->
|
184
|
+
def _get_entangling_pairs(self) -> list[tuple[int, int]]:
|
184
185
|
"""Get pairs of qubits for entangling gates."""
|
185
186
|
pairs = []
|
186
187
|
|
@@ -211,7 +212,7 @@ class ZZFeatureMap(QuantumFeatureMap):
|
|
211
212
|
|
212
213
|
class PauliFeatureMap(QuantumFeatureMap):
|
213
214
|
"""Pauli feature map with arbitrary Pauli strings.
|
214
|
-
|
215
|
+
|
215
216
|
This feature map applies rotations based on Pauli operators:
|
216
217
|
exp(i * alpha * phi * P) where P is a Pauli string and phi is the feature value.
|
217
218
|
"""
|
@@ -220,16 +221,18 @@ class PauliFeatureMap(QuantumFeatureMap):
|
|
220
221
|
self,
|
221
222
|
n_features: int,
|
222
223
|
reps: int = 1,
|
223
|
-
paulis:
|
224
|
+
paulis: list[str] = None,
|
224
225
|
entanglement: str = 'full',
|
225
226
|
alpha: float = 2.0,
|
226
227
|
parameter_prefix: str = 'x'
|
227
228
|
):
|
229
|
+
if paulis is None:
|
230
|
+
paulis = ['Z', 'ZZ']
|
228
231
|
super().__init__(n_features, reps, entanglement, parameter_prefix)
|
229
232
|
self.paulis = paulis
|
230
233
|
self.alpha = alpha
|
231
234
|
|
232
|
-
def _build_circuit(self, parameters: np.ndarray) ->
|
235
|
+
def _build_circuit(self, parameters: np.ndarray) -> dict[str, Any]:
|
233
236
|
"""Build Pauli feature map circuit."""
|
234
237
|
gates = []
|
235
238
|
|
@@ -256,7 +259,7 @@ class PauliFeatureMap(QuantumFeatureMap):
|
|
256
259
|
|
257
260
|
def _add_single_pauli_gates(
|
258
261
|
self,
|
259
|
-
gates:
|
262
|
+
gates: list[dict],
|
260
263
|
pauli: str,
|
261
264
|
parameters: np.ndarray,
|
262
265
|
rep: int
|
@@ -283,7 +286,7 @@ class PauliFeatureMap(QuantumFeatureMap):
|
|
283
286
|
|
284
287
|
def _add_multi_pauli_gates(
|
285
288
|
self,
|
286
|
-
gates:
|
289
|
+
gates: list[dict],
|
287
290
|
pauli_string: str,
|
288
291
|
parameters: np.ndarray,
|
289
292
|
rep: int
|
@@ -312,12 +315,12 @@ def create_feature_map(
|
|
312
315
|
**kwargs
|
313
316
|
) -> QuantumFeatureMap:
|
314
317
|
"""Factory function to create quantum feature maps.
|
315
|
-
|
318
|
+
|
316
319
|
Args:
|
317
320
|
feature_map_type: Type of feature map ('Z', 'ZZ', 'Pauli')
|
318
321
|
n_features: Number of input features
|
319
322
|
**kwargs: Additional arguments for specific feature maps
|
320
|
-
|
323
|
+
|
321
324
|
Returns:
|
322
325
|
QuantumFeatureMap instance
|
323
326
|
|
@@ -336,24 +339,26 @@ def create_feature_map(
|
|
336
339
|
|
337
340
|
def pauli_feature_map(
|
338
341
|
n_features: int,
|
339
|
-
paulis:
|
342
|
+
paulis: list[str] = None,
|
340
343
|
reps: int = 1,
|
341
344
|
alpha: float = 2.0,
|
342
345
|
entanglement: str = 'full'
|
343
346
|
) -> PauliFeatureMap:
|
344
347
|
"""Create a Pauli feature map with specified Pauli strings.
|
345
|
-
|
348
|
+
|
346
349
|
Args:
|
347
350
|
n_features: Number of input features
|
348
351
|
paulis: List of Pauli strings to use
|
349
352
|
reps: Number of repetitions
|
350
353
|
alpha: Scaling factor
|
351
354
|
entanglement: Entanglement pattern
|
352
|
-
|
355
|
+
|
353
356
|
Returns:
|
354
357
|
PauliFeatureMap instance
|
355
358
|
|
356
359
|
"""
|
360
|
+
if paulis is None:
|
361
|
+
paulis = ['Z', 'ZZ']
|
357
362
|
return PauliFeatureMap(
|
358
363
|
n_features=n_features,
|
359
364
|
paulis=paulis,
|
@@ -370,13 +375,13 @@ def zz_feature_map(
|
|
370
375
|
alpha: float = 2.0
|
371
376
|
) -> ZZFeatureMap:
|
372
377
|
"""Create a ZZ feature map with specified parameters.
|
373
|
-
|
378
|
+
|
374
379
|
Args:
|
375
380
|
n_features: Number of input features
|
376
381
|
reps: Number of repetitions
|
377
382
|
entanglement: Entanglement pattern ('linear', 'circular', 'full')
|
378
383
|
alpha: Scaling factor
|
379
|
-
|
384
|
+
|
380
385
|
Returns:
|
381
386
|
ZZFeatureMap instance
|
382
387
|
|
@@ -391,10 +396,10 @@ def zz_feature_map(
|
|
391
396
|
|
392
397
|
def feature_map_from_config(config: FeatureMapConfig) -> QuantumFeatureMap:
|
393
398
|
"""Create feature map from configuration.
|
394
|
-
|
399
|
+
|
395
400
|
Args:
|
396
401
|
config: FeatureMapConfig instance
|
397
|
-
|
402
|
+
|
398
403
|
Returns:
|
399
404
|
QuantumFeatureMap instance
|
400
405
|
|
@@ -419,18 +424,18 @@ def feature_map_from_config(config: FeatureMapConfig) -> QuantumFeatureMap:
|
|
419
424
|
def evaluate_feature_map_expressibility(
|
420
425
|
feature_map: QuantumFeatureMap,
|
421
426
|
n_samples: int = 1000,
|
422
|
-
random_state:
|
423
|
-
) ->
|
427
|
+
random_state: int | None = None
|
428
|
+
) -> dict[str, float]:
|
424
429
|
"""Evaluate the expressibility of a quantum feature map.
|
425
|
-
|
430
|
+
|
426
431
|
Expressibility measures how well a feature map can generate
|
427
432
|
diverse quantum states across the Hilbert space.
|
428
|
-
|
433
|
+
|
429
434
|
Args:
|
430
435
|
feature_map: QuantumFeatureMap to evaluate
|
431
436
|
n_samples: Number of random data points to sample
|
432
437
|
random_state: Random seed
|
433
|
-
|
438
|
+
|
434
439
|
Returns:
|
435
440
|
Dictionary with expressibility metrics
|
436
441
|
|
@@ -6,7 +6,8 @@ including classical optimizers commonly used in quantum machine learning.
|
|
6
6
|
|
7
7
|
import time
|
8
8
|
from abc import ABC, abstractmethod
|
9
|
-
from
|
9
|
+
from collections.abc import Callable
|
10
|
+
from typing import Any
|
10
11
|
|
11
12
|
import numpy as np
|
12
13
|
|
@@ -94,15 +95,15 @@ class AdamOptimizer(Optimizer):
|
|
94
95
|
def optimize_circuit(
|
95
96
|
cost_function: Callable[[np.ndarray], float],
|
96
97
|
initial_params: np.ndarray,
|
97
|
-
gradient_function:
|
98
|
+
gradient_function: Callable[[np.ndarray], np.ndarray] | None = None,
|
98
99
|
optimizer: str = 'adam',
|
99
100
|
max_iterations: int = 100,
|
100
101
|
tolerance: float = 1e-6,
|
101
102
|
learning_rate: float = 0.01,
|
102
103
|
verbose: bool = False
|
103
|
-
) ->
|
104
|
+
) -> dict[str, Any]:
|
104
105
|
"""Optimize quantum circuit parameters.
|
105
|
-
|
106
|
+
|
106
107
|
Args:
|
107
108
|
cost_function: Function to minimize f(params) -> cost
|
108
109
|
initial_params: Initial parameter values
|
@@ -112,7 +113,7 @@ def optimize_circuit(
|
|
112
113
|
tolerance: Convergence tolerance
|
113
114
|
learning_rate: Learning rate for gradient-based optimizers
|
114
115
|
verbose: Whether to print progress
|
115
|
-
|
116
|
+
|
116
117
|
Returns:
|
117
118
|
Dictionary with optimization results
|
118
119
|
|
@@ -132,7 +133,8 @@ def optimize_circuit(
|
|
132
133
|
|
133
134
|
# If no gradient function provided, use finite differences
|
134
135
|
if gradient_function is None:
|
135
|
-
gradient_function
|
136
|
+
def gradient_function(p):
|
137
|
+
return finite_difference_gradient(cost_function, p)
|
136
138
|
|
137
139
|
for iteration in range(max_iterations):
|
138
140
|
# Compute cost and gradient
|
@@ -168,20 +170,20 @@ def optimize_circuit(
|
|
168
170
|
|
169
171
|
def optimize_parameters(
|
170
172
|
objective_function: Callable,
|
171
|
-
bounds:
|
173
|
+
bounds: list[tuple[float, float]],
|
172
174
|
method: str = 'scipy',
|
173
175
|
max_evaluations: int = 1000,
|
174
|
-
random_state:
|
175
|
-
) ->
|
176
|
+
random_state: int | None = None
|
177
|
+
) -> dict[str, Any]:
|
176
178
|
"""Optimize parameters using various methods.
|
177
|
-
|
179
|
+
|
178
180
|
Args:
|
179
181
|
objective_function: Function to minimize
|
180
182
|
bounds: Parameter bounds as list of (min, max) tuples
|
181
183
|
method: Optimization method ('scipy', 'random_search', 'grid_search')
|
182
184
|
max_evaluations: Maximum function evaluations
|
183
185
|
random_state: Random seed
|
184
|
-
|
186
|
+
|
185
187
|
Returns:
|
186
188
|
Optimization results dictionary
|
187
189
|
|
@@ -203,9 +205,9 @@ def gradient_descent(
|
|
203
205
|
learning_rate: float = 0.01,
|
204
206
|
max_iterations: int = 1000,
|
205
207
|
tolerance: float = 1e-6
|
206
|
-
) ->
|
208
|
+
) -> tuple[np.ndarray, list[float]]:
|
207
209
|
"""Perform gradient descent optimization.
|
208
|
-
|
210
|
+
|
209
211
|
Args:
|
210
212
|
cost_function: Cost function to minimize
|
211
213
|
gradient_function: Function returning gradients
|
@@ -213,7 +215,7 @@ def gradient_descent(
|
|
213
215
|
learning_rate: Learning rate
|
214
216
|
max_iterations: Maximum iterations
|
215
217
|
tolerance: Convergence tolerance
|
216
|
-
|
218
|
+
|
217
219
|
Returns:
|
218
220
|
Tuple of (optimal_params, cost_history)
|
219
221
|
|
@@ -244,9 +246,9 @@ def adam_optimizer(
|
|
244
246
|
epsilon: float = 1e-8,
|
245
247
|
max_iterations: int = 1000,
|
246
248
|
tolerance: float = 1e-6
|
247
|
-
) ->
|
249
|
+
) -> tuple[np.ndarray, list[float]]:
|
248
250
|
"""Perform Adam optimization.
|
249
|
-
|
251
|
+
|
250
252
|
Args:
|
251
253
|
cost_function: Cost function to minimize
|
252
254
|
gradient_function: Function returning gradients
|
@@ -257,7 +259,7 @@ def adam_optimizer(
|
|
257
259
|
epsilon: Small constant for numerical stability
|
258
260
|
max_iterations: Maximum iterations
|
259
261
|
tolerance: Convergence tolerance
|
260
|
-
|
262
|
+
|
261
263
|
Returns:
|
262
264
|
Tuple of (optimal_params, cost_history)
|
263
265
|
|
@@ -285,12 +287,12 @@ def finite_difference_gradient(
|
|
285
287
|
epsilon: float = 1e-6
|
286
288
|
) -> np.ndarray:
|
287
289
|
"""Compute gradient using finite differences.
|
288
|
-
|
290
|
+
|
289
291
|
Args:
|
290
292
|
function: Function to differentiate
|
291
293
|
params: Parameters at which to compute gradient
|
292
294
|
epsilon: Finite difference step size
|
293
|
-
|
295
|
+
|
294
296
|
Returns:
|
295
297
|
Gradient vector
|
296
298
|
|
@@ -312,9 +314,9 @@ def finite_difference_gradient(
|
|
312
314
|
|
313
315
|
def _scipy_optimize(
|
314
316
|
objective_function: Callable,
|
315
|
-
bounds:
|
317
|
+
bounds: list[tuple[float, float]],
|
316
318
|
max_evaluations: int
|
317
|
-
) ->
|
319
|
+
) -> dict[str, Any]:
|
318
320
|
"""Optimize using scipy methods."""
|
319
321
|
try:
|
320
322
|
from scipy.optimize import minimize
|
@@ -342,10 +344,10 @@ def _scipy_optimize(
|
|
342
344
|
|
343
345
|
def _random_search_optimize(
|
344
346
|
objective_function: Callable,
|
345
|
-
bounds:
|
347
|
+
bounds: list[tuple[float, float]],
|
346
348
|
max_evaluations: int,
|
347
|
-
random_state:
|
348
|
-
) ->
|
349
|
+
random_state: int | None
|
350
|
+
) -> dict[str, Any]:
|
349
351
|
"""Random search optimization."""
|
350
352
|
np.random.seed(random_state)
|
351
353
|
|
@@ -372,9 +374,9 @@ def _random_search_optimize(
|
|
372
374
|
|
373
375
|
def _grid_search_optimize(
|
374
376
|
objective_function: Callable,
|
375
|
-
bounds:
|
377
|
+
bounds: list[tuple[float, float]],
|
376
378
|
max_evaluations: int
|
377
|
-
) ->
|
379
|
+
) -> dict[str, Any]:
|
378
380
|
"""Grid search optimization."""
|
379
381
|
n_params = len(bounds)
|
380
382
|
n_points_per_dim = int(max_evaluations ** (1 / n_params))
|