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/algorithms.py
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
"""
|
3
3
|
|
4
4
|
from abc import ABC, abstractmethod
|
5
|
-
from
|
5
|
+
from collections.abc import Callable
|
6
|
+
from typing import Any
|
6
7
|
|
7
8
|
import numpy as np
|
8
9
|
from scipy.optimize import minimize
|
@@ -17,18 +18,18 @@ class QuantumAlgorithm(ABC):
|
|
17
18
|
"""Base class for quantum algorithms
|
18
19
|
"""
|
19
20
|
|
20
|
-
def __init__(self, client:
|
21
|
+
def __init__(self, client: SuperQuantXClient | None = None):
|
21
22
|
"""Initialize quantum algorithm
|
22
|
-
|
23
|
+
|
23
24
|
Args:
|
24
25
|
client: SuperQuantX client for quantum execution
|
25
26
|
|
26
27
|
"""
|
27
28
|
self.client = client
|
28
|
-
self.result_history:
|
29
|
+
self.result_history: list[dict[str, Any]] = []
|
29
30
|
|
30
31
|
@abstractmethod
|
31
|
-
def run(self, *args, **kwargs) ->
|
32
|
+
def run(self, *args, **kwargs) -> dict[str, Any]:
|
32
33
|
"""Execute the quantum algorithm"""
|
33
34
|
pass
|
34
35
|
|
@@ -45,13 +46,13 @@ class VQE(QuantumAlgorithm):
|
|
45
46
|
self,
|
46
47
|
hamiltonian: Hamiltonian,
|
47
48
|
ansatz: Callable[[np.ndarray], QuantumCircuit],
|
48
|
-
client:
|
49
|
+
client: SuperQuantXClient | None = None,
|
49
50
|
optimizer: str = "SLSQP",
|
50
51
|
max_iterations: int = 1000,
|
51
52
|
tolerance: float = 1e-6
|
52
53
|
):
|
53
54
|
"""Initialize VQE algorithm
|
54
|
-
|
55
|
+
|
55
56
|
Args:
|
56
57
|
hamiltonian: Target Hamiltonian
|
57
58
|
ansatz: Parameterized quantum circuit ansatz
|
@@ -68,16 +69,16 @@ class VQE(QuantumAlgorithm):
|
|
68
69
|
self.max_iterations = max_iterations
|
69
70
|
self.tolerance = tolerance
|
70
71
|
|
71
|
-
self.optimal_parameters:
|
72
|
-
self.optimal_energy:
|
73
|
-
self.optimization_history:
|
72
|
+
self.optimal_parameters: np.ndarray | None = None
|
73
|
+
self.optimal_energy: float | None = None
|
74
|
+
self.optimization_history: list[float] = []
|
74
75
|
|
75
76
|
def cost_function(self, parameters: np.ndarray) -> float:
|
76
77
|
"""VQE cost function: expectation value of Hamiltonian
|
77
|
-
|
78
|
+
|
78
79
|
Args:
|
79
80
|
parameters: Ansatz parameters
|
80
|
-
|
81
|
+
|
81
82
|
Returns:
|
82
83
|
Energy expectation value
|
83
84
|
|
@@ -171,7 +172,7 @@ class VQE(QuantumAlgorithm):
|
|
171
172
|
|
172
173
|
for i in range(dim):
|
173
174
|
control_bit = (i >> control) & 1
|
174
|
-
|
175
|
+
(i >> target) & 1
|
175
176
|
|
176
177
|
if control_bit == 1:
|
177
178
|
# Flip target bit
|
@@ -232,7 +233,7 @@ class VQE(QuantumAlgorithm):
|
|
232
233
|
|
233
234
|
def _calculate_pauli_expectation(
|
234
235
|
self,
|
235
|
-
measurement_results:
|
236
|
+
measurement_results: dict[str, Any],
|
236
237
|
pauli_string: PauliString
|
237
238
|
) -> float:
|
238
239
|
"""Calculate expectation value from measurement results"""
|
@@ -258,15 +259,15 @@ class VQE(QuantumAlgorithm):
|
|
258
259
|
|
259
260
|
def run(
|
260
261
|
self,
|
261
|
-
initial_parameters:
|
262
|
+
initial_parameters: np.ndarray | None = None,
|
262
263
|
**optimizer_kwargs
|
263
|
-
) ->
|
264
|
+
) -> dict[str, Any]:
|
264
265
|
"""Run VQE optimization
|
265
|
-
|
266
|
+
|
266
267
|
Args:
|
267
268
|
initial_parameters: Initial parameter values
|
268
269
|
**optimizer_kwargs: Additional optimizer parameters
|
269
|
-
|
270
|
+
|
270
271
|
Returns:
|
271
272
|
VQE results dictionary
|
272
273
|
|
@@ -312,13 +313,13 @@ class QAOA(QuantumAlgorithm):
|
|
312
313
|
def __init__(
|
313
314
|
self,
|
314
315
|
cost_hamiltonian: Hamiltonian,
|
315
|
-
mixer_hamiltonian:
|
316
|
+
mixer_hamiltonian: Hamiltonian | None = None,
|
316
317
|
p: int = 1,
|
317
|
-
client:
|
318
|
+
client: SuperQuantXClient | None = None,
|
318
319
|
optimizer: str = "SLSQP"
|
319
320
|
):
|
320
321
|
"""Initialize QAOA
|
321
|
-
|
322
|
+
|
322
323
|
Args:
|
323
324
|
cost_hamiltonian: Problem Hamiltonian
|
324
325
|
mixer_hamiltonian: Mixer Hamiltonian (default: X on all qubits)
|
@@ -345,10 +346,10 @@ class QAOA(QuantumAlgorithm):
|
|
345
346
|
|
346
347
|
def create_qaoa_circuit(self, parameters: np.ndarray) -> QuantumCircuit:
|
347
348
|
"""Create QAOA circuit with given parameters
|
348
|
-
|
349
|
+
|
349
350
|
Args:
|
350
351
|
parameters: [beta_1, gamma_1, beta_2, gamma_2, ...] for p layers
|
351
|
-
|
352
|
+
|
352
353
|
Returns:
|
353
354
|
QAOA quantum circuit
|
354
355
|
|
@@ -458,15 +459,15 @@ class QAOA(QuantumAlgorithm):
|
|
458
459
|
|
459
460
|
def run(
|
460
461
|
self,
|
461
|
-
initial_parameters:
|
462
|
+
initial_parameters: np.ndarray | None = None,
|
462
463
|
**optimizer_kwargs
|
463
|
-
) ->
|
464
|
+
) -> dict[str, Any]:
|
464
465
|
"""Run QAOA optimization
|
465
|
-
|
466
|
+
|
466
467
|
Args:
|
467
468
|
initial_parameters: Initial [beta, gamma] parameters
|
468
469
|
**optimizer_kwargs: Additional optimizer options
|
469
|
-
|
470
|
+
|
470
471
|
Returns:
|
471
472
|
QAOA results
|
472
473
|
|
@@ -502,12 +503,12 @@ class QuantumNeuralNetwork(BaseEstimator):
|
|
502
503
|
num_qubits: int,
|
503
504
|
num_layers: int = 2,
|
504
505
|
entangling_gates: str = "CNOT",
|
505
|
-
client:
|
506
|
+
client: SuperQuantXClient | None = None,
|
506
507
|
optimizer: str = "SLSQP",
|
507
508
|
learning_rate: float = 0.01
|
508
509
|
):
|
509
510
|
"""Initialize Quantum Neural Network
|
510
|
-
|
511
|
+
|
511
512
|
Args:
|
512
513
|
num_qubits: Number of qubits
|
513
514
|
num_layers: Number of variational layers
|
@@ -526,17 +527,17 @@ class QuantumNeuralNetwork(BaseEstimator):
|
|
526
527
|
|
527
528
|
# Calculate number of parameters
|
528
529
|
self.num_parameters = num_qubits * num_layers * 3 # 3 rotation angles per qubit per layer
|
529
|
-
self.parameters:
|
530
|
+
self.parameters: np.ndarray | None = None
|
530
531
|
|
531
532
|
self.is_fitted_ = False
|
532
533
|
|
533
|
-
def create_ansatz(self, parameters: np.ndarray, x:
|
534
|
+
def create_ansatz(self, parameters: np.ndarray, x: np.ndarray | None = None) -> QuantumCircuit:
|
534
535
|
"""Create parameterized quantum circuit ansatz
|
535
|
-
|
536
|
+
|
536
537
|
Args:
|
537
538
|
parameters: Variational parameters
|
538
539
|
x: Input data for encoding (optional)
|
539
|
-
|
540
|
+
|
540
541
|
Returns:
|
541
542
|
Quantum circuit
|
542
543
|
|
@@ -581,11 +582,11 @@ class QuantumNeuralNetwork(BaseEstimator):
|
|
581
582
|
|
582
583
|
def forward(self, X: np.ndarray, parameters: np.ndarray) -> np.ndarray:
|
583
584
|
"""Forward pass through quantum neural network
|
584
|
-
|
585
|
+
|
585
586
|
Args:
|
586
587
|
X: Input data
|
587
588
|
parameters: Network parameters
|
588
|
-
|
589
|
+
|
589
590
|
Returns:
|
590
591
|
Output predictions
|
591
592
|
|
@@ -642,11 +643,11 @@ class QuantumNeuralNetwork(BaseEstimator):
|
|
642
643
|
|
643
644
|
def fit(self, X: np.ndarray, y: np.ndarray) -> "QuantumNeuralNetwork":
|
644
645
|
"""Fit the quantum neural network
|
645
|
-
|
646
|
+
|
646
647
|
Args:
|
647
648
|
X: Training data
|
648
649
|
y: Training labels
|
649
|
-
|
650
|
+
|
650
651
|
Returns:
|
651
652
|
Fitted model
|
652
653
|
|
@@ -668,10 +669,10 @@ class QuantumNeuralNetwork(BaseEstimator):
|
|
668
669
|
|
669
670
|
def predict(self, X: np.ndarray) -> np.ndarray:
|
670
671
|
"""Make predictions
|
671
|
-
|
672
|
+
|
672
673
|
Args:
|
673
674
|
X: Input data
|
674
|
-
|
675
|
+
|
675
676
|
Returns:
|
676
677
|
Predictions
|
677
678
|
|
@@ -683,11 +684,11 @@ class QuantumNeuralNetwork(BaseEstimator):
|
|
683
684
|
|
684
685
|
def score(self, X: np.ndarray, y: np.ndarray) -> float:
|
685
686
|
"""Calculate R² score
|
686
|
-
|
687
|
+
|
687
688
|
Args:
|
688
689
|
X: Test data
|
689
690
|
y: True labels
|
690
|
-
|
691
|
+
|
691
692
|
Returns:
|
692
693
|
R² score
|
693
694
|
|
@@ -702,9 +703,9 @@ class QuantumFourierTransform(QuantumAlgorithm):
|
|
702
703
|
"""Quantum Fourier Transform implementation
|
703
704
|
"""
|
704
705
|
|
705
|
-
def __init__(self, num_qubits: int, client:
|
706
|
+
def __init__(self, num_qubits: int, client: SuperQuantXClient | None = None):
|
706
707
|
"""Initialize QFT
|
707
|
-
|
708
|
+
|
708
709
|
Args:
|
709
710
|
num_qubits: Number of qubits
|
710
711
|
client: SuperQuantX client
|
@@ -715,10 +716,10 @@ class QuantumFourierTransform(QuantumAlgorithm):
|
|
715
716
|
|
716
717
|
def create_qft_circuit(self, inverse: bool = False) -> QuantumCircuit:
|
717
718
|
"""Create QFT circuit
|
718
|
-
|
719
|
+
|
719
720
|
Args:
|
720
721
|
inverse: Whether to create inverse QFT
|
721
|
-
|
722
|
+
|
722
723
|
Returns:
|
723
724
|
QFT circuit
|
724
725
|
|
@@ -746,12 +747,12 @@ class QuantumFourierTransform(QuantumAlgorithm):
|
|
746
747
|
|
747
748
|
return circuit
|
748
749
|
|
749
|
-
def run(self, initial_state:
|
750
|
+
def run(self, initial_state: np.ndarray | None = None) -> dict[str, Any]:
|
750
751
|
"""Execute QFT
|
751
|
-
|
752
|
+
|
752
753
|
Args:
|
753
754
|
initial_state: Initial quantum state
|
754
|
-
|
755
|
+
|
755
756
|
Returns:
|
756
757
|
QFT results
|
757
758
|
|
@@ -787,15 +788,15 @@ class QuantumFourierTransform(QuantumAlgorithm):
|
|
787
788
|
def create_vqe_for_molecule(
|
788
789
|
molecule_name: str,
|
789
790
|
basis_set: str = "sto-3g",
|
790
|
-
client:
|
791
|
+
client: SuperQuantXClient | None = None
|
791
792
|
) -> VQE:
|
792
793
|
"""Create VQE instance for molecular ground state calculation
|
793
|
-
|
794
|
+
|
794
795
|
Args:
|
795
796
|
molecule_name: Molecule identifier (e.g., "H2", "LiH")
|
796
797
|
basis_set: Quantum chemistry basis set
|
797
798
|
client: SuperQuantX client
|
798
|
-
|
799
|
+
|
799
800
|
Returns:
|
800
801
|
Configured VQE instance
|
801
802
|
|
@@ -829,19 +830,19 @@ def create_vqe_for_molecule(
|
|
829
830
|
|
830
831
|
|
831
832
|
def create_qaoa_for_max_cut(
|
832
|
-
graph_edges:
|
833
|
+
graph_edges: list[tuple[int, int]],
|
833
834
|
num_nodes: int,
|
834
835
|
p: int = 1,
|
835
|
-
client:
|
836
|
+
client: SuperQuantXClient | None = None
|
836
837
|
) -> QAOA:
|
837
838
|
"""Create QAOA instance for Max-Cut problem
|
838
|
-
|
839
|
+
|
839
840
|
Args:
|
840
841
|
graph_edges: List of graph edges as (node1, node2) tuples
|
841
842
|
num_nodes: Number of nodes in graph
|
842
843
|
p: QAOA depth parameter
|
843
844
|
client: SuperQuantX client
|
844
|
-
|
845
|
+
|
845
846
|
Returns:
|
846
847
|
Configured QAOA instance
|
847
848
|
|
superquantx/backends/__init__.py
CHANGED
@@ -85,20 +85,20 @@ BACKEND_ALIASES = {
|
|
85
85
|
'local': 'simulator',
|
86
86
|
}
|
87
87
|
|
88
|
-
def get_backend(backend:
|
88
|
+
def get_backend(backend: str | BaseBackend, **kwargs) -> BaseBackend:
|
89
89
|
"""Get a quantum backend instance.
|
90
|
-
|
90
|
+
|
91
91
|
Args:
|
92
92
|
backend: Backend name or instance
|
93
93
|
**kwargs: Backend configuration parameters
|
94
|
-
|
94
|
+
|
95
95
|
Returns:
|
96
96
|
Backend instance
|
97
|
-
|
97
|
+
|
98
98
|
Raises:
|
99
99
|
ValueError: If backend is not supported
|
100
100
|
ImportError: If backend dependencies are missing
|
101
|
-
|
101
|
+
|
102
102
|
Example:
|
103
103
|
>>> backend = get_backend('pennylane', device='default.qubit')
|
104
104
|
>>> backend = get_backend('qiskit', provider='IBMQ')
|
@@ -136,7 +136,7 @@ def get_backend(backend: Union[str, BaseBackend], **kwargs) -> BaseBackend:
|
|
136
136
|
|
137
137
|
def _auto_select_backend() -> str:
|
138
138
|
"""Automatically select the best available backend.
|
139
|
-
|
139
|
+
|
140
140
|
Returns:
|
141
141
|
Backend name
|
142
142
|
|
@@ -148,7 +148,7 @@ def _auto_select_backend() -> str:
|
|
148
148
|
try:
|
149
149
|
backend_class = BACKEND_REGISTRY[backend_name]
|
150
150
|
# Try to instantiate with minimal config
|
151
|
-
|
151
|
+
backend_class()
|
152
152
|
logger.info(f"Auto-selected backend: {backend_name}")
|
153
153
|
return backend_name
|
154
154
|
except (ImportError, Exception) as e:
|
@@ -159,9 +159,9 @@ def _auto_select_backend() -> str:
|
|
159
159
|
logger.warning("No preferred backends available, falling back to simulator")
|
160
160
|
return 'simulator'
|
161
161
|
|
162
|
-
def list_available_backends() ->
|
162
|
+
def list_available_backends() -> dict[str, dict[str, Any]]:
|
163
163
|
"""List all available backends and their status.
|
164
|
-
|
164
|
+
|
165
165
|
Returns:
|
166
166
|
Dictionary with backend information
|
167
167
|
|
@@ -196,12 +196,12 @@ def list_available_backends() -> Dict[str, Dict[str, Any]]:
|
|
196
196
|
|
197
197
|
return backend_info
|
198
198
|
|
199
|
-
def check_backend_compatibility(backend_name: str) ->
|
199
|
+
def check_backend_compatibility(backend_name: str) -> dict[str, Any]:
|
200
200
|
"""Check compatibility and requirements for a specific backend.
|
201
|
-
|
201
|
+
|
202
202
|
Args:
|
203
203
|
backend_name: Name of the backend to check
|
204
|
-
|
204
|
+
|
205
205
|
Returns:
|
206
206
|
Compatibility information
|
207
207
|
|
@@ -6,7 +6,7 @@ must implement to work with SuperQuantX algorithms.
|
|
6
6
|
|
7
7
|
import logging
|
8
8
|
from abc import ABC, abstractmethod
|
9
|
-
from typing import Any
|
9
|
+
from typing import Any
|
10
10
|
|
11
11
|
import numpy as np
|
12
12
|
|
@@ -15,11 +15,11 @@ logger = logging.getLogger(__name__)
|
|
15
15
|
|
16
16
|
class BaseBackend(ABC):
|
17
17
|
"""Abstract base class for quantum computing backends.
|
18
|
-
|
18
|
+
|
19
19
|
This class defines the interface that all quantum backends must implement
|
20
20
|
to provide quantum circuit execution, measurement, and algorithm-specific
|
21
21
|
operations for SuperQuantX.
|
22
|
-
|
22
|
+
|
23
23
|
Args:
|
24
24
|
device: Device or simulator to use
|
25
25
|
shots: Default number of measurement shots
|
@@ -27,7 +27,7 @@ class BaseBackend(ABC):
|
|
27
27
|
|
28
28
|
"""
|
29
29
|
|
30
|
-
def __init__(self, device:
|
30
|
+
def __init__(self, device: str | None = None, shots: int = 1024, **kwargs):
|
31
31
|
self.device = device
|
32
32
|
self.shots = shots
|
33
33
|
self.config = kwargs
|
@@ -50,18 +50,18 @@ class BaseBackend(ABC):
|
|
50
50
|
pass
|
51
51
|
|
52
52
|
@abstractmethod
|
53
|
-
def add_gate(self, circuit: Any, gate: str, qubits:
|
54
|
-
params:
|
53
|
+
def add_gate(self, circuit: Any, gate: str, qubits: int | list[int],
|
54
|
+
params: list[float] | None = None) -> Any:
|
55
55
|
"""Add a quantum gate to the circuit."""
|
56
56
|
pass
|
57
57
|
|
58
58
|
@abstractmethod
|
59
|
-
def add_measurement(self, circuit: Any, qubits:
|
59
|
+
def add_measurement(self, circuit: Any, qubits: list[int] | None = None) -> Any:
|
60
60
|
"""Add measurement operations to the circuit."""
|
61
61
|
pass
|
62
62
|
|
63
63
|
@abstractmethod
|
64
|
-
def execute_circuit(self, circuit: Any, shots:
|
64
|
+
def execute_circuit(self, circuit: Any, shots: int | None = None) -> dict[str, Any]:
|
65
65
|
"""Execute quantum circuit and return results."""
|
66
66
|
pass
|
67
67
|
|
@@ -80,7 +80,7 @@ class BaseBackend(ABC):
|
|
80
80
|
return self.create_circuit(n_features)
|
81
81
|
|
82
82
|
def compute_kernel_matrix(self, X1: np.ndarray, X2: np.ndarray,
|
83
|
-
feature_map: Any, shots:
|
83
|
+
feature_map: Any, shots: int | None = None) -> np.ndarray:
|
84
84
|
"""Compute quantum kernel matrix between data points."""
|
85
85
|
logger.warning(f"Kernel matrix computation not implemented in {self.__class__.__name__}")
|
86
86
|
# Fallback to RBF kernel
|
@@ -94,7 +94,7 @@ class BaseBackend(ABC):
|
|
94
94
|
return self.create_circuit(n_qubits)
|
95
95
|
|
96
96
|
def compute_expectation(self, circuit: Any, hamiltonian: Any,
|
97
|
-
shots:
|
97
|
+
shots: int | None = None) -> float:
|
98
98
|
"""Compute expectation value of Hamiltonian."""
|
99
99
|
logger.warning(f"Expectation computation not implemented in {self.__class__.__name__}")
|
100
100
|
return 0.0
|
@@ -107,12 +107,12 @@ class BaseBackend(ABC):
|
|
107
107
|
return self.create_circuit(n_qubits)
|
108
108
|
|
109
109
|
def execute_qaoa(self, circuit: Any, problem_hamiltonian: Any, problem_instance: Any,
|
110
|
-
shots:
|
110
|
+
shots: int | None = None) -> float:
|
111
111
|
"""Execute QAOA circuit and return expectation value."""
|
112
112
|
logger.warning(f"QAOA execution not implemented in {self.__class__.__name__}")
|
113
113
|
return 0.0
|
114
114
|
|
115
|
-
def sample_circuit(self, circuit: Any, shots:
|
115
|
+
def sample_circuit(self, circuit: Any, shots: int | None = None) -> np.ndarray:
|
116
116
|
"""Sample bit strings from quantum circuit."""
|
117
117
|
result = self.execute_circuit(circuit, shots)
|
118
118
|
# Convert result to bit string array
|
@@ -141,9 +141,9 @@ class BaseBackend(ABC):
|
|
141
141
|
# Normalize data
|
142
142
|
norm = np.linalg.norm(data)
|
143
143
|
if norm > 0:
|
144
|
-
|
144
|
+
data / norm
|
145
145
|
else:
|
146
|
-
|
146
|
+
pass
|
147
147
|
|
148
148
|
# Simple implementation - would need proper state preparation
|
149
149
|
logger.warning("Amplitude encoding not fully implemented")
|
@@ -173,8 +173,8 @@ class BaseBackend(ABC):
|
|
173
173
|
encoding: str, n_qubits: int, shots: int) -> float:
|
174
174
|
"""Compute quantum distance between two data points."""
|
175
175
|
# Encode both data points
|
176
|
-
|
177
|
-
|
176
|
+
self.encode_data_point(x1, encoding, n_qubits)
|
177
|
+
self.encode_data_point(x2, encoding, n_qubits)
|
178
178
|
|
179
179
|
# Simple distance approximation using overlap
|
180
180
|
# This is a placeholder - actual implementation would use swap test or similar
|
@@ -186,10 +186,10 @@ class BaseBackend(ABC):
|
|
186
186
|
return np.linalg.norm(x1 - x2)
|
187
187
|
|
188
188
|
def execute_qnn(self, input_data: np.ndarray, weights: np.ndarray,
|
189
|
-
quantum_layers:
|
189
|
+
quantum_layers: list[dict], classical_layers: list[dict],
|
190
190
|
encoding: str, measurement: str, shots: int) -> np.ndarray:
|
191
191
|
"""Execute quantum neural network."""
|
192
|
-
|
192
|
+
input_data.shape[0]
|
193
193
|
n_qubits = len(weights) // len(quantum_layers) if quantum_layers else 1
|
194
194
|
|
195
195
|
# Get expected output size from classical layers
|
@@ -226,7 +226,7 @@ class BaseBackend(ABC):
|
|
226
226
|
result = self._result_to_probabilities(result)
|
227
227
|
|
228
228
|
# Apply classical layers if present
|
229
|
-
|
229
|
+
len(result)
|
230
230
|
if classical_layers and expected_output_size:
|
231
231
|
# Simple linear transformation to get desired output size
|
232
232
|
if len(result) != expected_output_size:
|
@@ -271,7 +271,7 @@ class BaseBackend(ABC):
|
|
271
271
|
"""Get number of qubits in circuit."""
|
272
272
|
pass
|
273
273
|
|
274
|
-
def _result_to_bitstrings(self, result:
|
274
|
+
def _result_to_bitstrings(self, result: dict[str, Any]) -> np.ndarray:
|
275
275
|
"""Convert execution result to bit string array."""
|
276
276
|
# This is backend-specific and should be overridden
|
277
277
|
if 'counts' in result:
|
@@ -284,7 +284,7 @@ class BaseBackend(ABC):
|
|
284
284
|
else:
|
285
285
|
return np.array([[0, 1]]) # Placeholder
|
286
286
|
|
287
|
-
def _result_to_probabilities(self, result:
|
287
|
+
def _result_to_probabilities(self, result: dict[str, Any]) -> np.ndarray:
|
288
288
|
"""Convert execution result to probability array."""
|
289
289
|
if 'counts' in result:
|
290
290
|
counts = result['counts']
|
@@ -296,20 +296,21 @@ class BaseBackend(ABC):
|
|
296
296
|
else:
|
297
297
|
return np.array([0.5, 0.5]) # Placeholder
|
298
298
|
|
299
|
-
def _compute_pauli_expectation(self, circuit: Any, pauli_strings:
|
299
|
+
def _compute_pauli_expectation(self, circuit: Any, pauli_strings: list[str]) -> np.ndarray:
|
300
300
|
"""Compute expectation values of Pauli strings."""
|
301
301
|
# Placeholder implementation
|
302
302
|
return np.random.random(len(pauli_strings)) * 2 - 1
|
303
303
|
|
304
|
-
def get_version_info(self) ->
|
304
|
+
def get_version_info(self) -> dict[str, Any]:
|
305
305
|
"""Get backend version information."""
|
306
306
|
return {
|
307
307
|
'backend_name': self.__class__.__name__,
|
308
308
|
'device': self.device,
|
309
309
|
'capabilities': self.capabilities,
|
310
|
+
'backend_version': '1.0.0', # Default backend version
|
310
311
|
}
|
311
312
|
|
312
|
-
def get_device_info(self) ->
|
313
|
+
def get_device_info(self) -> dict[str, Any]:
|
313
314
|
"""Get information about the quantum device."""
|
314
315
|
return {
|
315
316
|
'device': self.device,
|