quantumflow-sdk 0.1.0__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.
Files changed (60) hide show
  1. api/__init__.py +1 -0
  2. api/auth.py +208 -0
  3. api/main.py +403 -0
  4. api/models.py +137 -0
  5. api/routes/__init__.py +1 -0
  6. api/routes/auth_routes.py +234 -0
  7. api/routes/teleport_routes.py +415 -0
  8. db/__init__.py +15 -0
  9. db/crud.py +319 -0
  10. db/database.py +93 -0
  11. db/models.py +197 -0
  12. quantumflow/__init__.py +47 -0
  13. quantumflow/algorithms/__init__.py +48 -0
  14. quantumflow/algorithms/compression/__init__.py +7 -0
  15. quantumflow/algorithms/compression/amplitude_amplification.py +189 -0
  16. quantumflow/algorithms/compression/qft_compression.py +133 -0
  17. quantumflow/algorithms/compression/token_compression.py +261 -0
  18. quantumflow/algorithms/cryptography/__init__.py +6 -0
  19. quantumflow/algorithms/cryptography/qkd.py +205 -0
  20. quantumflow/algorithms/cryptography/qrng.py +231 -0
  21. quantumflow/algorithms/machine_learning/__init__.py +7 -0
  22. quantumflow/algorithms/machine_learning/qnn.py +276 -0
  23. quantumflow/algorithms/machine_learning/qsvm.py +249 -0
  24. quantumflow/algorithms/machine_learning/vqe.py +229 -0
  25. quantumflow/algorithms/optimization/__init__.py +7 -0
  26. quantumflow/algorithms/optimization/grover.py +223 -0
  27. quantumflow/algorithms/optimization/qaoa.py +251 -0
  28. quantumflow/algorithms/optimization/quantum_annealing.py +237 -0
  29. quantumflow/algorithms/utility/__init__.py +6 -0
  30. quantumflow/algorithms/utility/circuit_optimizer.py +194 -0
  31. quantumflow/algorithms/utility/error_correction.py +330 -0
  32. quantumflow/api/__init__.py +1 -0
  33. quantumflow/api/routes/__init__.py +4 -0
  34. quantumflow/api/routes/billing_routes.py +520 -0
  35. quantumflow/backends/__init__.py +33 -0
  36. quantumflow/backends/base_backend.py +184 -0
  37. quantumflow/backends/braket_backend.py +345 -0
  38. quantumflow/backends/ibm_backend.py +112 -0
  39. quantumflow/backends/simulator_backend.py +86 -0
  40. quantumflow/billing/__init__.py +25 -0
  41. quantumflow/billing/models.py +126 -0
  42. quantumflow/billing/stripe_service.py +619 -0
  43. quantumflow/core/__init__.py +12 -0
  44. quantumflow/core/entanglement.py +164 -0
  45. quantumflow/core/memory.py +147 -0
  46. quantumflow/core/quantum_backprop.py +394 -0
  47. quantumflow/core/quantum_compressor.py +309 -0
  48. quantumflow/core/teleportation.py +386 -0
  49. quantumflow/integrations/__init__.py +107 -0
  50. quantumflow/integrations/autogen_tools.py +501 -0
  51. quantumflow/integrations/crewai_agents.py +425 -0
  52. quantumflow/integrations/crewai_tools.py +407 -0
  53. quantumflow/integrations/langchain_memory.py +385 -0
  54. quantumflow/integrations/langchain_tools.py +366 -0
  55. quantumflow/integrations/mcp_server.py +575 -0
  56. quantumflow_sdk-0.1.0.dist-info/METADATA +190 -0
  57. quantumflow_sdk-0.1.0.dist-info/RECORD +60 -0
  58. quantumflow_sdk-0.1.0.dist-info/WHEEL +5 -0
  59. quantumflow_sdk-0.1.0.dist-info/entry_points.txt +2 -0
  60. quantumflow_sdk-0.1.0.dist-info/top_level.txt +3 -0
