superquantx 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.
- superquantx/__init__.py +321 -0
- superquantx/algorithms/__init__.py +55 -0
- superquantx/algorithms/base_algorithm.py +413 -0
- superquantx/algorithms/hybrid_classifier.py +628 -0
- superquantx/algorithms/qaoa.py +406 -0
- superquantx/algorithms/quantum_agents.py +1006 -0
- superquantx/algorithms/quantum_kmeans.py +575 -0
- superquantx/algorithms/quantum_nn.py +544 -0
- superquantx/algorithms/quantum_pca.py +499 -0
- superquantx/algorithms/quantum_svm.py +346 -0
- superquantx/algorithms/vqe.py +553 -0
- superquantx/algorithms.py +863 -0
- superquantx/backends/__init__.py +265 -0
- superquantx/backends/base_backend.py +321 -0
- superquantx/backends/braket_backend.py +420 -0
- superquantx/backends/cirq_backend.py +466 -0
- superquantx/backends/ocean_backend.py +491 -0
- superquantx/backends/pennylane_backend.py +419 -0
- superquantx/backends/qiskit_backend.py +451 -0
- superquantx/backends/simulator_backend.py +455 -0
- superquantx/backends/tket_backend.py +519 -0
- superquantx/circuits.py +447 -0
- superquantx/cli/__init__.py +28 -0
- superquantx/cli/commands.py +528 -0
- superquantx/cli/main.py +254 -0
- superquantx/client.py +298 -0
- superquantx/config.py +326 -0
- superquantx/exceptions.py +287 -0
- superquantx/gates.py +588 -0
- superquantx/logging_config.py +347 -0
- superquantx/measurements.py +702 -0
- superquantx/ml.py +936 -0
- superquantx/noise.py +760 -0
- superquantx/utils/__init__.py +83 -0
- superquantx/utils/benchmarking.py +523 -0
- superquantx/utils/classical_utils.py +575 -0
- superquantx/utils/feature_mapping.py +467 -0
- superquantx/utils/optimization.py +410 -0
- superquantx/utils/quantum_utils.py +456 -0
- superquantx/utils/visualization.py +654 -0
- superquantx/version.py +33 -0
- superquantx-0.1.0.dist-info/METADATA +365 -0
- superquantx-0.1.0.dist-info/RECORD +46 -0
- superquantx-0.1.0.dist-info/WHEEL +4 -0
- superquantx-0.1.0.dist-info/entry_points.txt +2 -0
- superquantx-0.1.0.dist-info/licenses/LICENSE +21 -0
superquantx/cli/main.py
ADDED
@@ -0,0 +1,254 @@
|
|
1
|
+
"""Main CLI entry point for SuperQuantX.
|
2
|
+
|
3
|
+
This module provides the main CLI application using Click framework,
|
4
|
+
with subcommands for various quantum machine learning operations.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import sys
|
8
|
+
from pathlib import Path
|
9
|
+
from typing import Optional
|
10
|
+
|
11
|
+
import click
|
12
|
+
|
13
|
+
# Import version directly to avoid circular import
|
14
|
+
from superquantx.version import __version__
|
15
|
+
|
16
|
+
from .commands import (
|
17
|
+
benchmark,
|
18
|
+
configure,
|
19
|
+
create_dataset,
|
20
|
+
info,
|
21
|
+
list_algorithms,
|
22
|
+
list_backends,
|
23
|
+
run_algorithm,
|
24
|
+
visualize,
|
25
|
+
)
|
26
|
+
|
27
|
+
|
28
|
+
@click.group()
|
29
|
+
@click.version_option(version=__version__, prog_name='SuperQuantX')
|
30
|
+
@click.option(
|
31
|
+
'--config', '-c',
|
32
|
+
type=click.Path(exists=True),
|
33
|
+
help='Path to configuration file'
|
34
|
+
)
|
35
|
+
@click.option(
|
36
|
+
'--verbose', '-v',
|
37
|
+
is_flag=True,
|
38
|
+
help='Enable verbose output'
|
39
|
+
)
|
40
|
+
@click.pass_context
|
41
|
+
def cli(ctx: click.Context, config: Optional[str], verbose: bool):
|
42
|
+
"""SuperQuantX: Building the Foundation for Quantum Agentic AI
|
43
|
+
|
44
|
+
Deploy quantum-enhanced autonomous agents and AI systems in minutes.
|
45
|
+
From quantum circuits to intelligent agents across all quantum platforms.
|
46
|
+
|
47
|
+
Examples:
|
48
|
+
sqx create-agent trading # Deploy quantum trading agent
|
49
|
+
sqx run automl --data portfolio # Quantum AutoML optimization
|
50
|
+
sqx run qsvm --data iris # Traditional quantum algorithm
|
51
|
+
sqx benchmark quantum-vs-classical # Performance comparison
|
52
|
+
sqx benchmark --backend all # Benchmark all backends
|
53
|
+
|
54
|
+
"""
|
55
|
+
# Ensure context object exists
|
56
|
+
ctx.ensure_object(dict)
|
57
|
+
|
58
|
+
# Store global options
|
59
|
+
ctx.obj['config'] = config
|
60
|
+
ctx.obj['verbose'] = verbose
|
61
|
+
|
62
|
+
# Load configuration if specified
|
63
|
+
if config:
|
64
|
+
try:
|
65
|
+
sqx.configure(config_file=config)
|
66
|
+
if verbose:
|
67
|
+
click.echo(f"Loaded configuration from {config}")
|
68
|
+
except Exception as e:
|
69
|
+
click.echo(f"Error loading configuration: {e}", err=True)
|
70
|
+
sys.exit(1)
|
71
|
+
|
72
|
+
|
73
|
+
# Add command groups
|
74
|
+
cli.add_command(info)
|
75
|
+
cli.add_command(list_algorithms)
|
76
|
+
cli.add_command(list_backends)
|
77
|
+
cli.add_command(run_algorithm)
|
78
|
+
cli.add_command(benchmark)
|
79
|
+
cli.add_command(configure)
|
80
|
+
cli.add_command(create_dataset)
|
81
|
+
cli.add_command(visualize)
|
82
|
+
|
83
|
+
|
84
|
+
@cli.command()
|
85
|
+
@click.pass_context
|
86
|
+
def version(ctx: click.Context):
|
87
|
+
"""Show detailed version information."""
|
88
|
+
click.echo(f"SuperQuantX version: {sqx.__version__}")
|
89
|
+
click.echo(f"Python version: {sys.version}")
|
90
|
+
|
91
|
+
if ctx.obj.get('verbose'):
|
92
|
+
click.echo("\nBackend versions:")
|
93
|
+
backend_info = sqx.get_backend_info()
|
94
|
+
for backend, version in backend_info.items():
|
95
|
+
status = version if version else "Not installed"
|
96
|
+
click.echo(f" {backend}: {status}")
|
97
|
+
|
98
|
+
|
99
|
+
@cli.command()
|
100
|
+
def shell():
|
101
|
+
"""Start interactive SuperQuantX shell."""
|
102
|
+
try:
|
103
|
+
import matplotlib.pyplot as plt
|
104
|
+
|
105
|
+
# Import common modules for convenience
|
106
|
+
import numpy as np
|
107
|
+
from IPython import embed
|
108
|
+
|
109
|
+
banner = """
|
110
|
+
SuperQuantX Interactive Shell
|
111
|
+
=============================
|
112
|
+
|
113
|
+
Available imports:
|
114
|
+
- superquantx as sqx
|
115
|
+
- numpy as np
|
116
|
+
- matplotlib.pyplot as plt
|
117
|
+
|
118
|
+
Try: sqx.algorithms.QuantumSVM()
|
119
|
+
"""
|
120
|
+
|
121
|
+
embed(banner1=banner, exit_msg="Goodbye!")
|
122
|
+
|
123
|
+
except ImportError:
|
124
|
+
click.echo("IPython not available. Install with: pip install ipython")
|
125
|
+
sys.exit(1)
|
126
|
+
|
127
|
+
|
128
|
+
@cli.command()
|
129
|
+
@click.option(
|
130
|
+
'--output', '-o',
|
131
|
+
type=click.Path(),
|
132
|
+
default='superquantx_examples',
|
133
|
+
help='Output directory for examples'
|
134
|
+
)
|
135
|
+
def examples(output: str):
|
136
|
+
"""Generate example scripts and notebooks."""
|
137
|
+
output_path = Path(output)
|
138
|
+
output_path.mkdir(exist_ok=True)
|
139
|
+
|
140
|
+
# Basic example
|
141
|
+
basic_example = '''#!/usr/bin/env python3
|
142
|
+
"""
|
143
|
+
Basic SuperQuantX Example: Quantum SVM Classification
|
144
|
+
"""
|
145
|
+
|
146
|
+
import numpy as np
|
147
|
+
import superquantx as sqx
|
148
|
+
|
149
|
+
# Load quantum-adapted Iris dataset
|
150
|
+
X_train, X_test, y_train, y_test, metadata = sqx.datasets.load_iris_quantum(
|
151
|
+
n_features=4, encoding='amplitude'
|
152
|
+
)
|
153
|
+
|
154
|
+
print(f"Dataset: {metadata['dataset_name']}")
|
155
|
+
print(f"Training samples: {len(X_train)}")
|
156
|
+
print(f"Test samples: {len(X_test)}")
|
157
|
+
print(f"Features: {metadata['n_features']}")
|
158
|
+
print(f"Classes: {metadata['n_classes']}")
|
159
|
+
|
160
|
+
# Create quantum SVM with automatic backend selection
|
161
|
+
qsvm = sqx.QuantumSVM(
|
162
|
+
backend='auto',
|
163
|
+
feature_map='ZZFeatureMap',
|
164
|
+
quantum_kernel=True
|
165
|
+
)
|
166
|
+
|
167
|
+
# Train the model
|
168
|
+
print("\\nTraining Quantum SVM...")
|
169
|
+
qsvm.fit(X_train, y_train)
|
170
|
+
|
171
|
+
# Make predictions
|
172
|
+
y_pred = qsvm.predict(X_test)
|
173
|
+
|
174
|
+
# Calculate accuracy
|
175
|
+
accuracy = np.mean(y_pred == y_test)
|
176
|
+
print(f"Test Accuracy: {accuracy:.4f}")
|
177
|
+
|
178
|
+
# Visualize results
|
179
|
+
sqx.visualize_results({
|
180
|
+
'y_true': y_test,
|
181
|
+
'y_pred': y_pred,
|
182
|
+
'algorithm': 'QuantumSVM'
|
183
|
+
}, plot_type='classification')
|
184
|
+
'''
|
185
|
+
|
186
|
+
# VQE example
|
187
|
+
vqe_example = '''#!/usr/bin/env python3
|
188
|
+
"""
|
189
|
+
SuperQuantX VQE Example: H2 Molecule Ground State
|
190
|
+
"""
|
191
|
+
|
192
|
+
import superquantx as sqx
|
193
|
+
|
194
|
+
# Load H2 molecule
|
195
|
+
molecule, metadata = sqx.datasets.load_h2_molecule(bond_length=0.735)
|
196
|
+
|
197
|
+
print(f"Molecule: {molecule.name}")
|
198
|
+
print(f"Bond length: {metadata['bond_length']} Å")
|
199
|
+
print(f"Expected ground state energy: {metadata['ground_state_energy']} Ha")
|
200
|
+
|
201
|
+
# Create VQE algorithm
|
202
|
+
vqe = sqx.VQE(
|
203
|
+
backend='auto',
|
204
|
+
ansatz='UCCSD',
|
205
|
+
optimizer='Adam'
|
206
|
+
)
|
207
|
+
|
208
|
+
# Run VQE optimization
|
209
|
+
print("\\nRunning VQE optimization...")
|
210
|
+
result = vqe.compute_minimum_eigenvalue(molecule)
|
211
|
+
|
212
|
+
print(f"VQE ground state energy: {result['eigenvalue']:.6f} Ha")
|
213
|
+
print(f"Number of iterations: {result['n_iterations']}")
|
214
|
+
print(f"Optimization time: {result['optimization_time']:.2f} s")
|
215
|
+
|
216
|
+
# Plot optimization history
|
217
|
+
sqx.plot_optimization_history(result)
|
218
|
+
'''
|
219
|
+
|
220
|
+
# Write examples
|
221
|
+
examples_to_create = [
|
222
|
+
('basic_qsvm.py', basic_example),
|
223
|
+
('vqe_h2.py', vqe_example)
|
224
|
+
]
|
225
|
+
|
226
|
+
for filename, content in examples_to_create:
|
227
|
+
example_path = output_path / filename
|
228
|
+
with open(example_path, 'w') as f:
|
229
|
+
f.write(content)
|
230
|
+
click.echo(f"Created: {example_path}")
|
231
|
+
|
232
|
+
click.echo(f"\\nExamples created in: {output_path}")
|
233
|
+
click.echo("Run with: python basic_qsvm.py")
|
234
|
+
|
235
|
+
|
236
|
+
def create_app():
|
237
|
+
"""Create and return the CLI application."""
|
238
|
+
return cli
|
239
|
+
|
240
|
+
|
241
|
+
def main():
|
242
|
+
"""Main entry point for the CLI."""
|
243
|
+
try:
|
244
|
+
cli()
|
245
|
+
except KeyboardInterrupt:
|
246
|
+
click.echo("\\nInterrupted by user")
|
247
|
+
sys.exit(130)
|
248
|
+
except Exception as e:
|
249
|
+
click.echo(f"Error: {e}", err=True)
|
250
|
+
sys.exit(1)
|
251
|
+
|
252
|
+
|
253
|
+
if __name__ == '__main__':
|
254
|
+
main()
|
superquantx/client.py
ADDED
@@ -0,0 +1,298 @@
|
|
1
|
+
"""SuperQuantX Client - Main interface for the SuperQuantX platform
|
2
|
+
"""
|
3
|
+
|
4
|
+
import asyncio
|
5
|
+
from typing import Any, Dict, List, Optional, Union
|
6
|
+
|
7
|
+
import httpx
|
8
|
+
from pydantic import BaseModel, Field
|
9
|
+
|
10
|
+
|
11
|
+
class SuperQuantXConfig(BaseModel):
|
12
|
+
"""Configuration for SuperQuantX client"""
|
13
|
+
|
14
|
+
api_key: str = Field(..., description="API key for authentication")
|
15
|
+
base_url: str = Field(default="https://api.superquantx.ai", description="Base API URL")
|
16
|
+
timeout: int = Field(default=30, description="Request timeout in seconds")
|
17
|
+
max_retries: int = Field(default=3, description="Maximum number of retries")
|
18
|
+
verify_ssl: bool = Field(default=True, description="Verify SSL certificates")
|
19
|
+
|
20
|
+
|
21
|
+
class QuantumJob(BaseModel):
|
22
|
+
"""Represents a quantum computation job"""
|
23
|
+
|
24
|
+
job_id: str
|
25
|
+
status: str
|
26
|
+
created_at: str
|
27
|
+
circuit_id: Optional[str] = None
|
28
|
+
backend: Optional[str] = None
|
29
|
+
shots: Optional[int] = None
|
30
|
+
results: Optional[Dict[str, Any]] = None
|
31
|
+
error: Optional[str] = None
|
32
|
+
|
33
|
+
|
34
|
+
class SuperQuantXClient:
|
35
|
+
"""Main client for interacting with the SuperQuantX platform
|
36
|
+
|
37
|
+
This client provides access to quantum computing resources, quantum algorithms,
|
38
|
+
and quantum machine learning capabilities through the SuperQuantX API.
|
39
|
+
"""
|
40
|
+
|
41
|
+
def __init__(self, config: Union[SuperQuantXConfig, str, Dict[str, Any]]):
|
42
|
+
"""Initialize SuperQuantX client
|
43
|
+
|
44
|
+
Args:
|
45
|
+
config: Configuration object, API key string, or config dictionary
|
46
|
+
|
47
|
+
"""
|
48
|
+
if isinstance(config, str):
|
49
|
+
self.config = SuperQuantXConfig(api_key=config)
|
50
|
+
elif isinstance(config, dict):
|
51
|
+
self.config = SuperQuantXConfig(**config)
|
52
|
+
else:
|
53
|
+
self.config = config
|
54
|
+
|
55
|
+
self._client = httpx.AsyncClient(
|
56
|
+
base_url=self.config.base_url,
|
57
|
+
timeout=self.config.timeout,
|
58
|
+
verify=self.config.verify_ssl,
|
59
|
+
headers={
|
60
|
+
"Authorization": f"Bearer {self.config.api_key}",
|
61
|
+
"Content-Type": "application/json",
|
62
|
+
"User-Agent": "SuperQuantX-Python-SDK/0.1.0"
|
63
|
+
}
|
64
|
+
)
|
65
|
+
|
66
|
+
async def __aenter__(self):
|
67
|
+
"""Async context manager entry"""
|
68
|
+
return self
|
69
|
+
|
70
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
71
|
+
"""Async context manager exit"""
|
72
|
+
await self._client.aclose()
|
73
|
+
|
74
|
+
def __enter__(self):
|
75
|
+
"""Sync context manager entry"""
|
76
|
+
return self
|
77
|
+
|
78
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
79
|
+
"""Sync context manager exit"""
|
80
|
+
asyncio.run(self._client.aclose())
|
81
|
+
|
82
|
+
async def _request(
|
83
|
+
self,
|
84
|
+
method: str,
|
85
|
+
endpoint: str,
|
86
|
+
data: Optional[Dict[str, Any]] = None,
|
87
|
+
params: Optional[Dict[str, Any]] = None
|
88
|
+
) -> Dict[str, Any]:
|
89
|
+
"""Make an authenticated request to the SuperQuantX API
|
90
|
+
|
91
|
+
Args:
|
92
|
+
method: HTTP method (GET, POST, etc.)
|
93
|
+
endpoint: API endpoint
|
94
|
+
data: Request body data
|
95
|
+
params: Query parameters
|
96
|
+
|
97
|
+
Returns:
|
98
|
+
Response data as dictionary
|
99
|
+
|
100
|
+
Raises:
|
101
|
+
httpx.HTTPError: If request fails
|
102
|
+
|
103
|
+
"""
|
104
|
+
for attempt in range(self.config.max_retries):
|
105
|
+
try:
|
106
|
+
response = await self._client.request(
|
107
|
+
method=method,
|
108
|
+
url=endpoint,
|
109
|
+
json=data,
|
110
|
+
params=params
|
111
|
+
)
|
112
|
+
response.raise_for_status()
|
113
|
+
return response.json()
|
114
|
+
|
115
|
+
except httpx.HTTPError:
|
116
|
+
if attempt == self.config.max_retries - 1:
|
117
|
+
raise
|
118
|
+
await asyncio.sleep(2 ** attempt) # Exponential backoff
|
119
|
+
|
120
|
+
async def health_check(self) -> Dict[str, Any]:
|
121
|
+
"""Check API health and connectivity
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
Health status information
|
125
|
+
|
126
|
+
"""
|
127
|
+
return await self._request("GET", "/health")
|
128
|
+
|
129
|
+
async def get_account_info(self) -> Dict[str, Any]:
|
130
|
+
"""Get account information and usage statistics
|
131
|
+
|
132
|
+
Returns:
|
133
|
+
Account information including quotas and usage
|
134
|
+
|
135
|
+
"""
|
136
|
+
return await self._request("GET", "/account")
|
137
|
+
|
138
|
+
async def list_backends(self) -> List[Dict[str, Any]]:
|
139
|
+
"""List available quantum backends
|
140
|
+
|
141
|
+
Returns:
|
142
|
+
List of available backends with their specifications
|
143
|
+
|
144
|
+
"""
|
145
|
+
response = await self._request("GET", "/backends")
|
146
|
+
return response.get("backends", [])
|
147
|
+
|
148
|
+
async def get_backend_info(self, backend_name: str) -> Dict[str, Any]:
|
149
|
+
"""Get detailed information about a specific backend
|
150
|
+
|
151
|
+
Args:
|
152
|
+
backend_name: Name of the backend
|
153
|
+
|
154
|
+
Returns:
|
155
|
+
Backend information including capabilities and status
|
156
|
+
|
157
|
+
"""
|
158
|
+
return await self._request("GET", f"/backends/{backend_name}")
|
159
|
+
|
160
|
+
async def submit_job(
|
161
|
+
self,
|
162
|
+
circuit_data: Dict[str, Any],
|
163
|
+
backend: str = "simulator",
|
164
|
+
shots: int = 1024,
|
165
|
+
optimization_level: int = 1,
|
166
|
+
**kwargs
|
167
|
+
) -> QuantumJob:
|
168
|
+
"""Submit a quantum circuit for execution
|
169
|
+
|
170
|
+
Args:
|
171
|
+
circuit_data: Quantum circuit representation
|
172
|
+
backend: Target backend for execution
|
173
|
+
shots: Number of measurement shots
|
174
|
+
optimization_level: Circuit optimization level (0-3)
|
175
|
+
**kwargs: Additional execution parameters
|
176
|
+
|
177
|
+
Returns:
|
178
|
+
QuantumJob object representing the submitted job
|
179
|
+
|
180
|
+
"""
|
181
|
+
job_data = {
|
182
|
+
"circuit": circuit_data,
|
183
|
+
"backend": backend,
|
184
|
+
"shots": shots,
|
185
|
+
"optimization_level": optimization_level,
|
186
|
+
**kwargs
|
187
|
+
}
|
188
|
+
|
189
|
+
response = await self._request("POST", "/jobs", data=job_data)
|
190
|
+
return QuantumJob(**response)
|
191
|
+
|
192
|
+
async def get_job(self, job_id: str) -> QuantumJob:
|
193
|
+
"""Get job information and results
|
194
|
+
|
195
|
+
Args:
|
196
|
+
job_id: Job identifier
|
197
|
+
|
198
|
+
Returns:
|
199
|
+
QuantumJob object with current status and results
|
200
|
+
|
201
|
+
"""
|
202
|
+
response = await self._request("GET", f"/jobs/{job_id}")
|
203
|
+
return QuantumJob(**response)
|
204
|
+
|
205
|
+
async def cancel_job(self, job_id: str) -> Dict[str, Any]:
|
206
|
+
"""Cancel a running job
|
207
|
+
|
208
|
+
Args:
|
209
|
+
job_id: Job identifier
|
210
|
+
|
211
|
+
Returns:
|
212
|
+
Cancellation confirmation
|
213
|
+
|
214
|
+
"""
|
215
|
+
return await self._request("DELETE", f"/jobs/{job_id}")
|
216
|
+
|
217
|
+
async def list_jobs(
|
218
|
+
self,
|
219
|
+
limit: int = 100,
|
220
|
+
status: Optional[str] = None,
|
221
|
+
backend: Optional[str] = None
|
222
|
+
) -> List[QuantumJob]:
|
223
|
+
"""List user's jobs with optional filtering
|
224
|
+
|
225
|
+
Args:
|
226
|
+
limit: Maximum number of jobs to return
|
227
|
+
status: Filter by job status
|
228
|
+
backend: Filter by backend
|
229
|
+
|
230
|
+
Returns:
|
231
|
+
List of QuantumJob objects
|
232
|
+
|
233
|
+
"""
|
234
|
+
params = {"limit": limit}
|
235
|
+
if status:
|
236
|
+
params["status"] = status
|
237
|
+
if backend:
|
238
|
+
params["backend"] = backend
|
239
|
+
|
240
|
+
response = await self._request("GET", "/jobs", params=params)
|
241
|
+
return [QuantumJob(**job) for job in response.get("jobs", [])]
|
242
|
+
|
243
|
+
async def wait_for_job(
|
244
|
+
self,
|
245
|
+
job_id: str,
|
246
|
+
timeout: int = 300,
|
247
|
+
poll_interval: int = 5
|
248
|
+
) -> QuantumJob:
|
249
|
+
"""Wait for job completion with polling
|
250
|
+
|
251
|
+
Args:
|
252
|
+
job_id: Job identifier
|
253
|
+
timeout: Maximum wait time in seconds
|
254
|
+
poll_interval: Polling interval in seconds
|
255
|
+
|
256
|
+
Returns:
|
257
|
+
Completed QuantumJob object
|
258
|
+
|
259
|
+
Raises:
|
260
|
+
TimeoutError: If job doesn't complete within timeout
|
261
|
+
|
262
|
+
"""
|
263
|
+
start_time = asyncio.get_event_loop().time()
|
264
|
+
|
265
|
+
while True:
|
266
|
+
job = await self.get_job(job_id)
|
267
|
+
|
268
|
+
if job.status in ["completed", "failed", "cancelled"]:
|
269
|
+
return job
|
270
|
+
|
271
|
+
elapsed = asyncio.get_event_loop().time() - start_time
|
272
|
+
if elapsed > timeout:
|
273
|
+
raise TimeoutError(f"Job {job_id} did not complete within {timeout} seconds")
|
274
|
+
|
275
|
+
await asyncio.sleep(poll_interval)
|
276
|
+
|
277
|
+
# Synchronous wrappers for common operations
|
278
|
+
def health_check_sync(self) -> Dict[str, Any]:
|
279
|
+
"""Synchronous version of health_check"""
|
280
|
+
return asyncio.run(self.health_check())
|
281
|
+
|
282
|
+
def submit_job_sync(
|
283
|
+
self,
|
284
|
+
circuit_data: Dict[str, Any],
|
285
|
+
backend: str = "simulator",
|
286
|
+
shots: int = 1024,
|
287
|
+
**kwargs
|
288
|
+
) -> QuantumJob:
|
289
|
+
"""Synchronous version of submit_job"""
|
290
|
+
return asyncio.run(self.submit_job(circuit_data, backend, shots, **kwargs))
|
291
|
+
|
292
|
+
def get_job_sync(self, job_id: str) -> QuantumJob:
|
293
|
+
"""Synchronous version of get_job"""
|
294
|
+
return asyncio.run(self.get_job(job_id))
|
295
|
+
|
296
|
+
def wait_for_job_sync(self, job_id: str, timeout: int = 300) -> QuantumJob:
|
297
|
+
"""Synchronous version of wait_for_job"""
|
298
|
+
return asyncio.run(self.wait_for_job(job_id, timeout))
|