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
@@ -0,0 +1,528 @@
|
|
1
|
+
"""CLI commands for SuperQuantX.
|
2
|
+
|
3
|
+
This module implements individual CLI commands for various SuperQuantX operations
|
4
|
+
including algorithm execution, benchmarking, configuration, and system information.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import json
|
8
|
+
import sys
|
9
|
+
import time
|
10
|
+
from typing import Optional
|
11
|
+
|
12
|
+
import click
|
13
|
+
import numpy as np
|
14
|
+
|
15
|
+
import superquantx as sqx
|
16
|
+
|
17
|
+
|
18
|
+
@click.command()
|
19
|
+
def info():
|
20
|
+
"""Show system and backend information."""
|
21
|
+
click.echo("SuperQuantX System Information")
|
22
|
+
click.echo("=" * 40)
|
23
|
+
|
24
|
+
# Basic info
|
25
|
+
click.echo(f"Version: {sqx.__version__}")
|
26
|
+
click.echo(f"Installation path: {sqx.__file__}")
|
27
|
+
|
28
|
+
# Backend information
|
29
|
+
click.echo("\\nAvailable Backends:")
|
30
|
+
backend_info = sqx.get_backend_info()
|
31
|
+
|
32
|
+
for backend_name, version in backend_info.items():
|
33
|
+
status = "✓" if version else "✗"
|
34
|
+
version_str = version if version else "Not installed"
|
35
|
+
click.echo(f" {status} {backend_name}: {version_str}")
|
36
|
+
|
37
|
+
# Configuration
|
38
|
+
config = sqx.config
|
39
|
+
click.echo("\\nCurrent Configuration:")
|
40
|
+
click.echo(f" Default backend: {config.get('default_backend', 'auto')}")
|
41
|
+
click.echo(f" Random seed: {config.get('random_seed', 42)}")
|
42
|
+
click.echo(f" Shots: {config.get('shots', 1024)}")
|
43
|
+
|
44
|
+
# Hardware info
|
45
|
+
try:
|
46
|
+
import psutil
|
47
|
+
click.echo("\\nSystem Resources:")
|
48
|
+
click.echo(f" CPU cores: {psutil.cpu_count()}")
|
49
|
+
click.echo(f" RAM: {psutil.virtual_memory().total / (1024**3):.1f} GB")
|
50
|
+
except ImportError:
|
51
|
+
pass
|
52
|
+
|
53
|
+
|
54
|
+
@click.command('list-algorithms')
|
55
|
+
@click.option(
|
56
|
+
'--category', '-c',
|
57
|
+
type=click.Choice(['all', 'classification', 'regression', 'clustering', 'optimization']),
|
58
|
+
default='all',
|
59
|
+
help='Algorithm category to list'
|
60
|
+
)
|
61
|
+
@click.option(
|
62
|
+
'--verbose', '-v',
|
63
|
+
is_flag=True,
|
64
|
+
help='Show detailed algorithm information'
|
65
|
+
)
|
66
|
+
def list_algorithms(category: str, verbose: bool):
|
67
|
+
"""List available quantum algorithms."""
|
68
|
+
algorithms = {
|
69
|
+
'classification': [
|
70
|
+
('QuantumSVM', 'Quantum Support Vector Machine'),
|
71
|
+
('QuantumNN', 'Quantum Neural Network'),
|
72
|
+
('HybridClassifier', 'Hybrid Classical-Quantum Classifier')
|
73
|
+
],
|
74
|
+
'regression': [
|
75
|
+
('QuantumNN', 'Quantum Neural Network (regression mode)')
|
76
|
+
],
|
77
|
+
'clustering': [
|
78
|
+
('QuantumKMeans', 'Quantum K-Means Clustering'),
|
79
|
+
('QuantumPCA', 'Quantum Principal Component Analysis')
|
80
|
+
],
|
81
|
+
'optimization': [
|
82
|
+
('QAOA', 'Quantum Approximate Optimization Algorithm'),
|
83
|
+
('VQE', 'Variational Quantum Eigensolver')
|
84
|
+
]
|
85
|
+
}
|
86
|
+
|
87
|
+
click.echo("Available Quantum Algorithms")
|
88
|
+
click.echo("=" * 40)
|
89
|
+
|
90
|
+
categories_to_show = [category] if category != 'all' else list(algorithms.keys())
|
91
|
+
|
92
|
+
for cat in categories_to_show:
|
93
|
+
if cat in algorithms:
|
94
|
+
click.echo(f"\\n{cat.title()}:")
|
95
|
+
|
96
|
+
for alg_name, description in algorithms[cat]:
|
97
|
+
if verbose:
|
98
|
+
click.echo(f" • {alg_name}")
|
99
|
+
click.echo(f" {description}")
|
100
|
+
|
101
|
+
# Try to get algorithm class and show parameters
|
102
|
+
try:
|
103
|
+
alg_class = getattr(sqx.algorithms, alg_name)
|
104
|
+
# This is a simplified approach - real implementation would
|
105
|
+
# need to inspect the class properly
|
106
|
+
click.echo(f" Module: superquantx.algorithms.{alg_name}")
|
107
|
+
except AttributeError:
|
108
|
+
pass
|
109
|
+
click.echo()
|
110
|
+
else:
|
111
|
+
click.echo(f" • {alg_name}: {description}")
|
112
|
+
|
113
|
+
|
114
|
+
@click.command('list-backends')
|
115
|
+
@click.option(
|
116
|
+
'--available-only', '-a',
|
117
|
+
is_flag=True,
|
118
|
+
help='Show only installed backends'
|
119
|
+
)
|
120
|
+
def list_backends(available_only: bool):
|
121
|
+
"""List quantum computing backends."""
|
122
|
+
backends = {
|
123
|
+
'Local Simulators': [
|
124
|
+
('simulator', 'SuperQuantX built-in simulator'),
|
125
|
+
('pennylane_local', 'PennyLane local simulators'),
|
126
|
+
('qiskit_aer', 'Qiskit Aer simulator')
|
127
|
+
],
|
128
|
+
'Cloud Simulators': [
|
129
|
+
('pennylane_cloud', 'PennyLane cloud devices'),
|
130
|
+
('qiskit_ibm', 'IBM Quantum simulators'),
|
131
|
+
('braket_sv1', 'AWS Braket SV1 simulator'),
|
132
|
+
('cirq_cloud', 'Google Cirq cloud simulators')
|
133
|
+
],
|
134
|
+
'Quantum Hardware': [
|
135
|
+
('ibm_quantum', 'IBM Quantum hardware'),
|
136
|
+
('braket_hardware', 'AWS Braket hardware access'),
|
137
|
+
('azure_quantum', 'Azure Quantum hardware'),
|
138
|
+
('rigetti_qcs', 'Rigetti Quantum Cloud Services')
|
139
|
+
]
|
140
|
+
}
|
141
|
+
|
142
|
+
backend_info = sqx.get_backend_info()
|
143
|
+
|
144
|
+
click.echo("Quantum Computing Backends")
|
145
|
+
click.echo("=" * 40)
|
146
|
+
|
147
|
+
for category, backend_list in backends.items():
|
148
|
+
click.echo(f"\\n{category}:")
|
149
|
+
|
150
|
+
for backend_name, description in backend_list:
|
151
|
+
# Check if backend is available (simplified logic)
|
152
|
+
is_available = any(info for info in backend_info.values())
|
153
|
+
|
154
|
+
if available_only and not is_available:
|
155
|
+
continue
|
156
|
+
|
157
|
+
status = "✓" if is_available else "✗"
|
158
|
+
click.echo(f" {status} {backend_name}: {description}")
|
159
|
+
|
160
|
+
|
161
|
+
@click.command('run')
|
162
|
+
@click.argument('algorithm')
|
163
|
+
@click.option(
|
164
|
+
'--data', '-d',
|
165
|
+
default='iris',
|
166
|
+
help='Dataset to use (iris, wine, digits, synthetic)'
|
167
|
+
)
|
168
|
+
@click.option(
|
169
|
+
'--backend', '-b',
|
170
|
+
default='auto',
|
171
|
+
help='Quantum backend to use'
|
172
|
+
)
|
173
|
+
@click.option(
|
174
|
+
'--output', '-o',
|
175
|
+
type=click.Path(),
|
176
|
+
help='Output file for results'
|
177
|
+
)
|
178
|
+
@click.option(
|
179
|
+
'--config-file', '-c',
|
180
|
+
type=click.Path(exists=True),
|
181
|
+
help='Algorithm configuration file'
|
182
|
+
)
|
183
|
+
@click.option(
|
184
|
+
'--verbose', '-v',
|
185
|
+
is_flag=True,
|
186
|
+
help='Enable verbose output'
|
187
|
+
)
|
188
|
+
def run_algorithm(
|
189
|
+
algorithm: str,
|
190
|
+
data: str,
|
191
|
+
backend: str,
|
192
|
+
output: Optional[str],
|
193
|
+
config_file: Optional[str],
|
194
|
+
verbose: bool
|
195
|
+
):
|
196
|
+
"""Run a quantum algorithm on specified dataset."""
|
197
|
+
if verbose:
|
198
|
+
click.echo(f"Running {algorithm} on {data} dataset using {backend} backend")
|
199
|
+
|
200
|
+
try:
|
201
|
+
# Load dataset
|
202
|
+
if data == 'iris':
|
203
|
+
X_train, X_test, y_train, y_test, metadata = sqx.datasets.load_iris_quantum()
|
204
|
+
elif data == 'wine':
|
205
|
+
X_train, X_test, y_train, y_test, metadata = sqx.datasets.load_wine_quantum()
|
206
|
+
elif data == 'synthetic':
|
207
|
+
X_train, X_test, y_train, y_test, metadata = sqx.datasets.generate_classification_data()
|
208
|
+
else:
|
209
|
+
click.echo(f"Unknown dataset: {data}", err=True)
|
210
|
+
sys.exit(1)
|
211
|
+
|
212
|
+
if verbose:
|
213
|
+
click.echo(f"Loaded {metadata['dataset_name']} dataset")
|
214
|
+
click.echo(f"Training samples: {len(X_train)}")
|
215
|
+
click.echo(f"Features: {metadata['n_features']}")
|
216
|
+
|
217
|
+
# Load configuration
|
218
|
+
config = {}
|
219
|
+
if config_file:
|
220
|
+
with open(config_file) as f:
|
221
|
+
config = json.load(f)
|
222
|
+
|
223
|
+
# Create algorithm
|
224
|
+
algorithm_map = {
|
225
|
+
'qsvm': sqx.QuantumSVM,
|
226
|
+
'qaoa': sqx.QAOA,
|
227
|
+
'vqe': sqx.VQE,
|
228
|
+
'qnn': sqx.QuantumNN,
|
229
|
+
'qkmeans': sqx.QuantumKMeans,
|
230
|
+
'qpca': sqx.QuantumPCA
|
231
|
+
}
|
232
|
+
|
233
|
+
if algorithm.lower() not in algorithm_map:
|
234
|
+
click.echo(f"Unknown algorithm: {algorithm}", err=True)
|
235
|
+
click.echo(f"Available: {list(algorithm_map.keys())}")
|
236
|
+
sys.exit(1)
|
237
|
+
|
238
|
+
AlgorithmClass = algorithm_map[algorithm.lower()]
|
239
|
+
|
240
|
+
# Set backend
|
241
|
+
config['backend'] = backend
|
242
|
+
|
243
|
+
alg = AlgorithmClass(**config)
|
244
|
+
|
245
|
+
if verbose:
|
246
|
+
click.echo(f"Created {AlgorithmClass.__name__} with config: {config}")
|
247
|
+
|
248
|
+
# Train
|
249
|
+
click.echo("Training...")
|
250
|
+
start_time = time.time()
|
251
|
+
|
252
|
+
alg.fit(X_train, y_train)
|
253
|
+
|
254
|
+
training_time = time.time() - start_time
|
255
|
+
|
256
|
+
# Predict
|
257
|
+
click.echo("Evaluating...")
|
258
|
+
y_pred = alg.predict(X_test)
|
259
|
+
|
260
|
+
# Calculate metrics
|
261
|
+
accuracy = np.mean(y_pred == y_test)
|
262
|
+
|
263
|
+
# Results
|
264
|
+
results = {
|
265
|
+
'algorithm': AlgorithmClass.__name__,
|
266
|
+
'dataset': metadata['dataset_name'],
|
267
|
+
'backend': backend,
|
268
|
+
'accuracy': float(accuracy),
|
269
|
+
'training_time': training_time,
|
270
|
+
'n_train_samples': len(X_train),
|
271
|
+
'n_test_samples': len(X_test),
|
272
|
+
'n_features': metadata['n_features']
|
273
|
+
}
|
274
|
+
|
275
|
+
# Output results
|
276
|
+
click.echo("\\nResults:")
|
277
|
+
click.echo(f"Accuracy: {accuracy:.4f}")
|
278
|
+
click.echo(f"Training time: {training_time:.2f}s")
|
279
|
+
|
280
|
+
if output:
|
281
|
+
with open(output, 'w') as f:
|
282
|
+
json.dump(results, f, indent=2)
|
283
|
+
click.echo(f"Results saved to {output}")
|
284
|
+
|
285
|
+
if verbose:
|
286
|
+
click.echo(f"Full results: {results}")
|
287
|
+
|
288
|
+
except Exception as e:
|
289
|
+
click.echo(f"Error running algorithm: {e}", err=True)
|
290
|
+
if verbose:
|
291
|
+
import traceback
|
292
|
+
traceback.print_exc()
|
293
|
+
sys.exit(1)
|
294
|
+
|
295
|
+
|
296
|
+
@click.command()
|
297
|
+
@click.option(
|
298
|
+
'--algorithms', '-a',
|
299
|
+
default='qsvm,qnn',
|
300
|
+
help='Comma-separated list of algorithms to benchmark'
|
301
|
+
)
|
302
|
+
@click.option(
|
303
|
+
'--datasets', '-d',
|
304
|
+
default='iris,wine',
|
305
|
+
help='Comma-separated list of datasets'
|
306
|
+
)
|
307
|
+
@click.option(
|
308
|
+
'--backends', '-b',
|
309
|
+
default='simulator',
|
310
|
+
help='Comma-separated list of backends'
|
311
|
+
)
|
312
|
+
@click.option(
|
313
|
+
'--output', '-o',
|
314
|
+
type=click.Path(),
|
315
|
+
default='benchmark_results.json',
|
316
|
+
help='Output file for benchmark results'
|
317
|
+
)
|
318
|
+
@click.option(
|
319
|
+
'--runs', '-r',
|
320
|
+
default=3,
|
321
|
+
help='Number of runs for averaging'
|
322
|
+
)
|
323
|
+
def benchmark(
|
324
|
+
algorithms: str,
|
325
|
+
datasets: str,
|
326
|
+
backends: str,
|
327
|
+
output: str,
|
328
|
+
runs: int
|
329
|
+
):
|
330
|
+
"""Benchmark algorithms across datasets and backends."""
|
331
|
+
alg_list = algorithms.split(',')
|
332
|
+
dataset_list = datasets.split(',')
|
333
|
+
backend_list = backends.split(',')
|
334
|
+
|
335
|
+
click.echo("SuperQuantX Benchmark")
|
336
|
+
click.echo("=" * 30)
|
337
|
+
click.echo(f"Algorithms: {alg_list}")
|
338
|
+
click.echo(f"Datasets: {dataset_list}")
|
339
|
+
click.echo(f"Backends: {backend_list}")
|
340
|
+
click.echo(f"Runs per combination: {runs}")
|
341
|
+
click.echo()
|
342
|
+
|
343
|
+
results = []
|
344
|
+
total_combinations = len(alg_list) * len(dataset_list) * len(backend_list)
|
345
|
+
current = 0
|
346
|
+
|
347
|
+
for algorithm in alg_list:
|
348
|
+
for dataset in dataset_list:
|
349
|
+
for backend in backend_list:
|
350
|
+
current += 1
|
351
|
+
click.echo(f"[{current}/{total_combinations}] {algorithm} on {dataset} with {backend}")
|
352
|
+
|
353
|
+
try:
|
354
|
+
# This would call the actual benchmark function
|
355
|
+
# For now, simulate results
|
356
|
+
result = {
|
357
|
+
'algorithm': algorithm,
|
358
|
+
'dataset': dataset,
|
359
|
+
'backend': backend,
|
360
|
+
'accuracy': np.random.uniform(0.7, 0.95),
|
361
|
+
'execution_time': np.random.uniform(1.0, 10.0),
|
362
|
+
'success': True
|
363
|
+
}
|
364
|
+
results.append(result)
|
365
|
+
|
366
|
+
click.echo(f" Accuracy: {result['accuracy']:.4f}")
|
367
|
+
click.echo(f" Time: {result['execution_time']:.2f}s")
|
368
|
+
|
369
|
+
except Exception as e:
|
370
|
+
click.echo(f" Failed: {e}")
|
371
|
+
results.append({
|
372
|
+
'algorithm': algorithm,
|
373
|
+
'dataset': dataset,
|
374
|
+
'backend': backend,
|
375
|
+
'success': False,
|
376
|
+
'error': str(e)
|
377
|
+
})
|
378
|
+
|
379
|
+
# Save results
|
380
|
+
with open(output, 'w') as f:
|
381
|
+
json.dump(results, f, indent=2)
|
382
|
+
|
383
|
+
click.echo(f"\\nBenchmark complete. Results saved to {output}")
|
384
|
+
|
385
|
+
|
386
|
+
@click.command()
|
387
|
+
@click.option(
|
388
|
+
'--backend', '-b',
|
389
|
+
help='Set default backend'
|
390
|
+
)
|
391
|
+
@click.option(
|
392
|
+
'--shots', '-s',
|
393
|
+
type=int,
|
394
|
+
help='Set default number of shots'
|
395
|
+
)
|
396
|
+
@click.option(
|
397
|
+
'--seed',
|
398
|
+
type=int,
|
399
|
+
help='Set random seed'
|
400
|
+
)
|
401
|
+
@click.option(
|
402
|
+
'--show',
|
403
|
+
is_flag=True,
|
404
|
+
help='Show current configuration'
|
405
|
+
)
|
406
|
+
def configure(backend: Optional[str], shots: Optional[int], seed: Optional[int], show: bool):
|
407
|
+
"""Configure SuperQuantX settings."""
|
408
|
+
if show:
|
409
|
+
click.echo("Current SuperQuantX Configuration:")
|
410
|
+
click.echo("=" * 40)
|
411
|
+
config = sqx.config
|
412
|
+
for key, value in config.items():
|
413
|
+
click.echo(f"{key}: {value}")
|
414
|
+
return
|
415
|
+
|
416
|
+
# Update configuration
|
417
|
+
config_updates = {}
|
418
|
+
if backend:
|
419
|
+
config_updates['default_backend'] = backend
|
420
|
+
click.echo(f"Set default backend to: {backend}")
|
421
|
+
|
422
|
+
if shots:
|
423
|
+
config_updates['shots'] = shots
|
424
|
+
click.echo(f"Set default shots to: {shots}")
|
425
|
+
|
426
|
+
if seed:
|
427
|
+
config_updates['random_seed'] = seed
|
428
|
+
click.echo(f"Set random seed to: {seed}")
|
429
|
+
|
430
|
+
if config_updates:
|
431
|
+
sqx.configure(**config_updates)
|
432
|
+
click.echo("Configuration updated successfully")
|
433
|
+
else:
|
434
|
+
click.echo("No configuration changes specified")
|
435
|
+
|
436
|
+
|
437
|
+
@click.command('create-dataset')
|
438
|
+
@click.argument('dataset_type', type=click.Choice(['classification', 'regression', 'clustering']))
|
439
|
+
@click.option(
|
440
|
+
'--samples', '-n',
|
441
|
+
default=200,
|
442
|
+
help='Number of samples to generate'
|
443
|
+
)
|
444
|
+
@click.option(
|
445
|
+
'--features', '-f',
|
446
|
+
default=4,
|
447
|
+
help='Number of features'
|
448
|
+
)
|
449
|
+
@click.option(
|
450
|
+
'--output', '-o',
|
451
|
+
type=click.Path(),
|
452
|
+
help='Output file (NPZ format)'
|
453
|
+
)
|
454
|
+
def create_dataset(dataset_type: str, samples: int, features: int, output: Optional[str]):
|
455
|
+
"""Create synthetic datasets for testing."""
|
456
|
+
if dataset_type == 'classification':
|
457
|
+
X_train, X_test, y_train, y_test, metadata = sqx.datasets.generate_classification_data(
|
458
|
+
n_samples=samples,
|
459
|
+
n_features=features
|
460
|
+
)
|
461
|
+
elif dataset_type == 'regression':
|
462
|
+
X_train, X_test, y_train, y_test, metadata = sqx.datasets.generate_regression_data(
|
463
|
+
n_samples=samples,
|
464
|
+
n_features=features
|
465
|
+
)
|
466
|
+
elif dataset_type == 'clustering':
|
467
|
+
X, y_true, metadata = sqx.datasets.generate_clustering_data(
|
468
|
+
n_samples=samples,
|
469
|
+
n_features=features
|
470
|
+
)
|
471
|
+
# For clustering, no train/test split
|
472
|
+
X_train, X_test, y_train, y_test = X, X, y_true, y_true
|
473
|
+
|
474
|
+
click.echo(f"Created {dataset_type} dataset:")
|
475
|
+
click.echo(f" Samples: {samples}")
|
476
|
+
click.echo(f" Features: {features}")
|
477
|
+
click.echo(f" Training set: {len(X_train)}")
|
478
|
+
click.echo(f" Test set: {len(X_test)}")
|
479
|
+
|
480
|
+
if output:
|
481
|
+
np.savez(
|
482
|
+
output,
|
483
|
+
X_train=X_train,
|
484
|
+
X_test=X_test,
|
485
|
+
y_train=y_train,
|
486
|
+
y_test=y_test,
|
487
|
+
metadata=metadata
|
488
|
+
)
|
489
|
+
click.echo(f"Dataset saved to: {output}")
|
490
|
+
|
491
|
+
|
492
|
+
@click.command()
|
493
|
+
@click.argument('results_file', type=click.Path(exists=True))
|
494
|
+
@click.option(
|
495
|
+
'--plot-type', '-p',
|
496
|
+
type=click.Choice(['optimization', 'classification', 'regression']),
|
497
|
+
default='optimization',
|
498
|
+
help='Type of plot to generate'
|
499
|
+
)
|
500
|
+
@click.option(
|
501
|
+
'--output', '-o',
|
502
|
+
type=click.Path(),
|
503
|
+
help='Output file for plot'
|
504
|
+
)
|
505
|
+
def visualize(results_file: str, plot_type: str, output: Optional[str]):
|
506
|
+
"""Visualize algorithm results."""
|
507
|
+
# Load results
|
508
|
+
with open(results_file) as f:
|
509
|
+
results = json.load(f)
|
510
|
+
|
511
|
+
click.echo(f"Visualizing results from {results_file}")
|
512
|
+
click.echo(f"Plot type: {plot_type}")
|
513
|
+
|
514
|
+
try:
|
515
|
+
sqx.visualize_results(
|
516
|
+
results,
|
517
|
+
plot_type=plot_type,
|
518
|
+
save_path=output
|
519
|
+
)
|
520
|
+
|
521
|
+
if output:
|
522
|
+
click.echo(f"Plot saved to: {output}")
|
523
|
+
else:
|
524
|
+
click.echo("Plot displayed")
|
525
|
+
|
526
|
+
except Exception as e:
|
527
|
+
click.echo(f"Error creating visualization: {e}", err=True)
|
528
|
+
sys.exit(1)
|