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 @@ on AWS quantum hardware and simulators.
|
|
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
|
|
@@ -23,7 +23,7 @@ try:
|
|
23
23
|
try:
|
24
24
|
from braket.aws import AwsDevice
|
25
25
|
AWS_AVAILABLE = True
|
26
|
-
except:
|
26
|
+
except ImportError:
|
27
27
|
AWS_AVAILABLE = False
|
28
28
|
BRAKET_AVAILABLE = True
|
29
29
|
except ImportError:
|
@@ -34,22 +34,22 @@ except ImportError:
|
|
34
34
|
|
35
35
|
class BraketBackend(BaseBackend):
|
36
36
|
"""AWS Braket backend for quantum computing operations.
|
37
|
-
|
37
|
+
|
38
38
|
This backend provides access to AWS Braket's quantum devices including
|
39
39
|
local simulators, managed simulators, and QPU hardware from IonQ, Rigetti,
|
40
40
|
and other providers available on AWS.
|
41
|
-
|
41
|
+
|
42
42
|
Args:
|
43
43
|
device: Device name or ARN (e.g., 'local:braket/braket_sv', 'arn:aws:braket::device/qpu/ionq/ionQdevice')
|
44
44
|
shots: Number of measurement shots
|
45
45
|
aws_session: Optional AWS session for authentication
|
46
46
|
s3_folder: S3 bucket folder for results (required for hardware)
|
47
47
|
**kwargs: Additional device configuration
|
48
|
-
|
48
|
+
|
49
49
|
Example:
|
50
50
|
>>> # Local simulator
|
51
51
|
>>> backend = BraketBackend(device='local:braket/braket_sv')
|
52
|
-
>>>
|
52
|
+
>>>
|
53
53
|
>>> # AWS hardware (requires authentication)
|
54
54
|
>>> backend = BraketBackend(
|
55
55
|
... device='arn:aws:braket::device/qpu/ionq/ionQdevice',
|
@@ -63,7 +63,7 @@ class BraketBackend(BaseBackend):
|
|
63
63
|
device: str = 'local:braket/braket_sv',
|
64
64
|
shots: int = 1024,
|
65
65
|
aws_session = None,
|
66
|
-
s3_folder:
|
66
|
+
s3_folder: tuple[str, str] | None = None,
|
67
67
|
**kwargs
|
68
68
|
) -> None:
|
69
69
|
if not BRAKET_AVAILABLE:
|
@@ -122,7 +122,7 @@ class BraketBackend(BaseBackend):
|
|
122
122
|
if hasattr(self._device, 'properties'):
|
123
123
|
try:
|
124
124
|
return self._device.properties.paradigm.qubit_count
|
125
|
-
except:
|
125
|
+
except (AttributeError, Exception):
|
126
126
|
pass
|
127
127
|
# Default estimates
|
128
128
|
if 'sv' in self.device_name:
|
@@ -134,7 +134,7 @@ class BraketBackend(BaseBackend):
|
|
134
134
|
else:
|
135
135
|
return 30 # Conservative estimate for hardware
|
136
136
|
|
137
|
-
def _get_native_gates(self) ->
|
137
|
+
def _get_native_gates(self) -> list[str]:
|
138
138
|
"""Get native gates supported by the device."""
|
139
139
|
# Common Braket gates
|
140
140
|
return [
|
@@ -155,8 +155,8 @@ class BraketBackend(BaseBackend):
|
|
155
155
|
|
156
156
|
return BraketCircuit()
|
157
157
|
|
158
|
-
def add_gate(self, circuit: BraketCircuit, gate: str, qubits:
|
159
|
-
params:
|
158
|
+
def add_gate(self, circuit: BraketCircuit, gate: str, qubits: int | list[int],
|
159
|
+
params: list[float] | None = None) -> BraketCircuit:
|
160
160
|
"""Add a quantum gate to the circuit."""
|
161
161
|
if isinstance(qubits, int):
|
162
162
|
qubits = [qubits]
|
@@ -209,7 +209,7 @@ class BraketBackend(BaseBackend):
|
|
209
209
|
|
210
210
|
return circuit
|
211
211
|
|
212
|
-
def add_measurement(self, circuit: BraketCircuit, qubits:
|
212
|
+
def add_measurement(self, circuit: BraketCircuit, qubits: int | list[int]) -> BraketCircuit:
|
213
213
|
"""Add measurement instructions to specified qubits."""
|
214
214
|
if isinstance(qubits, int):
|
215
215
|
qubits = [qubits]
|
@@ -223,7 +223,7 @@ class BraketBackend(BaseBackend):
|
|
223
223
|
|
224
224
|
return circuit
|
225
225
|
|
226
|
-
def execute_circuit(self, circuit: BraketCircuit, shots:
|
226
|
+
def execute_circuit(self, circuit: BraketCircuit, shots: int | None = None) -> dict[str, Any]:
|
227
227
|
"""Execute quantum circuit and return results."""
|
228
228
|
shots = shots or self.shots
|
229
229
|
|
@@ -281,7 +281,7 @@ class BraketBackend(BaseBackend):
|
|
281
281
|
# Algorithm-Specific Operations
|
282
282
|
# ========================================================================
|
283
283
|
|
284
|
-
def create_parameterized_circuit(self, n_qubits: int, n_params: int) ->
|
284
|
+
def create_parameterized_circuit(self, n_qubits: int, n_params: int) -> tuple[BraketCircuit, list[str]]:
|
285
285
|
"""Create a parameterized quantum circuit for variational algorithms."""
|
286
286
|
circuit = self.create_circuit(n_qubits)
|
287
287
|
|
@@ -294,7 +294,7 @@ class BraketBackend(BaseBackend):
|
|
294
294
|
|
295
295
|
return circuit, param_names
|
296
296
|
|
297
|
-
def bind_parameters(self, circuit: BraketCircuit, param_values:
|
297
|
+
def bind_parameters(self, circuit: BraketCircuit, param_values: dict[str, float]) -> BraketCircuit:
|
298
298
|
"""Bind parameter values to parameterized circuit."""
|
299
299
|
# Braket handles parameterization differently - would need custom implementation
|
300
300
|
# For now, create a new circuit with bound parameters
|
@@ -306,8 +306,8 @@ class BraketBackend(BaseBackend):
|
|
306
306
|
|
307
307
|
return bound_circuit
|
308
308
|
|
309
|
-
def expectation_value(self, circuit: BraketCircuit, observable:
|
310
|
-
shots:
|
309
|
+
def expectation_value(self, circuit: BraketCircuit, observable: str | np.ndarray,
|
310
|
+
shots: int | None = None) -> float:
|
311
311
|
"""Calculate expectation value of observable."""
|
312
312
|
shots = shots or self.shots
|
313
313
|
|
@@ -347,7 +347,7 @@ class BraketBackend(BaseBackend):
|
|
347
347
|
# Backend Information
|
348
348
|
# ========================================================================
|
349
349
|
|
350
|
-
def get_backend_info(self) ->
|
350
|
+
def get_backend_info(self) -> dict[str, Any]:
|
351
351
|
"""Get information about the Braket backend."""
|
352
352
|
info = {
|
353
353
|
'backend_name': 'braket',
|
@@ -366,12 +366,12 @@ class BraketBackend(BaseBackend):
|
|
366
366
|
'provider_name': getattr(props, 'providerName', 'AWS'),
|
367
367
|
'max_qubits': getattr(props.paradigm, 'qubit_count', 'unknown') if hasattr(props, 'paradigm') else 'unknown',
|
368
368
|
})
|
369
|
-
except:
|
369
|
+
except (AttributeError, Exception):
|
370
370
|
pass
|
371
371
|
|
372
372
|
return info
|
373
373
|
|
374
|
-
def get_version_info(self) ->
|
374
|
+
def get_version_info(self) -> dict[str, str]:
|
375
375
|
"""Get version information for Braket dependencies."""
|
376
376
|
import braket
|
377
377
|
return {
|
@@ -383,7 +383,7 @@ class BraketBackend(BaseBackend):
|
|
383
383
|
"""Check if the backend is available and properly configured."""
|
384
384
|
return BRAKET_AVAILABLE and self._device is not None
|
385
385
|
|
386
|
-
def get_circuit_info(self) ->
|
386
|
+
def get_circuit_info(self) -> dict[str, Any]:
|
387
387
|
"""Get information about circuit execution capabilities."""
|
388
388
|
return {
|
389
389
|
'max_qubits': self._get_max_qubits(),
|
@@ -5,7 +5,7 @@ operations and access to Google Quantum AI hardware.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from typing import TYPE_CHECKING, Any
|
8
|
+
from typing import TYPE_CHECKING, Any
|
9
9
|
|
10
10
|
import numpy as np
|
11
11
|
|
@@ -27,10 +27,10 @@ except ImportError:
|
|
27
27
|
|
28
28
|
class CirqBackend(BaseBackend):
|
29
29
|
"""Cirq backend for quantum computing operations.
|
30
|
-
|
30
|
+
|
31
31
|
This backend provides access to Cirq simulators and Google Quantum AI
|
32
32
|
hardware for quantum algorithm execution.
|
33
|
-
|
33
|
+
|
34
34
|
Args:
|
35
35
|
device: Cirq device name ('simulator', 'sycamore', etc.)
|
36
36
|
processor_id: Google Quantum AI processor ID
|
@@ -39,7 +39,7 @@ class CirqBackend(BaseBackend):
|
|
39
39
|
|
40
40
|
"""
|
41
41
|
|
42
|
-
def __init__(self, device: str = 'simulator', processor_id:
|
42
|
+
def __init__(self, device: str = 'simulator', processor_id: str | None = None,
|
43
43
|
shots: int = 1024, **kwargs):
|
44
44
|
if not CIRQ_AVAILABLE:
|
45
45
|
raise ImportError("Cirq is required for CirqBackend. Install with: pip install cirq")
|
@@ -90,8 +90,8 @@ class CirqBackend(BaseBackend):
|
|
90
90
|
circuit = cirq.Circuit()
|
91
91
|
return circuit, qubits # Return both circuit and qubits for convenience
|
92
92
|
|
93
|
-
def add_gate(self, circuit_info:
|
94
|
-
qubits:
|
93
|
+
def add_gate(self, circuit_info: tuple[Any, list], gate: str,
|
94
|
+
qubits: int | list[int], params: list[float] | None = None) -> tuple[Any, list]:
|
95
95
|
"""Add a quantum gate to the circuit."""
|
96
96
|
circuit, qubit_list = circuit_info
|
97
97
|
|
@@ -131,8 +131,8 @@ class CirqBackend(BaseBackend):
|
|
131
131
|
|
132
132
|
return circuit, qubit_list
|
133
133
|
|
134
|
-
def add_measurement(self, circuit_info:
|
135
|
-
qubits:
|
134
|
+
def add_measurement(self, circuit_info: tuple[Any, list],
|
135
|
+
qubits: list[int] | None = None) -> tuple[Any, list]:
|
136
136
|
"""Add measurement operations to the circuit."""
|
137
137
|
circuit, qubit_list = circuit_info
|
138
138
|
|
@@ -144,7 +144,7 @@ class CirqBackend(BaseBackend):
|
|
144
144
|
|
145
145
|
return circuit, qubit_list
|
146
146
|
|
147
|
-
def execute_circuit(self, circuit_info:
|
147
|
+
def execute_circuit(self, circuit_info: Any | tuple, shots: int | None = None) -> dict[str, Any]:
|
148
148
|
"""Execute quantum circuit and return results."""
|
149
149
|
if isinstance(circuit_info, tuple):
|
150
150
|
circuit, qubit_list = circuit_info
|
@@ -202,7 +202,7 @@ class CirqBackend(BaseBackend):
|
|
202
202
|
logger.error(f"Circuit execution failed: {e}")
|
203
203
|
raise
|
204
204
|
|
205
|
-
def get_statevector(self, circuit_info:
|
205
|
+
def get_statevector(self, circuit_info: Any | tuple) -> np.ndarray:
|
206
206
|
"""Get the statevector from a quantum circuit."""
|
207
207
|
if isinstance(circuit_info, tuple):
|
208
208
|
circuit, qubit_list = circuit_info
|
@@ -227,7 +227,7 @@ class CirqBackend(BaseBackend):
|
|
227
227
|
n_qubits = len(qubit_list)
|
228
228
|
return np.array([1.0] + [0.0] * (2**n_qubits - 1))
|
229
229
|
|
230
|
-
def _get_n_qubits(self, circuit_info:
|
230
|
+
def _get_n_qubits(self, circuit_info: Any | tuple) -> int:
|
231
231
|
"""Get number of qubits in circuit."""
|
232
232
|
if isinstance(circuit_info, tuple):
|
233
233
|
circuit, qubit_list = circuit_info
|
@@ -239,10 +239,10 @@ class CirqBackend(BaseBackend):
|
|
239
239
|
# Enhanced Cirq-specific implementations
|
240
240
|
# ========================================================================
|
241
241
|
|
242
|
-
def create_feature_map(self, n_features: int, feature_map: str, reps: int = 1) ->
|
242
|
+
def create_feature_map(self, n_features: int, feature_map: str, reps: int = 1) -> tuple[Any, list]:
|
243
243
|
"""Create quantum feature map for data encoding."""
|
244
|
-
|
245
|
-
|
244
|
+
[cirq.LineQubit(i) for i in range(n_features)]
|
245
|
+
cirq.Circuit()
|
246
246
|
|
247
247
|
if feature_map == 'ZZFeatureMap':
|
248
248
|
circuit_info = self._create_zz_feature_map(n_features, reps)
|
@@ -256,7 +256,7 @@ class CirqBackend(BaseBackend):
|
|
256
256
|
|
257
257
|
return circuit_info
|
258
258
|
|
259
|
-
def _create_zz_feature_map(self, n_features: int, reps: int) ->
|
259
|
+
def _create_zz_feature_map(self, n_features: int, reps: int) -> tuple[Any, list]:
|
260
260
|
"""Create ZZ feature map circuit."""
|
261
261
|
qubits = [cirq.LineQubit(i) for i in range(n_features)]
|
262
262
|
circuit = cirq.Circuit()
|
@@ -277,7 +277,7 @@ class CirqBackend(BaseBackend):
|
|
277
277
|
|
278
278
|
return circuit, qubits
|
279
279
|
|
280
|
-
def _create_pauli_feature_map(self, n_features: int, reps: int) ->
|
280
|
+
def _create_pauli_feature_map(self, n_features: int, reps: int) -> tuple[Any, list]:
|
281
281
|
"""Create Pauli feature map circuit."""
|
282
282
|
qubits = [cirq.LineQubit(i) for i in range(n_features)]
|
283
283
|
circuit = cirq.Circuit()
|
@@ -295,7 +295,7 @@ class CirqBackend(BaseBackend):
|
|
295
295
|
|
296
296
|
return circuit, qubits
|
297
297
|
|
298
|
-
def _create_amplitude_map(self, n_features: int) ->
|
298
|
+
def _create_amplitude_map(self, n_features: int) -> tuple[Any, list]:
|
299
299
|
"""Create amplitude encoding map."""
|
300
300
|
n_qubits = int(np.ceil(np.log2(n_features)))
|
301
301
|
qubits = [cirq.LineQubit(i) for i in range(n_qubits)]
|
@@ -307,7 +307,7 @@ class CirqBackend(BaseBackend):
|
|
307
307
|
|
308
308
|
return circuit, qubits
|
309
309
|
|
310
|
-
def _create_angle_encoding_map(self, n_features: int) ->
|
310
|
+
def _create_angle_encoding_map(self, n_features: int) -> tuple[Any, list]:
|
311
311
|
"""Create angle encoding map."""
|
312
312
|
qubits = [cirq.LineQubit(i) for i in range(n_features)]
|
313
313
|
circuit = cirq.Circuit()
|
@@ -318,7 +318,7 @@ class CirqBackend(BaseBackend):
|
|
318
318
|
return circuit, qubits
|
319
319
|
|
320
320
|
def create_ansatz(self, ansatz_type: str, n_qubits: int, params: np.ndarray,
|
321
|
-
include_custom_gates: bool = False) ->
|
321
|
+
include_custom_gates: bool = False) -> tuple[Any, list]:
|
322
322
|
"""Create parameterized ansatz circuit."""
|
323
323
|
if ansatz_type == 'RealAmplitudes':
|
324
324
|
return self._create_real_amplitudes_ansatz(n_qubits, params)
|
@@ -332,7 +332,7 @@ class CirqBackend(BaseBackend):
|
|
332
332
|
logger.warning(f"Unknown ansatz '{ansatz_type}', using RealAmplitudes")
|
333
333
|
return self._create_real_amplitudes_ansatz(n_qubits, params)
|
334
334
|
|
335
|
-
def _create_real_amplitudes_ansatz(self, n_qubits: int, params: np.ndarray) ->
|
335
|
+
def _create_real_amplitudes_ansatz(self, n_qubits: int, params: np.ndarray) -> tuple[Any, list]:
|
336
336
|
"""Create RealAmplitudes ansatz."""
|
337
337
|
qubits = [cirq.LineQubit(i) for i in range(n_qubits)]
|
338
338
|
circuit = cirq.Circuit()
|
@@ -359,7 +359,7 @@ class CirqBackend(BaseBackend):
|
|
359
359
|
|
360
360
|
return circuit, qubits
|
361
361
|
|
362
|
-
def _create_efficient_su2_ansatz(self, n_qubits: int, params: np.ndarray) ->
|
362
|
+
def _create_efficient_su2_ansatz(self, n_qubits: int, params: np.ndarray) -> tuple[Any, list]:
|
363
363
|
"""Create EfficientSU2 ansatz."""
|
364
364
|
qubits = [cirq.LineQubit(i) for i in range(n_qubits)]
|
365
365
|
circuit = cirq.Circuit()
|
@@ -382,7 +382,7 @@ class CirqBackend(BaseBackend):
|
|
382
382
|
|
383
383
|
return circuit, qubits
|
384
384
|
|
385
|
-
def _create_two_local_ansatz(self, n_qubits: int, params: np.ndarray) ->
|
385
|
+
def _create_two_local_ansatz(self, n_qubits: int, params: np.ndarray) -> tuple[Any, list]:
|
386
386
|
"""Create TwoLocal ansatz."""
|
387
387
|
qubits = [cirq.LineQubit(i) for i in range(n_qubits)]
|
388
388
|
circuit = cirq.Circuit()
|
@@ -406,7 +406,7 @@ class CirqBackend(BaseBackend):
|
|
406
406
|
|
407
407
|
return circuit, qubits
|
408
408
|
|
409
|
-
def _create_uccsd_ansatz(self, n_qubits: int, params: np.ndarray) ->
|
409
|
+
def _create_uccsd_ansatz(self, n_qubits: int, params: np.ndarray) -> tuple[Any, list]:
|
410
410
|
"""Create UCCSD ansatz (simplified)."""
|
411
411
|
qubits = [cirq.LineQubit(i) for i in range(n_qubits)]
|
412
412
|
circuit = cirq.Circuit()
|
@@ -434,8 +434,8 @@ class CirqBackend(BaseBackend):
|
|
434
434
|
|
435
435
|
return circuit, qubits
|
436
436
|
|
437
|
-
def compute_expectation(self, circuit_info:
|
438
|
-
shots:
|
437
|
+
def compute_expectation(self, circuit_info: Any | tuple, hamiltonian: Any,
|
438
|
+
shots: int | None = None) -> float:
|
439
439
|
"""Compute expectation value of Hamiltonian."""
|
440
440
|
try:
|
441
441
|
if isinstance(hamiltonian, np.ndarray):
|
@@ -451,7 +451,7 @@ class CirqBackend(BaseBackend):
|
|
451
451
|
logger.error(f"Expectation computation failed: {e}")
|
452
452
|
return 0.0
|
453
453
|
|
454
|
-
def get_version_info(self) ->
|
454
|
+
def get_version_info(self) -> dict[str, Any]:
|
455
455
|
"""Get Cirq version information."""
|
456
456
|
info = super().get_version_info()
|
457
457
|
|
@@ -3,12 +3,12 @@
|
|
3
3
|
This module provides integration with D-Wave Ocean SDK for quantum annealing
|
4
4
|
and optimization problems using D-Wave quantum annealing processors.
|
5
5
|
|
6
|
-
Note: This backend focuses on QUBO/Ising model problems rather than
|
6
|
+
Note: This backend focuses on QUBO/Ising model problems rather than
|
7
7
|
gate-model quantum circuits.
|
8
8
|
"""
|
9
9
|
|
10
10
|
import logging
|
11
|
-
from typing import Any
|
11
|
+
from typing import Any
|
12
12
|
|
13
13
|
import numpy as np
|
14
14
|
|
@@ -35,13 +35,13 @@ except ImportError:
|
|
35
35
|
|
36
36
|
class OceanBackend(BaseBackend):
|
37
37
|
"""D-Wave Ocean backend for quantum annealing operations.
|
38
|
-
|
38
|
+
|
39
39
|
This backend provides access to D-Wave's quantum annealing systems
|
40
40
|
for solving optimization problems formulated as QUBO or Ising models.
|
41
|
-
|
41
|
+
|
42
42
|
Note: Unlike gate-model quantum computers, D-Wave systems solve optimization
|
43
43
|
problems rather than running quantum circuits.
|
44
|
-
|
44
|
+
|
45
45
|
Args:
|
46
46
|
device: Sampler type ('DWave', 'hybrid', 'simulator', 'advantage')
|
47
47
|
solver: Specific solver name (optional)
|
@@ -49,11 +49,11 @@ class OceanBackend(BaseBackend):
|
|
49
49
|
endpoint: D-Wave API endpoint
|
50
50
|
shots: Number of samples (reads)
|
51
51
|
**kwargs: Additional sampler configuration
|
52
|
-
|
52
|
+
|
53
53
|
Example:
|
54
54
|
>>> # Simulated annealing (no hardware required)
|
55
55
|
>>> backend = OceanBackend(device='simulator')
|
56
|
-
>>>
|
56
|
+
>>>
|
57
57
|
>>> # D-Wave hardware (requires API token)
|
58
58
|
>>> backend = OceanBackend(
|
59
59
|
... device='advantage',
|
@@ -65,9 +65,9 @@ class OceanBackend(BaseBackend):
|
|
65
65
|
def __init__(
|
66
66
|
self,
|
67
67
|
device: str = 'simulator',
|
68
|
-
solver:
|
69
|
-
token:
|
70
|
-
endpoint:
|
68
|
+
solver: str | None = None,
|
69
|
+
token: str | None = None,
|
70
|
+
endpoint: str | None = None,
|
71
71
|
shots: int = 1000, # Called "num_reads" in D-Wave
|
72
72
|
**kwargs
|
73
73
|
) -> None:
|
@@ -141,7 +141,7 @@ class OceanBackend(BaseBackend):
|
|
141
141
|
if hasattr(self._sampler, 'properties'):
|
142
142
|
try:
|
143
143
|
return len(self._sampler.properties['qubits'])
|
144
|
-
except:
|
144
|
+
except (AttributeError, KeyError, Exception):
|
145
145
|
pass
|
146
146
|
|
147
147
|
# Default estimates
|
@@ -156,13 +156,13 @@ class OceanBackend(BaseBackend):
|
|
156
156
|
# Optimization Problem Interface (replaces circuit operations)
|
157
157
|
# ========================================================================
|
158
158
|
|
159
|
-
def solve_qubo(self, Q:
|
159
|
+
def solve_qubo(self, Q: dict[tuple[int, int], float], **kwargs) -> dict[str, Any]:
|
160
160
|
"""Solve a Quadratic Unconstrained Binary Optimization (QUBO) problem.
|
161
|
-
|
161
|
+
|
162
162
|
Args:
|
163
163
|
Q: QUBO dictionary where keys are (i, j) variable pairs and values are coefficients
|
164
164
|
**kwargs: Additional solving parameters
|
165
|
-
|
165
|
+
|
166
166
|
Returns:
|
167
167
|
Solution results with energies and samples
|
168
168
|
|
@@ -204,14 +204,14 @@ class OceanBackend(BaseBackend):
|
|
204
204
|
'problem_type': 'QUBO'
|
205
205
|
}
|
206
206
|
|
207
|
-
def solve_ising(self, h:
|
207
|
+
def solve_ising(self, h: dict[int, float], J: dict[tuple[int, int], float], **kwargs) -> dict[str, Any]:
|
208
208
|
"""Solve an Ising model problem.
|
209
|
-
|
209
|
+
|
210
210
|
Args:
|
211
211
|
h: Linear coefficients (bias terms) for each variable
|
212
212
|
J: Quadratic coefficients (coupling terms) between variables
|
213
213
|
**kwargs: Additional solving parameters
|
214
|
-
|
214
|
+
|
215
215
|
Returns:
|
216
216
|
Solution results with energies and samples
|
217
217
|
|
@@ -253,13 +253,13 @@ class OceanBackend(BaseBackend):
|
|
253
253
|
'problem_type': 'Ising'
|
254
254
|
}
|
255
255
|
|
256
|
-
def solve_optimization_problem(self, problem:
|
256
|
+
def solve_optimization_problem(self, problem: dict | Any, problem_type: str = 'auto') -> dict[str, Any]:
|
257
257
|
"""Generic optimization problem solver.
|
258
|
-
|
258
|
+
|
259
259
|
Args:
|
260
260
|
problem: Problem specification (QUBO dict, Ising model, or BQM)
|
261
261
|
problem_type: Type of problem ('qubo', 'ising', 'bqm', 'auto')
|
262
|
-
|
262
|
+
|
263
263
|
Returns:
|
264
264
|
Solution results
|
265
265
|
|
@@ -296,7 +296,7 @@ class OceanBackend(BaseBackend):
|
|
296
296
|
'problem_type': problem_type
|
297
297
|
}
|
298
298
|
|
299
|
-
def _convert_sampleset(self, sampleset, problem_type: str) ->
|
299
|
+
def _convert_sampleset(self, sampleset, problem_type: str) -> dict[str, Any]:
|
300
300
|
"""Convert D-Wave sampleset to standard format."""
|
301
301
|
results = {
|
302
302
|
'samples': [],
|
@@ -319,9 +319,9 @@ class OceanBackend(BaseBackend):
|
|
319
319
|
# Gate Model Compatibility (Limited Support)
|
320
320
|
# ========================================================================
|
321
321
|
|
322
|
-
def create_circuit(self, n_qubits: int) ->
|
322
|
+
def create_circuit(self, n_qubits: int) -> dict[str, Any]:
|
323
323
|
"""Limited circuit support for compatibility.
|
324
|
-
|
324
|
+
|
325
325
|
Note: D-Wave is not a gate-model quantum computer.
|
326
326
|
This returns a placeholder for optimization problems.
|
327
327
|
"""
|
@@ -333,18 +333,18 @@ class OceanBackend(BaseBackend):
|
|
333
333
|
'problem': None
|
334
334
|
}
|
335
335
|
|
336
|
-
def add_gate(self, circuit:
|
337
|
-
params:
|
336
|
+
def add_gate(self, circuit: dict, gate: str, qubits: int | list[int],
|
337
|
+
params: list[float] | None = None) -> dict:
|
338
338
|
"""Limited gate support - not applicable for annealing."""
|
339
339
|
logger.warning("Gate operations not supported on D-Wave annealing backend")
|
340
340
|
return circuit
|
341
341
|
|
342
|
-
def add_measurement(self, circuit:
|
342
|
+
def add_measurement(self, circuit: dict, qubits: int | list[int]) -> dict:
|
343
343
|
"""Limited measurement support - not applicable for annealing."""
|
344
344
|
logger.warning("Measurements not applicable for D-Wave annealing backend")
|
345
345
|
return circuit
|
346
346
|
|
347
|
-
def execute_circuit(self, circuit:
|
347
|
+
def execute_circuit(self, circuit: dict, shots: int | None = None) -> dict[str, Any]:
|
348
348
|
"""Limited circuit execution - redirects to optimization solving."""
|
349
349
|
logger.warning("Circuit execution not supported - use solve_qubo() or solve_ising() instead")
|
350
350
|
return {
|
@@ -359,7 +359,7 @@ class OceanBackend(BaseBackend):
|
|
359
359
|
# Backend Information
|
360
360
|
# ========================================================================
|
361
361
|
|
362
|
-
def get_backend_info(self) ->
|
362
|
+
def get_backend_info(self) -> dict[str, Any]:
|
363
363
|
"""Get information about the D-Wave Ocean backend."""
|
364
364
|
info = {
|
365
365
|
'backend_name': 'ocean',
|
@@ -379,30 +379,30 @@ class OceanBackend(BaseBackend):
|
|
379
379
|
'num_qubits': len(props.get('qubits', [])),
|
380
380
|
'connectivity': 'Chimera/Pegasus/Zephyr', # D-Wave topologies
|
381
381
|
})
|
382
|
-
except:
|
382
|
+
except (AttributeError, Exception):
|
383
383
|
pass
|
384
384
|
|
385
385
|
return info
|
386
386
|
|
387
|
-
def get_version_info(self) ->
|
387
|
+
def get_version_info(self) -> dict[str, str]:
|
388
388
|
"""Get version information for Ocean dependencies."""
|
389
389
|
version_info = {'backend_version': '1.0.0'}
|
390
390
|
|
391
391
|
try:
|
392
392
|
version_info['dimod'] = dimod.__version__
|
393
|
-
except:
|
393
|
+
except (AttributeError, ImportError):
|
394
394
|
pass
|
395
395
|
|
396
396
|
try:
|
397
397
|
import dwave.system
|
398
398
|
version_info['dwave_system'] = dwave.system.__version__
|
399
|
-
except:
|
399
|
+
except (ImportError, AttributeError):
|
400
400
|
pass
|
401
401
|
|
402
402
|
try:
|
403
403
|
import dwave.samplers
|
404
404
|
version_info['dwave_samplers'] = dwave.samplers.__version__
|
405
|
-
except:
|
405
|
+
except (ImportError, AttributeError):
|
406
406
|
pass
|
407
407
|
|
408
408
|
return version_info
|
@@ -411,7 +411,7 @@ class OceanBackend(BaseBackend):
|
|
411
411
|
"""Check if the backend is available and properly configured."""
|
412
412
|
return OCEAN_AVAILABLE and self._sampler is not None
|
413
413
|
|
414
|
-
def get_circuit_info(self) ->
|
414
|
+
def get_circuit_info(self) -> dict[str, Any]:
|
415
415
|
"""Get circuit capabilities (limited for annealing backend)."""
|
416
416
|
return {
|
417
417
|
'max_qubits': 0, # Not applicable
|
@@ -424,13 +424,13 @@ class OceanBackend(BaseBackend):
|
|
424
424
|
'quantum_annealing': True,
|
425
425
|
}
|
426
426
|
|
427
|
-
def _get_n_qubits(self, circuit:
|
427
|
+
def _get_n_qubits(self, circuit: dict) -> int:
|
428
428
|
"""Get number of qubits/variables (not applicable for annealing)."""
|
429
429
|
if isinstance(circuit, dict):
|
430
430
|
return circuit.get('n_variables', 0)
|
431
431
|
return 0
|
432
432
|
|
433
|
-
def get_statevector(self, circuit:
|
433
|
+
def get_statevector(self, circuit: dict) -> np.ndarray:
|
434
434
|
"""Get statevector (not applicable for annealing backend)."""
|
435
435
|
logger.warning("Statevector not applicable for quantum annealing backend")
|
436
436
|
return np.array([1.0 + 0j]) # Dummy statevector
|
@@ -439,7 +439,7 @@ class OceanBackend(BaseBackend):
|
|
439
439
|
# Convenience Methods for Common Optimization Problems
|
440
440
|
# ========================================================================
|
441
441
|
|
442
|
-
def solve_max_cut(self, graph:
|
442
|
+
def solve_max_cut(self, graph: Any | list[tuple], **kwargs) -> dict[str, Any]:
|
443
443
|
"""Solve Maximum Cut problem on a graph."""
|
444
444
|
try:
|
445
445
|
if not nx:
|
@@ -465,7 +465,7 @@ class OceanBackend(BaseBackend):
|
|
465
465
|
logger.error(f"Max Cut solving failed: {e}")
|
466
466
|
return {'success': False, 'error': str(e)}
|
467
467
|
|
468
|
-
def solve_tsp(self, distance_matrix: np.ndarray, **kwargs) ->
|
468
|
+
def solve_tsp(self, distance_matrix: np.ndarray, **kwargs) -> dict[str, Any]:
|
469
469
|
"""Solve Traveling Salesman Problem (simplified formulation)."""
|
470
470
|
try:
|
471
471
|
n_cities = len(distance_matrix)
|