@@ -0,0 +1,184 @@
1
+ """
2
+ Base Quantum Backend - Abstract interface for quantum hardware/simulators.
3
+
4
+ Supports:
5
+ - IBM Quantum (ibm_fez, etc.)
6
+ - Google Quantum AI
7
+ - AWS Braket
8
+ - Local simulators (Qiskit Aer)
9
+ """
10
+
11
+ from abc import ABC, abstractmethod
12
+ from dataclasses import dataclass, field
13
+ from enum import Enum
14
+ from typing import Any, Optional
15
+ import numpy as np
16
+
17
+ from qiskit import QuantumCircuit
18
+
19
+
20
+ class BackendType(str, Enum):
21
+ """Supported quantum backend types."""
22
+
23
+ SIMULATOR = "simulator"
24
+ IBM = "ibm"
25
+ GOOGLE = "google"
26
+ AWS = "aws"
27
+ AUTO = "auto"
28
+
29
+
30
+ @dataclass
31
+ class ExecutionResult:
32
+ """Result from quantum circuit execution."""
33
+
34
+ counts: dict[str, int]
35
+ statevector: Optional[np.ndarray] = None
36
+ shots: int = 1024
37
+ backend_name: str = "unknown"
38
+ execution_time_ms: float = 0.0
39
+ fidelity: float = 1.0
40
+ metadata: dict[str, Any] = field(default_factory=dict)
41
+
42
+ @property
43
+ def probabilities(self) -> dict[str, float]:
44
+ """Convert counts to probabilities."""
45
+ total = sum(self.counts.values())
46
+ return {k: v / total for k, v in self.counts.items()}
47
+
48
+ @property
49
+ def most_likely_state(self) -> str:
50
+ """Get the most frequently measured state."""
51
+ return max(self.counts, key=self.counts.get)
52
+
53
+ def get_amplitude(self, state: str) -> complex:
54
+ """Get amplitude for a specific basis state."""
55
+ if self.statevector is None:
56
+ raise ValueError("Statevector not available for this result")
57
+ idx = int(state, 2)
58
+ return self.statevector[idx]
59
+
60
+
61
+ class QuantumBackend(ABC):
62
+ """Abstract base class for quantum backends."""
63
+
64
+ def __init__(self, backend_type: BackendType = BackendType.SIMULATOR):
65
+ self.backend_type = backend_type
66
+ self._is_connected = False
67
+
68
+ @abstractmethod
69
+ def connect(self) -> bool:
70
+ """Establish connection to the quantum backend."""
71
+ pass
72
+
73
+ @abstractmethod
74
+ def disconnect(self) -> None:
75
+ """Disconnect from the quantum backend."""
76
+ pass
77
+
78
+ @abstractmethod
79
+ def execute(
80
+ self,
81
+ circuit: QuantumCircuit,
82
+ shots: int = 1024,
83
+ optimization_level: int = 1,
84
+ ) -> ExecutionResult:
85
+ """Execute a quantum circuit on this backend."""
86
+ pass
87
+
88
+ @abstractmethod
89
+ def get_statevector(self, circuit: QuantumCircuit) -> np.ndarray:
90
+ """Get the statevector from a circuit (simulator only)."""
91
+ pass
92
+
93
+ @property
94
+ @abstractmethod
95
+ def max_qubits(self) -> int:
96
+ """Maximum number of qubits supported by this backend."""
97
+ pass
98
+
99
+ @property
100
+ @abstractmethod
101
+ def is_simulator(self) -> bool:
102
+ """Whether this backend is a simulator."""
103
+ pass
104
+
105
+ @property
106
+ def is_connected(self) -> bool:
107
+ """Whether the backend is currently connected."""
108
+ return self._is_connected
109
+
110
+ def validate_circuit(self, circuit: QuantumCircuit) -> bool:
111
+ """Validate that a circuit can run on this backend."""
112
+ if circuit.num_qubits > self.max_qubits:
113
+ raise ValueError(
114
+ f"Circuit requires {circuit.num_qubits} qubits, "
115
+ f"but backend only supports {self.max_qubits}"
116
+ )
117
+ return True
118
+
119
+ def __enter__(self):
120
+ self.connect()
121
+ return self
122
+
123
+ def __exit__(self, exc_type, exc_val, exc_tb):
124
+ self.disconnect()
125
+ return False
126
+
127
+
128
+ def get_backend(
129
+ backend_type: BackendType | str = BackendType.AUTO,
130
+ **kwargs,
131
+ ) -> QuantumBackend:
132
+ """
133
+ Factory function to get the appropriate quantum backend.
134
+
135
+ Args:
136
+ backend_type: Type of backend to use
137
+ **kwargs: Backend-specific configuration
138
+
139
+ Returns:
140
+ Configured QuantumBackend instance
141
+ """
142
+ if isinstance(backend_type, str):
143
+ backend_type = BackendType(backend_type.lower())
144
+
145
+ if backend_type == BackendType.AUTO:
146
+ # Try IBM first if available, fall back to simulator
147
+ try:
148
+ from quantumflow.backends.ibm_backend import IBMBackend
149
+ if IBMBackend is not None:
150
+ backend = IBMBackend(**kwargs)
151
+ if backend.connect():
152
+ return backend
153
+ except Exception:
154
+ pass
155
+
156
+ from quantumflow.backends.simulator_backend import SimulatorBackend
157
+ return SimulatorBackend(**kwargs)
158
+
159
+ elif backend_type == BackendType.SIMULATOR:
160
+ from quantumflow.backends.simulator_backend import SimulatorBackend
161
+ return SimulatorBackend(**kwargs)
162
+
163
+ elif backend_type == BackendType.IBM:
164
+ try:
165
+ from quantumflow.backends.ibm_backend import IBMBackend
166
+ return IBMBackend(**kwargs)
167
+ except ImportError:
168
+ raise ImportError("IBM backend requires qiskit-ibm-runtime. Install with: pip install qiskit-ibm-runtime")
169
+
170
+ elif backend_type == BackendType.GOOGLE:
171
+ raise NotImplementedError("Google Quantum backend not yet implemented")
172
+
173
+ elif backend_type == BackendType.AWS:
174
+ try:
175
+ from quantumflow.backends.braket_backend import BraketBackend
176
+ return BraketBackend(**kwargs)
177
+ except ImportError:
178
+ raise ImportError(
179
+ "AWS Braket backend requires amazon-braket-sdk. "
180
+ "Install with: pip install amazon-braket-sdk"
181
+ )
182
+
183
+ else:
184
+ raise ValueError(f"Unknown backend type: {backend_type}")
@@ -0,0 +1,345 @@
1
+ """
2
+ AWS Braket Backend - Connect to Amazon Braket quantum hardware and simulators.
3
+
4
+ Supports:
5
+ - IonQ (trapped ion)
6
+ - Rigetti (superconducting)
7
+ - OQC (superconducting)
8
+ - AWS Simulators: SV1, DM1, TN1
9
+ """
10
+
11
+ import os
12
+ import time
13
+ from typing import Optional, Literal
14
+ import numpy as np
15
+
16
+ from qiskit import QuantumCircuit
17
+ from qiskit.qasm2 import dumps as qasm2_dumps
18
+
19
+ from quantumflow.backends.base_backend import (
20
+ QuantumBackend,
21
+ BackendType,
22
+ ExecutionResult,
23
+ )
24
+
25
+ # Braket imports - optional dependency
26
+ try:
27
+ from braket.aws import AwsDevice, AwsQuantumTask
28
+ from braket.circuits import Circuit as BraketCircuit
29
+ from braket.devices import LocalSimulator
30
+ BRAKET_AVAILABLE = True
31
+ except ImportError:
32
+ BRAKET_AVAILABLE = False
33
+ # Dummy classes for type hints when Braket not installed
34
+ BraketCircuit = None
35
+ AwsDevice = None
36
+ AwsQuantumTask = None
37
+ LocalSimulator = None
38
+
39
+
40
+ # Device ARNs
41
+ BRAKET_DEVICES = {
42
+ # Hardware
43
+ "ionq_aria": "arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1",
44
+ "ionq_forte": "arn:aws:braket:us-east-1::device/qpu/ionq/Forte-1",
45
+ "rigetti_aspen": "arn:aws:braket:us-west-1::device/qpu/rigetti/Aspen-M-3",
46
+ "oqc_lucy": "arn:aws:braket:eu-west-2::device/qpu/oqc/Lucy",
47
+ # Simulators
48
+ "sv1": "arn:aws:braket:::device/quantum-simulator/amazon/sv1",
49
+ "dm1": "arn:aws:braket:::device/quantum-simulator/amazon/dm1",
50
+ "tn1": "arn:aws:braket:::device/quantum-simulator/amazon/tn1",
51
+ }
52
+
53
+ SIMULATOR_DEVICES = {"sv1", "dm1", "tn1", "local"}
54
+
55
+
56
+ class BraketBackend(QuantumBackend):
57
+ """AWS Braket quantum backend supporting hardware and simulators."""
58
+
59
+ def __init__(
60
+ self,
61
+ device: str = "sv1",
62
+ s3_bucket: Optional[str] = None,
63
+ s3_prefix: str = "quantumflow",
64
+ aws_region: Optional[str] = None,
65
+ ):
66
+ """
67
+ Initialize Braket backend.
68
+
69
+ Args:
70
+ device: Device name (ionq_aria, ionq_forte, rigetti_aspen, oqc_lucy,
71
+ sv1, dm1, tn1, local)
72
+ s3_bucket: S3 bucket for results (required for AWS devices)
73
+ s3_prefix: S3 prefix for results
74
+ aws_region: AWS region override
75
+ """
76
+ super().__init__(BackendType.AWS)
77
+
78
+ if not BRAKET_AVAILABLE:
79
+ raise ImportError(
80
+ "AWS Braket SDK not installed. Install with: "
81
+ "pip install amazon-braket-sdk"
82
+ )
83
+
84
+ self.device_name = device.lower()
85
+ self.s3_bucket = s3_bucket or os.getenv("BRAKET_S3_BUCKET")
86
+ self.s3_prefix = s3_prefix
87
+ self.aws_region = aws_region or os.getenv("AWS_DEFAULT_REGION", "us-east-1")
88
+
89
+ self._device: Optional["AwsDevice"] = None
90
+ self._local_simulator: Optional["LocalSimulator"] = None
91
+
92
+ # Validate device
93
+ if self.device_name not in BRAKET_DEVICES and self.device_name != "local":
94
+ raise ValueError(
95
+ f"Unknown device: {device}. "
96
+ f"Available: {list(BRAKET_DEVICES.keys()) + ['local']}"
97
+ )
98
+
99
+ def connect(self) -> bool:
100
+ """Connect to the Braket device."""
101
+ try:
102
+ if self.device_name == "local":
103
+ self._local_simulator = LocalSimulator()
104
+ self._is_connected = True
105
+ return True
106
+
107
+ device_arn = BRAKET_DEVICES[self.device_name]
108
+ self._device = AwsDevice(device_arn)
109
+
110
+ # Verify S3 bucket for non-local devices
111
+ if not self.s3_bucket and self.device_name not in {"local"}:
112
+ raise ValueError(
113
+ "S3 bucket required for AWS Braket devices. "
114
+ "Set BRAKET_S3_BUCKET env var or pass s3_bucket parameter."
115
+ )
116
+
117
+ self._is_connected = True
118
+ return True
119
+
120
+ except Exception as e:
121
+ raise ConnectionError(f"Failed to connect to Braket device: {e}")
122
+
123
+ def disconnect(self) -> None:
124
+ """Disconnect from the Braket device."""
125
+ self._device = None
126
+ self._local_simulator = None
127
+ self._is_connected = False
128
+
129
+ def _qiskit_to_braket(self, circuit: QuantumCircuit) -> "BraketCircuit":
130
+ """
131
+ Convert Qiskit circuit to Braket circuit.
132
+
133
+ Uses OpenQASM 2.0 as intermediate representation.
134
+ """
135
+ # Get QASM representation
136
+ qasm_str = qasm2_dumps(circuit)
137
+
138
+ # Parse QASM to Braket circuit
139
+ braket_circuit = BraketCircuit.from_ir(qasm_str)
140
+
141
+ return braket_circuit
142
+
143
+ def _qiskit_to_braket_manual(self, circuit: QuantumCircuit) -> "BraketCircuit":
144
+ """
145
+ Manual gate-by-gate conversion from Qiskit to Braket.
146
+
147
+ Fallback if QASM conversion fails.
148
+ """
149
+ braket_circuit = BraketCircuit()
150
+
151
+ # Gate mapping
152
+ gate_map = {
153
+ 'h': lambda bc, q: bc.h(q[0]),
154
+ 'x': lambda bc, q: bc.x(q[0]),
155
+ 'y': lambda bc, q: bc.y(q[0]),
156
+ 'z': lambda bc, q: bc.z(q[0]),
157
+ 's': lambda bc, q: bc.s(q[0]),
158
+ 't': lambda bc, q: bc.t(q[0]),
159
+ 'sdg': lambda bc, q: bc.si(q[0]),
160
+ 'tdg': lambda bc, q: bc.ti(q[0]),
161
+ 'cx': lambda bc, q: bc.cnot(q[0], q[1]),
162
+ 'cz': lambda bc, q: bc.cz(q[0], q[1]),
163
+ 'swap': lambda bc, q: bc.swap(q[0], q[1]),
164
+ 'rx': lambda bc, q, p: bc.rx(q[0], p[0]),
165
+ 'ry': lambda bc, q, p: bc.ry(q[0], p[0]),
166
+ 'rz': lambda bc, q, p: bc.rz(q[0], p[0]),
167
+ }
168
+
169
+ for instruction in circuit.data:
170
+ gate_name = instruction.operation.name.lower()
171
+ qubits = [circuit.find_bit(q).index for q in instruction.qubits]
172
+ params = list(instruction.operation.params)
173
+
174
+ if gate_name == 'measure':
175
+ continue # Braket handles measurement differently
176
+ elif gate_name == 'barrier':
177
+ continue # Skip barriers
178
+ elif gate_name in gate_map:
179
+ if params:
180
+ gate_map[gate_name](braket_circuit, qubits, params)
181
+ else:
182
+ gate_map[gate_name](braket_circuit, qubits)
183
+ else:
184
+ raise ValueError(f"Unsupported gate: {gate_name}")
185
+
186
+ return braket_circuit
187
+
188
+ def execute(
189
+ self,
190
+ circuit: QuantumCircuit,
191
+ shots: int = 1024,
192
+ optimization_level: int = 1,
193
+ ) -> ExecutionResult:
194
+ """Execute a quantum circuit on Braket."""
195
+ if not self._is_connected:
196
+ self.connect()
197
+
198
+ self.validate_circuit(circuit)
199
+ start_time = time.perf_counter()
200
+
201
+ # Convert Qiskit circuit to Braket
202
+ try:
203
+ braket_circuit = self._qiskit_to_braket(circuit)
204
+ except Exception:
205
+ # Fallback to manual conversion
206
+ braket_circuit = self._qiskit_to_braket_manual(circuit)
207
+
208
+ # Execute on device
209
+ if self.device_name == "local":
210
+ # Local simulator
211
+ result = self._local_simulator.run(braket_circuit, shots=shots).result()
212
+ counts = dict(result.measurement_counts)
213
+ else:
214
+ # AWS device
215
+ s3_location = (self.s3_bucket, self.s3_prefix)
216
+ task = self._device.run(braket_circuit, s3_location, shots=shots)
217
+ result = task.result()
218
+ counts = dict(result.measurement_counts)
219
+
220
+ # Convert counts format (Braket uses different bit ordering)
221
+ # Braket: qubit 0 is leftmost, Qiskit: qubit 0 is rightmost
222
+ converted_counts = {}
223
+ for bitstring, count in counts.items():
224
+ # Reverse bit order to match Qiskit convention
225
+ reversed_bits = bitstring[::-1]
226
+ converted_counts[reversed_bits] = count
227
+
228
+ execution_time = (time.perf_counter() - start_time) * 1000
229
+
230
+ return ExecutionResult(
231
+ counts=converted_counts,
232
+ statevector=None,
233
+ shots=shots,
234
+ backend_name=f"braket_{self.device_name}",
235
+ execution_time_ms=execution_time,
236
+ fidelity=self._estimate_fidelity(),
237
+ metadata={
238
+ "device": self.device_name,
239
+ "shots": shots,
240
+ "is_simulator": self.is_simulator,
241
+ },
242
+ )
243
+
244
+ def get_statevector(self, circuit: QuantumCircuit) -> np.ndarray:
245
+ """Get statevector from circuit (simulator only)."""
246
+ if not self.is_simulator:
247
+ raise NotImplementedError(
248
+ "Statevector not available on real quantum hardware"
249
+ )
250
+
251
+ if not self._is_connected:
252
+ self.connect()
253
+
254
+ # Use local simulator for statevector
255
+ if self._local_simulator is None:
256
+ self._local_simulator = LocalSimulator()
257
+
258
+ try:
259
+ braket_circuit = self._qiskit_to_braket(circuit)
260
+ except Exception:
261
+ braket_circuit = self._qiskit_to_braket_manual(circuit)
262
+
263
+ # Run with statevector simulator
264
+ result = self._local_simulator.run(braket_circuit, shots=0).result()
265
+
266
+ # Get statevector from result
267
+ if hasattr(result, 'values') and len(result.values) > 0:
268
+ return np.array(result.values[0])
269
+
270
+ raise ValueError("Could not retrieve statevector from result")
271
+
272
+ @property
273
+ def max_qubits(self) -> int:
274
+ """Maximum qubits supported by this device."""
275
+ qubit_limits = {
276
+ "ionq_aria": 25,
277
+ "ionq_forte": 32,
278
+ "rigetti_aspen": 80,
279
+ "oqc_lucy": 8,
280
+ "sv1": 34,
281
+ "dm1": 17,
282
+ "tn1": 50,
283
+ "local": 26,
284
+ }
285
+ return qubit_limits.get(self.device_name, 26)
286
+
287
+ @property
288
+ def is_simulator(self) -> bool:
289
+ """Whether this backend is a simulator."""
290
+ return self.device_name in SIMULATOR_DEVICES
291
+
292
+ def _estimate_fidelity(self) -> float:
293
+ """Estimate fidelity based on device type."""
294
+ fidelity_estimates = {
295
+ "ionq_aria": 0.995,
296
+ "ionq_forte": 0.997,
297
+ "rigetti_aspen": 0.99,
298
+ "oqc_lucy": 0.98,
299
+ "sv1": 1.0,
300
+ "dm1": 1.0,
301
+ "tn1": 1.0,
302
+ "local": 1.0,
303
+ }
304
+ return fidelity_estimates.get(self.device_name, 0.99)
305
+
306
+ def get_device_status(self) -> dict:
307
+ """Get current device status and availability."""
308
+ if not self._is_connected:
309
+ self.connect()
310
+
311
+ if self.device_name == "local":
312
+ return {
313
+ "device": "local",
314
+ "status": "AVAILABLE",
315
+ "queue_depth": 0,
316
+ }
317
+
318
+ if self._device:
319
+ return {
320
+ "device": self.device_name,
321
+ "status": str(self._device.status),
322
+ "queue_depth": getattr(self._device, 'queue_depth', None),
323
+ "provider": self._device.provider_name,
324
+ }
325
+
326
+ return {"device": self.device_name, "status": "UNKNOWN"}
327
+
328
+ @staticmethod
329
+ def list_available_devices() -> list[dict]:
330
+ """List all available Braket devices."""
331
+ devices = []
332
+ for name, arn in BRAKET_DEVICES.items():
333
+ devices.append({
334
+ "name": name,
335
+ "arn": arn,
336
+ "is_simulator": name in SIMULATOR_DEVICES,
337
+ "provider": arn.split("/")[-2] if "/" in arn else "amazon",
338
+ })
339
+ devices.append({
340
+ "name": "local",
341
+ "arn": None,
342
+ "is_simulator": True,
343
+ "provider": "local",
344
+ })
345
+ return devices
@@ -0,0 +1,112 @@
1
+ """
2
+ IBM Quantum Backend - Connect to IBM Quantum hardware.
3
+
4
+ Validated on IBM ibm_fez (156 qubits) with 99.43% fidelity.
5
+ """
6
+
7
+ import os
8
+ import time
9
+ from typing import Optional
10
+ import numpy as np
11
+ from qiskit import QuantumCircuit, transpile
12
+ from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
13
+
14
+ from quantumflow.backends.base_backend import (
15
+ QuantumBackend,
16
+ BackendType,
17
+ ExecutionResult,
18
+ )
19
+
20
+
21
+ class IBMBackend(QuantumBackend):
22
+ """IBM Quantum hardware backend."""
23
+
24
+ def __init__(
25
+ self,
26
+ token: Optional[str] = None,
27
+ instance: str = "ibm-q/open/main",
28
+ backend_name: str = "ibm_fez",
29
+ ):
30
+ super().__init__(BackendType.IBM)
31
+ self.token = token or os.getenv("IBM_QUANTUM_TOKEN")
32
+ self.instance = instance
33
+ self.backend_name = backend_name
34
+ self._service: Optional[QiskitRuntimeService] = None
35
+ self._backend = None
36
+
37
+ def connect(self) -> bool:
38
+ if not self.token:
39
+ raise ValueError("IBM_QUANTUM_TOKEN not set")
40
+
41
+ try:
42
+ self._service = QiskitRuntimeService(
43
+ channel="ibm_quantum",
44
+ token=self.token,
45
+ instance=self.instance,
46
+ )
47
+ self._backend = self._service.backend(self.backend_name)
48
+ self._is_connected = True
49
+ return True
50
+ except Exception as e:
51
+ raise ConnectionError(f"Failed to connect to IBM Quantum: {e}")
52
+
53
+ def disconnect(self) -> None:
54
+ self._service = None
55
+ self._backend = None
56
+ self._is_connected = False
57
+
58
+ def execute(
59
+ self,
60
+ circuit: QuantumCircuit,
61
+ shots: int = 1024,
62
+ optimization_level: int = 1,
63
+ ) -> ExecutionResult:
64
+ if not self._is_connected:
65
+ self.connect()
66
+
67
+ self.validate_circuit(circuit)
68
+ start_time = time.perf_counter()
69
+
70
+ # Add measurements if needed
71
+ exec_circuit = circuit.copy()
72
+ if not any(inst.operation.name == "measure" for inst in circuit.data):
73
+ exec_circuit.measure_all()
74
+
75
+ # Transpile for hardware
76
+ transpiled = transpile(
77
+ exec_circuit,
78
+ self._backend,
79
+ optimization_level=optimization_level,
80
+ )
81
+
82
+ # Execute via Sampler
83
+ sampler = Sampler(self._backend)
84
+ job = sampler.run([transpiled], shots=shots)
85
+ result = job.result()
86
+
87
+ # Extract counts from pub result
88
+ pub_result = result[0]
89
+ counts = pub_result.data.meas.get_counts()
90
+
91
+ return ExecutionResult(
92
+ counts=counts,
93
+ statevector=None, # Not available on real hardware
94
+ shots=shots,
95
+ backend_name=self.backend_name,
96
+ execution_time_ms=(time.perf_counter() - start_time) * 1000,
97
+ fidelity=0.9943, # Validated fidelity from Paper 1
98
+ metadata={"backend": self.backend_name, "shots": shots},
99
+ )
100
+
101
+ def get_statevector(self, circuit: QuantumCircuit) -> np.ndarray:
102
+ raise NotImplementedError("Statevector not available on real quantum hardware")
103
+
104
+ @property
105
+ def max_qubits(self) -> int:
106
+ if self._backend:
107
+ return self._backend.num_qubits
108
+ return 156 # ibm_fez default
109
+
110
+ @property
111
+ def is_simulator(self) -> bool:
112
+ return False