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
@@ -5,7 +5,7 @@ including quantum matrix diagonalization and dimensionality reduction.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from typing import Any
|
8
|
+
from typing import Any
|
9
9
|
|
10
10
|
import numpy as np
|
11
11
|
from sklearn.decomposition import PCA
|
@@ -18,16 +18,16 @@ logger = logging.getLogger(__name__)
|
|
18
18
|
|
19
19
|
class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
20
20
|
"""Quantum Principal Component Analysis for dimensionality reduction.
|
21
|
-
|
21
|
+
|
22
22
|
This implementation uses quantum algorithms to perform PCA, potentially
|
23
23
|
offering exponential speedup for certain types of data matrices.
|
24
|
-
|
24
|
+
|
25
25
|
The algorithm can use different quantum approaches:
|
26
26
|
- Quantum Matrix Inversion: For density matrix diagonalization
|
27
27
|
- Variational Quantum Eigensolver: For finding principal eigenvectors
|
28
28
|
- Quantum Phase Estimation: For eigenvalue extraction
|
29
29
|
- Quantum Singular Value Decomposition: Direct SVD approach
|
30
|
-
|
30
|
+
|
31
31
|
Args:
|
32
32
|
backend: Quantum backend for circuit execution
|
33
33
|
n_components: Number of principal components to extract
|
@@ -38,7 +38,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
38
38
|
shots: Number of measurement shots
|
39
39
|
classical_fallback: Use classical PCA if quantum fails
|
40
40
|
**kwargs: Additional parameters
|
41
|
-
|
41
|
+
|
42
42
|
Example:
|
43
43
|
>>> qpca = QuantumPCA(backend='pennylane', n_components=3, method='vqe')
|
44
44
|
>>> qpca.fit(X_train)
|
@@ -49,7 +49,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
49
49
|
|
50
50
|
def __init__(
|
51
51
|
self,
|
52
|
-
backend:
|
52
|
+
backend: str | Any,
|
53
53
|
n_components: int = 2,
|
54
54
|
method: str = 'vqe',
|
55
55
|
encoding: str = 'amplitude',
|
@@ -148,7 +148,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
148
148
|
logger.warning("Using fallback density matrix encoding")
|
149
149
|
return None
|
150
150
|
|
151
|
-
def _quantum_eigensolver_vqe(self, density_matrix: np.ndarray) ->
|
151
|
+
def _quantum_eigensolver_vqe(self, density_matrix: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
152
152
|
"""Use VQE to find principal eigenvectors and eigenvalues."""
|
153
153
|
logger.info("Running VQE for quantum PCA")
|
154
154
|
|
@@ -174,7 +174,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
174
174
|
logger.error(f"VQE eigensolver failed: {e}")
|
175
175
|
return self._fallback_vqe_eigensolver(density_matrix)
|
176
176
|
|
177
|
-
def _fallback_vqe_eigensolver(self, density_matrix: np.ndarray) ->
|
177
|
+
def _fallback_vqe_eigensolver(self, density_matrix: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
178
178
|
"""Fallback VQE implementation using classical eigensolver."""
|
179
179
|
logger.warning("Using classical fallback for VQE eigensolver")
|
180
180
|
eigenvals, eigenvecs = np.linalg.eigh(density_matrix)
|
@@ -182,7 +182,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
182
182
|
idx = np.argsort(eigenvals)[::-1]
|
183
183
|
return eigenvals[idx][:self.n_components], eigenvecs[:, idx][:, :self.n_components]
|
184
184
|
|
185
|
-
def _quantum_phase_estimation(self, density_matrix: np.ndarray) ->
|
185
|
+
def _quantum_phase_estimation(self, density_matrix: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
186
186
|
"""Use quantum phase estimation for eigenvalue extraction."""
|
187
187
|
logger.info("Running quantum phase estimation for PCA")
|
188
188
|
|
@@ -206,12 +206,12 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
206
206
|
logger.error(f"Quantum phase estimation failed: {e}")
|
207
207
|
return self._fallback_phase_estimation(density_matrix)
|
208
208
|
|
209
|
-
def _fallback_phase_estimation(self, density_matrix: np.ndarray) ->
|
209
|
+
def _fallback_phase_estimation(self, density_matrix: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
210
210
|
"""Fallback phase estimation using classical methods."""
|
211
211
|
logger.warning("Using classical fallback for phase estimation")
|
212
212
|
return self._fallback_vqe_eigensolver(density_matrix)
|
213
213
|
|
214
|
-
def _quantum_svd(self, X: np.ndarray) ->
|
214
|
+
def _quantum_svd(self, X: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
215
215
|
"""Quantum singular value decomposition approach."""
|
216
216
|
logger.info("Running quantum SVD for PCA")
|
217
217
|
|
@@ -237,14 +237,14 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
237
237
|
logger.error(f"Quantum SVD failed: {e}")
|
238
238
|
return self._fallback_svd(X)
|
239
239
|
|
240
|
-
def _fallback_svd(self, X: np.ndarray) ->
|
240
|
+
def _fallback_svd(self, X: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
241
241
|
"""Fallback SVD using classical methods."""
|
242
242
|
logger.warning("Using classical fallback for SVD")
|
243
243
|
U, s, Vt = np.linalg.svd(X, full_matrices=False)
|
244
244
|
eigenvalues = (s ** 2) / (X.shape[0] - 1)
|
245
245
|
return eigenvalues[:self.n_components], Vt[:self.n_components].T
|
246
246
|
|
247
|
-
def _quantum_matrix_inversion(self, density_matrix: np.ndarray) ->
|
247
|
+
def _quantum_matrix_inversion(self, density_matrix: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
248
248
|
"""Quantum matrix inversion approach."""
|
249
249
|
logger.info("Running quantum matrix inversion for PCA")
|
250
250
|
|
@@ -268,19 +268,19 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
268
268
|
logger.error(f"Quantum matrix inversion failed: {e}")
|
269
269
|
return self._fallback_matrix_inversion(density_matrix)
|
270
270
|
|
271
|
-
def _fallback_matrix_inversion(self, density_matrix: np.ndarray) ->
|
271
|
+
def _fallback_matrix_inversion(self, density_matrix: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
272
272
|
"""Fallback matrix inversion using classical methods."""
|
273
273
|
logger.warning("Using classical fallback for matrix inversion")
|
274
274
|
return self._fallback_vqe_eigensolver(density_matrix)
|
275
275
|
|
276
|
-
def fit(self, X: np.ndarray, y:
|
276
|
+
def fit(self, X: np.ndarray, y: np.ndarray | None = None, **kwargs) -> 'QuantumPCA':
|
277
277
|
"""Fit quantum PCA to the data.
|
278
|
-
|
278
|
+
|
279
279
|
Args:
|
280
280
|
X: Training data
|
281
281
|
y: Ignored (unsupervised learning)
|
282
282
|
**kwargs: Additional fitting parameters
|
283
|
-
|
283
|
+
|
284
284
|
Returns:
|
285
285
|
Self for method chaining
|
286
286
|
|
@@ -335,10 +335,10 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
335
335
|
|
336
336
|
def transform(self, X: np.ndarray) -> np.ndarray:
|
337
337
|
"""Transform data to lower dimensional space.
|
338
|
-
|
338
|
+
|
339
339
|
Args:
|
340
340
|
X: Data to transform
|
341
|
-
|
341
|
+
|
342
342
|
Returns:
|
343
343
|
Transformed data
|
344
344
|
|
@@ -360,10 +360,10 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
360
360
|
|
361
361
|
def inverse_transform(self, X_transformed: np.ndarray) -> np.ndarray:
|
362
362
|
"""Reconstruct data from lower dimensional representation.
|
363
|
-
|
363
|
+
|
364
364
|
Args:
|
365
365
|
X_transformed: Transformed data
|
366
|
-
|
366
|
+
|
367
367
|
Returns:
|
368
368
|
Reconstructed data
|
369
369
|
|
@@ -383,7 +383,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
383
383
|
|
384
384
|
return X_reconstructed
|
385
385
|
|
386
|
-
def fit_transform(self, X: np.ndarray, y:
|
386
|
+
def fit_transform(self, X: np.ndarray, y: np.ndarray | None = None) -> np.ndarray:
|
387
387
|
"""Fit PCA and transform data in one step."""
|
388
388
|
return self.fit(X, y).transform(X)
|
389
389
|
|
@@ -391,7 +391,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
391
391
|
"""Transform data (alias for transform method)."""
|
392
392
|
return self.transform(X)
|
393
393
|
|
394
|
-
def get_quantum_advantage_metrics(self) ->
|
394
|
+
def get_quantum_advantage_metrics(self) -> dict[str, Any]:
|
395
395
|
"""Analyze potential quantum advantage."""
|
396
396
|
if not self.is_fitted:
|
397
397
|
raise ValueError("Must fit model first")
|
@@ -418,7 +418,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
418
418
|
|
419
419
|
return metrics
|
420
420
|
|
421
|
-
def compare_with_classical(self, X: np.ndarray) ->
|
421
|
+
def compare_with_classical(self, X: np.ndarray) -> dict[str, Any]:
|
422
422
|
"""Compare quantum PCA results with classical PCA."""
|
423
423
|
if not self.is_fitted or not hasattr(self.classical_pca, 'components_'):
|
424
424
|
raise ValueError("Both quantum and classical PCA must be fitted")
|
@@ -459,7 +459,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
459
459
|
'mean_component_similarity': np.mean(component_similarities) if component_similarities else 0,
|
460
460
|
}
|
461
461
|
|
462
|
-
def analyze_convergence(self) ->
|
462
|
+
def analyze_convergence(self) -> dict[str, Any]:
|
463
463
|
"""Analyze convergence properties of the quantum algorithm."""
|
464
464
|
if not self.convergence_history:
|
465
465
|
return {'message': 'No convergence history available'}
|
@@ -475,7 +475,7 @@ class QuantumPCA(UnsupervisedQuantumAlgorithm):
|
|
475
475
|
'convergence_rate': np.mean(np.diff(convergence_data)) if len(convergence_data) > 1 else 0,
|
476
476
|
}
|
477
477
|
|
478
|
-
def get_params(self, deep: bool = True) ->
|
478
|
+
def get_params(self, deep: bool = True) -> dict[str, Any]:
|
479
479
|
"""Get quantum PCA parameters."""
|
480
480
|
params = super().get_params(deep)
|
481
481
|
params.update({
|
@@ -5,7 +5,8 @@ for binary and multiclass classification tasks using quantum kernels.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from
|
8
|
+
from collections.abc import Callable
|
9
|
+
from typing import Any
|
9
10
|
|
10
11
|
import numpy as np
|
11
12
|
from sklearn.metrics import accuracy_score
|
@@ -19,16 +20,16 @@ logger = logging.getLogger(__name__)
|
|
19
20
|
|
20
21
|
class QuantumSVM(SupervisedQuantumAlgorithm):
|
21
22
|
"""Quantum Support Vector Machine for classification.
|
22
|
-
|
23
|
+
|
23
24
|
This implementation uses quantum feature maps to transform data into
|
24
25
|
a high-dimensional Hilbert space where linear separation is possible.
|
25
26
|
The quantum kernel is computed using quantum circuits.
|
26
|
-
|
27
|
+
|
27
28
|
The algorithm works by:
|
28
29
|
1. Encoding classical data into quantum states using feature maps
|
29
30
|
2. Computing quantum kernels between data points
|
30
31
|
3. Training a classical SVM using the quantum kernel matrix
|
31
|
-
|
32
|
+
|
32
33
|
Args:
|
33
34
|
backend: Quantum backend for circuit execution
|
34
35
|
feature_map: Type of quantum feature map ('ZZFeatureMap', 'PauliFeatureMap', etc.)
|
@@ -38,7 +39,7 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
38
39
|
quantum_kernel: Custom quantum kernel function
|
39
40
|
shots: Number of measurement shots
|
40
41
|
**kwargs: Additional parameters
|
41
|
-
|
42
|
+
|
42
43
|
Example:
|
43
44
|
>>> qsvm = QuantumSVM(backend='pennylane', feature_map='ZZFeatureMap')
|
44
45
|
>>> qsvm.fit(X_train, y_train)
|
@@ -49,12 +50,12 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
49
50
|
|
50
51
|
def __init__(
|
51
52
|
self,
|
52
|
-
backend:
|
53
|
+
backend: str | Any,
|
53
54
|
feature_map: str = 'ZZFeatureMap',
|
54
55
|
feature_map_reps: int = 2,
|
55
56
|
C: float = 1.0,
|
56
|
-
gamma:
|
57
|
-
quantum_kernel:
|
57
|
+
gamma: float | None = None,
|
58
|
+
quantum_kernel: Callable | None = None,
|
58
59
|
shots: int = 1024,
|
59
60
|
normalize_data: bool = True,
|
60
61
|
**kwargs
|
@@ -103,13 +104,13 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
103
104
|
logger.warning("Using default feature map - results may vary")
|
104
105
|
return None
|
105
106
|
|
106
|
-
def _compute_quantum_kernel(self, X1: np.ndarray, X2:
|
107
|
+
def _compute_quantum_kernel(self, X1: np.ndarray, X2: np.ndarray | None = None) -> np.ndarray:
|
107
108
|
"""Compute quantum kernel matrix between data points.
|
108
|
-
|
109
|
+
|
109
110
|
Args:
|
110
111
|
X1: First set of data points
|
111
112
|
X2: Second set of data points (if None, use X1)
|
112
|
-
|
113
|
+
|
113
114
|
Returns:
|
114
115
|
Quantum kernel matrix
|
115
116
|
|
@@ -145,12 +146,12 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
145
146
|
|
146
147
|
def fit(self, X: np.ndarray, y: np.ndarray, **kwargs) -> 'QuantumSVM':
|
147
148
|
"""Train the quantum SVM.
|
148
|
-
|
149
|
+
|
149
150
|
Args:
|
150
151
|
X: Training data features
|
151
152
|
y: Training data labels
|
152
153
|
**kwargs: Additional training parameters
|
153
|
-
|
154
|
+
|
154
155
|
Returns:
|
155
156
|
Self for method chaining
|
156
157
|
|
@@ -198,11 +199,11 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
198
199
|
|
199
200
|
def predict(self, X: np.ndarray, **kwargs) -> np.ndarray:
|
200
201
|
"""Make predictions using the trained quantum SVM.
|
201
|
-
|
202
|
+
|
202
203
|
Args:
|
203
204
|
X: Input data for prediction
|
204
205
|
**kwargs: Additional prediction parameters
|
205
|
-
|
206
|
+
|
206
207
|
Returns:
|
207
208
|
Predicted labels
|
208
209
|
|
@@ -223,11 +224,11 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
223
224
|
|
224
225
|
def predict_proba(self, X: np.ndarray, **kwargs) -> np.ndarray:
|
225
226
|
"""Predict class probabilities.
|
226
|
-
|
227
|
+
|
227
228
|
Args:
|
228
229
|
X: Input data for prediction
|
229
230
|
**kwargs: Additional parameters
|
230
|
-
|
231
|
+
|
231
232
|
Returns:
|
232
233
|
Predicted class probabilities
|
233
234
|
|
@@ -249,10 +250,10 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
249
250
|
|
250
251
|
def decision_function(self, X: np.ndarray) -> np.ndarray:
|
251
252
|
"""Compute decision function values.
|
252
|
-
|
253
|
+
|
253
254
|
Args:
|
254
255
|
X: Input data
|
255
|
-
|
256
|
+
|
256
257
|
Returns:
|
257
258
|
Decision function values
|
258
259
|
|
@@ -273,12 +274,12 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
273
274
|
|
274
275
|
return self.X_train_[self.svm.support_]
|
275
276
|
|
276
|
-
def get_quantum_kernel_matrix(self, X:
|
277
|
+
def get_quantum_kernel_matrix(self, X: np.ndarray | None = None) -> np.ndarray:
|
277
278
|
"""Get the quantum kernel matrix.
|
278
|
-
|
279
|
+
|
279
280
|
Args:
|
280
281
|
X: Data to compute kernel matrix for (default: training data)
|
281
|
-
|
282
|
+
|
282
283
|
Returns:
|
283
284
|
Quantum kernel matrix
|
284
285
|
|
@@ -292,9 +293,9 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
292
293
|
X = self.scaler.transform(X)
|
293
294
|
return self._compute_quantum_kernel(X)
|
294
295
|
|
295
|
-
def analyze_kernel(self) ->
|
296
|
+
def analyze_kernel(self) -> dict[str, Any]:
|
296
297
|
"""Analyze properties of the quantum kernel.
|
297
|
-
|
298
|
+
|
298
299
|
Returns:
|
299
300
|
Dictionary with kernel analysis results
|
300
301
|
|
@@ -324,7 +325,7 @@ class QuantumSVM(SupervisedQuantumAlgorithm):
|
|
324
325
|
|
325
326
|
return analysis
|
326
327
|
|
327
|
-
def get_params(self, deep: bool = True) ->
|
328
|
+
def get_params(self, deep: bool = True) -> dict[str, Any]:
|
328
329
|
"""Get algorithm parameters."""
|
329
330
|
params = super().get_params(deep)
|
330
331
|
params.update({
|
superquantx/algorithms/vqe.py
CHANGED
@@ -5,7 +5,8 @@ and eigenvalues of quantum systems using parameterized quantum circuits.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from
|
8
|
+
from collections.abc import Callable
|
9
|
+
from typing import Any
|
9
10
|
|
10
11
|
import numpy as np
|
11
12
|
from scipy.optimize import minimize
|
@@ -17,27 +18,27 @@ logger = logging.getLogger(__name__)
|
|
17
18
|
|
18
19
|
class VQE(OptimizationQuantumAlgorithm):
|
19
20
|
"""Variational Quantum Eigensolver for finding ground states.
|
20
|
-
|
21
|
+
|
21
22
|
VQE is a hybrid quantum-classical algorithm that uses a parameterized
|
22
23
|
quantum circuit (ansatz) to find the ground state energy of a given
|
23
24
|
Hamiltonian by minimizing the expectation value.
|
24
|
-
|
25
|
+
|
25
26
|
The algorithm works by:
|
26
27
|
1. Preparing a parameterized quantum state |ψ(θ)⟩
|
27
28
|
2. Measuring the expectation value ⟨ψ(θ)|H|ψ(θ)⟩
|
28
29
|
3. Classically optimizing parameters θ to minimize energy
|
29
30
|
4. Iterating until convergence
|
30
|
-
|
31
|
+
|
31
32
|
Args:
|
32
33
|
backend: Quantum backend for circuit execution
|
33
34
|
hamiltonian: Target Hamiltonian (matrix or operator)
|
34
35
|
ansatz: Parameterized circuit ansatz ('UCCSD', 'RealAmplitudes', etc.)
|
35
36
|
optimizer: Classical optimizer ('COBYLA', 'L-BFGS-B', etc.)
|
36
37
|
shots: Number of measurement shots
|
37
|
-
maxiter: Maximum optimization iterations
|
38
|
+
maxiter: Maximum optimization iterations
|
38
39
|
initial_params: Initial parameter values
|
39
40
|
**kwargs: Additional parameters
|
40
|
-
|
41
|
+
|
41
42
|
Example:
|
42
43
|
>>> # Define H2 molecule Hamiltonian
|
43
44
|
>>> H2_hamiltonian = create_h2_hamiltonian(bond_distance=0.74)
|
@@ -49,13 +50,13 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
49
50
|
|
50
51
|
def __init__(
|
51
52
|
self,
|
52
|
-
hamiltonian:
|
53
|
-
ansatz:
|
54
|
-
backend:
|
53
|
+
hamiltonian: np.ndarray | Any,
|
54
|
+
ansatz: str | Callable = 'RealAmplitudes',
|
55
|
+
backend: str | Any = 'simulator',
|
55
56
|
optimizer: str = 'COBYLA',
|
56
57
|
shots: int = 1024,
|
57
58
|
maxiter: int = 1000,
|
58
|
-
initial_params:
|
59
|
+
initial_params: np.ndarray | None = None,
|
59
60
|
include_custom_gates: bool = False,
|
60
61
|
client = None,
|
61
62
|
**kwargs
|
@@ -101,14 +102,14 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
101
102
|
self.hamiltonian_terms = self.hamiltonian
|
102
103
|
self.n_qubits = self._infer_qubits_from_hamiltonian()
|
103
104
|
|
104
|
-
def _decompose_hamiltonian(self) ->
|
105
|
+
def _decompose_hamiltonian(self) -> list[tuple[float, str]]:
|
105
106
|
"""Decompose Hamiltonian into Pauli string representation."""
|
106
107
|
if hasattr(self.backend, 'decompose_hamiltonian'):
|
107
108
|
return self.backend.decompose_hamiltonian(self.hamiltonian)
|
108
109
|
else:
|
109
110
|
return self._fallback_decomposition()
|
110
111
|
|
111
|
-
def _fallback_decomposition(self) ->
|
112
|
+
def _fallback_decomposition(self) -> list[tuple[float, str]]:
|
112
113
|
"""Fallback Hamiltonian decomposition."""
|
113
114
|
logger.warning("Using fallback Hamiltonian decomposition")
|
114
115
|
# Simple placeholder - would need proper Pauli decomposition
|
@@ -122,10 +123,10 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
122
123
|
|
123
124
|
def _create_ansatz_circuit(self, params: np.ndarray) -> Any:
|
124
125
|
"""Create ansatz circuit with given parameters.
|
125
|
-
|
126
|
+
|
126
127
|
Args:
|
127
128
|
params: Circuit parameters
|
128
|
-
|
129
|
+
|
129
130
|
Returns:
|
130
131
|
Parameterized quantum circuit
|
131
132
|
|
@@ -151,10 +152,10 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
151
152
|
|
152
153
|
def _compute_expectation_value(self, params: np.ndarray) -> float:
|
153
154
|
"""Compute expectation value ⟨ψ(θ)|H|ψ(θ)⟩.
|
154
|
-
|
155
|
+
|
155
156
|
Args:
|
156
157
|
params: Circuit parameters
|
157
|
-
|
158
|
+
|
158
159
|
Returns:
|
159
160
|
Hamiltonian expectation value
|
160
161
|
|
@@ -190,10 +191,10 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
190
191
|
|
191
192
|
def _compute_gradient(self, params: np.ndarray) -> np.ndarray:
|
192
193
|
"""Compute parameter gradients using parameter-shift rule.
|
193
|
-
|
194
|
+
|
194
195
|
Args:
|
195
196
|
params: Current parameters
|
196
|
-
|
197
|
+
|
197
198
|
Returns:
|
198
199
|
Gradient vector
|
199
200
|
|
@@ -218,14 +219,14 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
218
219
|
self.gradient_history.append(np.linalg.norm(gradients))
|
219
220
|
return gradients
|
220
221
|
|
221
|
-
def fit(self, X:
|
222
|
+
def fit(self, X: np.ndarray | None = None, y: np.ndarray | None = None, **kwargs) -> 'VQE':
|
222
223
|
"""Fit VQE (setup for optimization).
|
223
|
-
|
224
|
+
|
224
225
|
Args:
|
225
226
|
X: Not used in VQE
|
226
227
|
y: Not used in VQE
|
227
228
|
**kwargs: Additional parameters
|
228
|
-
|
229
|
+
|
229
230
|
Returns:
|
230
231
|
Self for method chaining
|
231
232
|
|
@@ -265,13 +266,13 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
265
266
|
"""Generate random initial parameters."""
|
266
267
|
return np.random.uniform(-np.pi, np.pi, self.n_params)
|
267
268
|
|
268
|
-
def predict(self, X:
|
269
|
+
def predict(self, X: np.ndarray | None = None, **kwargs) -> np.ndarray:
|
269
270
|
"""Get ground state wavefunction coefficients.
|
270
|
-
|
271
|
+
|
271
272
|
Args:
|
272
273
|
X: Not used
|
273
274
|
**kwargs: Additional parameters
|
274
|
-
|
275
|
+
|
275
276
|
Returns:
|
276
277
|
Ground state wavefunction
|
277
278
|
|
@@ -292,14 +293,14 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
292
293
|
|
293
294
|
return np.array(statevector)
|
294
295
|
|
295
|
-
def _run_optimization(self, objective_function=None, initial_params:
|
296
|
+
def _run_optimization(self, objective_function=None, initial_params: np.ndarray | None = None, **kwargs):
|
296
297
|
"""Run VQE optimization.
|
297
|
-
|
298
|
+
|
298
299
|
Args:
|
299
300
|
objective_function: Not used (VQE has its own objective)
|
300
301
|
initial_params: Initial parameter guess
|
301
302
|
**kwargs: Additional optimization parameters
|
302
|
-
|
303
|
+
|
303
304
|
Returns:
|
304
305
|
Optimization result
|
305
306
|
|
@@ -356,15 +357,15 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
356
357
|
logger.error(f"VQE optimization failed: {e}")
|
357
358
|
raise
|
358
359
|
|
359
|
-
def get_energy_landscape(self, param_indices:
|
360
|
-
resolution: int = 20) ->
|
360
|
+
def get_energy_landscape(self, param_indices: list[int], param_ranges: list[tuple[float, float]],
|
361
|
+
resolution: int = 20) -> dict[str, Any]:
|
361
362
|
"""Compute energy landscape for visualization.
|
362
|
-
|
363
|
+
|
363
364
|
Args:
|
364
365
|
param_indices: Indices of parameters to vary
|
365
366
|
param_ranges: Ranges for each parameter
|
366
367
|
resolution: Number of points per dimension
|
367
|
-
|
368
|
+
|
368
369
|
Returns:
|
369
370
|
Dictionary with landscape data
|
370
371
|
|
@@ -396,9 +397,9 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
396
397
|
'param_indices': param_indices
|
397
398
|
}
|
398
399
|
|
399
|
-
def analyze_convergence(self) ->
|
400
|
+
def analyze_convergence(self) -> dict[str, Any]:
|
400
401
|
"""Analyze VQE convergence properties.
|
401
|
-
|
402
|
+
|
402
403
|
Returns:
|
403
404
|
Convergence analysis results
|
404
405
|
|
@@ -447,12 +448,12 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
447
448
|
|
448
449
|
return analysis
|
449
450
|
|
450
|
-
def compare_with_exact(self, exact_ground_energy: float) ->
|
451
|
+
def compare_with_exact(self, exact_ground_energy: float) -> dict[str, Any]:
|
451
452
|
"""Compare VQE result with exact ground state energy.
|
452
|
-
|
453
|
+
|
453
454
|
Args:
|
454
455
|
exact_ground_energy: Known exact ground state energy
|
455
|
-
|
456
|
+
|
456
457
|
Returns:
|
457
458
|
Comparison analysis
|
458
459
|
|
@@ -472,7 +473,7 @@ class VQE(OptimizationQuantumAlgorithm):
|
|
472
473
|
'energy_above_ground': max(0, self.optimal_value_ - exact_ground_energy)
|
473
474
|
}
|
474
475
|
|
475
|
-
def get_params(self, deep: bool = True) ->
|
476
|
+
def get_params(self, deep: bool = True) -> dict[str, Any]:
|
476
477
|
"""Get VQE parameters."""
|
477
478
|
params = super().get_params(deep)
|
478
479
|
params.update({
|
@@ -502,7 +503,7 @@ def create_vqe_for_molecule(
|
|
502
503
|
client = None
|
503
504
|
) -> VQE:
|
504
505
|
"""Create a VQE instance pre-configured for molecular simulation.
|
505
|
-
|
506
|
+
|
506
507
|
Args:
|
507
508
|
molecule_name: Name of the molecule (e.g., 'H2', 'LiH')
|
508
509
|
bond_distance: Bond distance for the molecule (uses default if None)
|
@@ -510,7 +511,7 @@ def create_vqe_for_molecule(
|
|
510
511
|
ansatz: Ansatz circuit type
|
511
512
|
optimizer: Classical optimizer
|
512
513
|
client: Optional client for quantum execution
|
513
|
-
|
514
|
+
|
514
515
|
Returns:
|
515
516
|
Configured VQE instance
|
516
517
|
|