wings-quantum 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.
- wings/__init__.py +251 -0
- wings/adam.py +132 -0
- wings/ansatz.py +207 -0
- wings/benchmarks.py +605 -0
- wings/campaign.py +661 -0
- wings/cli.py +377 -0
- wings/compat.py +132 -0
- wings/config.py +443 -0
- wings/convenience.py +259 -0
- wings/evaluators/__init__.py +19 -0
- wings/evaluators/cpu.py +72 -0
- wings/evaluators/custatevec.py +783 -0
- wings/evaluators/gpu.py +220 -0
- wings/export.py +243 -0
- wings/optimizer.py +1898 -0
- wings/paths.py +295 -0
- wings/py.typed +2 -0
- wings/results.py +255 -0
- wings/types.py +14 -0
- wings_quantum-0.1.0.dist-info/METADATA +491 -0
- wings_quantum-0.1.0.dist-info/RECORD +25 -0
- wings_quantum-0.1.0.dist-info/WHEEL +5 -0
- wings_quantum-0.1.0.dist-info/entry_points.txt +2 -0
- wings_quantum-0.1.0.dist-info/licenses/LICENSE.txt +21 -0
- wings_quantum-0.1.0.dist-info/top_level.txt +1 -0
wings/cli.py
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
"""Command-line interface for gaussian-state-optimizer."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main(args: Optional[list] = None) -> int:
|
|
9
|
+
"""
|
|
10
|
+
Main entry point for the CLI.
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
gso optimize --qubits 8 --sigma 0.5
|
|
14
|
+
gso benchmark --qubits 12
|
|
15
|
+
gso crossover
|
|
16
|
+
gso info
|
|
17
|
+
gso campaigns list
|
|
18
|
+
"""
|
|
19
|
+
parser = argparse.ArgumentParser(
|
|
20
|
+
prog="gso",
|
|
21
|
+
description="Gaussian State Optimizer - GPU-accelerated quantum state preparation",
|
|
22
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
23
|
+
epilog="""
|
|
24
|
+
Examples:
|
|
25
|
+
gso optimize --qubits 8 --sigma 0.5
|
|
26
|
+
gso optimize --qubits 10 --sigma 0.5 --target-infidelity 1e-10 --max-time 3600
|
|
27
|
+
gso benchmark --qubits 12
|
|
28
|
+
gso crossover
|
|
29
|
+
gso info
|
|
30
|
+
gso campaigns list
|
|
31
|
+
gso campaigns load campaign_q8_s0.50_20240101_120000
|
|
32
|
+
""",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
36
|
+
|
|
37
|
+
# ========================================
|
|
38
|
+
# optimize command
|
|
39
|
+
# ========================================
|
|
40
|
+
opt_parser = subparsers.add_parser(
|
|
41
|
+
"optimize",
|
|
42
|
+
help="Run Gaussian state optimization",
|
|
43
|
+
description="Optimize quantum circuit parameters to prepare a Gaussian state",
|
|
44
|
+
)
|
|
45
|
+
opt_parser.add_argument(
|
|
46
|
+
"-q",
|
|
47
|
+
"--qubits",
|
|
48
|
+
type=int,
|
|
49
|
+
default=8,
|
|
50
|
+
help="Number of qubits (default: 8)",
|
|
51
|
+
)
|
|
52
|
+
opt_parser.add_argument(
|
|
53
|
+
"-s",
|
|
54
|
+
"--sigma",
|
|
55
|
+
type=float,
|
|
56
|
+
default=0.5,
|
|
57
|
+
help="Gaussian width sigma (default: 0.5)",
|
|
58
|
+
)
|
|
59
|
+
opt_parser.add_argument(
|
|
60
|
+
"--box-size",
|
|
61
|
+
type=float,
|
|
62
|
+
default=None,
|
|
63
|
+
help="Box size for position grid (default: auto)",
|
|
64
|
+
)
|
|
65
|
+
opt_parser.add_argument(
|
|
66
|
+
"--target-infidelity",
|
|
67
|
+
type=float,
|
|
68
|
+
default=1e-8,
|
|
69
|
+
help="Target infidelity 1-F (default: 1e-8)",
|
|
70
|
+
)
|
|
71
|
+
opt_parser.add_argument(
|
|
72
|
+
"--max-time",
|
|
73
|
+
type=float,
|
|
74
|
+
default=600,
|
|
75
|
+
help="Maximum optimization time in seconds (default: 600)",
|
|
76
|
+
)
|
|
77
|
+
opt_parser.add_argument(
|
|
78
|
+
"--no-gpu",
|
|
79
|
+
action="store_true",
|
|
80
|
+
help="Disable GPU acceleration",
|
|
81
|
+
)
|
|
82
|
+
opt_parser.add_argument(
|
|
83
|
+
"--no-custatevec",
|
|
84
|
+
action="store_true",
|
|
85
|
+
help="Disable cuStateVec (use Aer GPU instead)",
|
|
86
|
+
)
|
|
87
|
+
opt_parser.add_argument(
|
|
88
|
+
"--no-plot",
|
|
89
|
+
action="store_true",
|
|
90
|
+
help="Disable result plotting",
|
|
91
|
+
)
|
|
92
|
+
opt_parser.add_argument(
|
|
93
|
+
"--no-save",
|
|
94
|
+
action="store_true",
|
|
95
|
+
help="Disable saving results to files",
|
|
96
|
+
)
|
|
97
|
+
opt_parser.add_argument(
|
|
98
|
+
"-v",
|
|
99
|
+
"--verbose",
|
|
100
|
+
action="store_true",
|
|
101
|
+
default=True,
|
|
102
|
+
help="Verbose output (default: True)",
|
|
103
|
+
)
|
|
104
|
+
opt_parser.add_argument(
|
|
105
|
+
"-Q",
|
|
106
|
+
"--quiet",
|
|
107
|
+
action="store_true",
|
|
108
|
+
help="Suppress output",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# ========================================
|
|
112
|
+
# campaign command
|
|
113
|
+
# ========================================
|
|
114
|
+
camp_parser = subparsers.add_parser(
|
|
115
|
+
"campaign",
|
|
116
|
+
help="Run production optimization campaign",
|
|
117
|
+
description="Run large-scale optimization campaign with checkpointing",
|
|
118
|
+
)
|
|
119
|
+
camp_parser.add_argument(
|
|
120
|
+
"-q",
|
|
121
|
+
"--qubits",
|
|
122
|
+
type=int,
|
|
123
|
+
default=8,
|
|
124
|
+
help="Number of qubits (default: 8)",
|
|
125
|
+
)
|
|
126
|
+
camp_parser.add_argument(
|
|
127
|
+
"-s",
|
|
128
|
+
"--sigma",
|
|
129
|
+
type=float,
|
|
130
|
+
default=0.5,
|
|
131
|
+
help="Gaussian width sigma (default: 0.5)",
|
|
132
|
+
)
|
|
133
|
+
camp_parser.add_argument(
|
|
134
|
+
"-n",
|
|
135
|
+
"--runs",
|
|
136
|
+
type=int,
|
|
137
|
+
default=100,
|
|
138
|
+
help="Total optimization runs (default: 100)",
|
|
139
|
+
)
|
|
140
|
+
camp_parser.add_argument(
|
|
141
|
+
"--target-infidelity",
|
|
142
|
+
type=float,
|
|
143
|
+
default=1e-10,
|
|
144
|
+
help="Target infidelity (default: 1e-10)",
|
|
145
|
+
)
|
|
146
|
+
camp_parser.add_argument(
|
|
147
|
+
"--name",
|
|
148
|
+
type=str,
|
|
149
|
+
default=None,
|
|
150
|
+
help="Campaign name (default: auto-generated)",
|
|
151
|
+
)
|
|
152
|
+
camp_parser.add_argument(
|
|
153
|
+
"--resume",
|
|
154
|
+
action="store_true",
|
|
155
|
+
help="Resume from checkpoint if available",
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# ========================================
|
|
159
|
+
# benchmark command
|
|
160
|
+
# ========================================
|
|
161
|
+
bench_parser = subparsers.add_parser(
|
|
162
|
+
"benchmark",
|
|
163
|
+
help="Benchmark GPU vs CPU performance",
|
|
164
|
+
)
|
|
165
|
+
bench_parser.add_argument(
|
|
166
|
+
"-q",
|
|
167
|
+
"--qubits",
|
|
168
|
+
type=int,
|
|
169
|
+
default=10,
|
|
170
|
+
help="Number of qubits (default: 10)",
|
|
171
|
+
)
|
|
172
|
+
bench_parser.add_argument(
|
|
173
|
+
"-s",
|
|
174
|
+
"--sigma",
|
|
175
|
+
type=float,
|
|
176
|
+
default=0.5,
|
|
177
|
+
help="Gaussian width (default: 0.5)",
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# ========================================
|
|
181
|
+
# crossover command
|
|
182
|
+
# ========================================
|
|
183
|
+
cross_parser = subparsers.add_parser(
|
|
184
|
+
"crossover",
|
|
185
|
+
help="Find GPU crossover point",
|
|
186
|
+
description="Determine at what qubit count GPU becomes faster than CPU",
|
|
187
|
+
)
|
|
188
|
+
cross_parser.add_argument(
|
|
189
|
+
"--min-qubits",
|
|
190
|
+
type=int,
|
|
191
|
+
default=6,
|
|
192
|
+
help="Minimum qubits to test (default: 6)",
|
|
193
|
+
)
|
|
194
|
+
cross_parser.add_argument(
|
|
195
|
+
"--max-qubits",
|
|
196
|
+
type=int,
|
|
197
|
+
default=18,
|
|
198
|
+
help="Maximum qubits to test (default: 18)",
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# ========================================
|
|
202
|
+
# info command
|
|
203
|
+
# ========================================
|
|
204
|
+
subparsers.add_parser(
|
|
205
|
+
"info",
|
|
206
|
+
help="Show backend and system information",
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# ========================================
|
|
210
|
+
# campaigns subcommand
|
|
211
|
+
# ========================================
|
|
212
|
+
campaigns_parser = subparsers.add_parser(
|
|
213
|
+
"campaigns",
|
|
214
|
+
help="Manage optimization campaigns",
|
|
215
|
+
)
|
|
216
|
+
campaigns_sub = campaigns_parser.add_subparsers(dest="campaigns_command")
|
|
217
|
+
|
|
218
|
+
campaigns_sub.add_parser("list", help="List all campaigns")
|
|
219
|
+
|
|
220
|
+
load_parser = campaigns_sub.add_parser("load", help="Load campaign results")
|
|
221
|
+
load_parser.add_argument("name", help="Campaign name or path")
|
|
222
|
+
|
|
223
|
+
# Parse arguments
|
|
224
|
+
parsed = parser.parse_args(args)
|
|
225
|
+
|
|
226
|
+
if parsed.command is None:
|
|
227
|
+
parser.print_help()
|
|
228
|
+
return 0
|
|
229
|
+
|
|
230
|
+
# Execute command
|
|
231
|
+
try:
|
|
232
|
+
if parsed.command == "optimize":
|
|
233
|
+
return _cmd_optimize(parsed)
|
|
234
|
+
elif parsed.command == "campaign":
|
|
235
|
+
return _cmd_campaign(parsed)
|
|
236
|
+
elif parsed.command == "benchmark":
|
|
237
|
+
return _cmd_benchmark(parsed)
|
|
238
|
+
elif parsed.command == "crossover":
|
|
239
|
+
return _cmd_crossover(parsed)
|
|
240
|
+
elif parsed.command == "info":
|
|
241
|
+
return _cmd_info(parsed)
|
|
242
|
+
elif parsed.command == "campaigns":
|
|
243
|
+
return _cmd_campaigns(parsed)
|
|
244
|
+
else:
|
|
245
|
+
parser.print_help()
|
|
246
|
+
return 1
|
|
247
|
+
except KeyboardInterrupt:
|
|
248
|
+
print("\nInterrupted by user")
|
|
249
|
+
return 130
|
|
250
|
+
except Exception as e:
|
|
251
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
252
|
+
return 1
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _cmd_optimize(args) -> int:
|
|
256
|
+
"""Handle optimize command."""
|
|
257
|
+
from .convenience import optimize_gaussian_state
|
|
258
|
+
|
|
259
|
+
verbose = not args.quiet if hasattr(args, "quiet") else True
|
|
260
|
+
|
|
261
|
+
results, optimizer = optimize_gaussian_state(
|
|
262
|
+
n_qubits=args.qubits,
|
|
263
|
+
sigma=args.sigma,
|
|
264
|
+
box_size=args.box_size,
|
|
265
|
+
target_infidelity=args.target_infidelity,
|
|
266
|
+
max_time=args.max_time,
|
|
267
|
+
use_gpu=not args.no_gpu,
|
|
268
|
+
use_custatevec=not args.no_custatevec,
|
|
269
|
+
plot=not args.no_plot,
|
|
270
|
+
save=not args.no_save,
|
|
271
|
+
verbose=verbose,
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
# Print final result for scripting
|
|
275
|
+
print(f"\nFinal fidelity: {results['fidelity']:.15f}")
|
|
276
|
+
print(f"Final infidelity: {results['infidelity']:.3e}")
|
|
277
|
+
|
|
278
|
+
return 0 if results["fidelity"] >= (1 - args.target_infidelity) else 1
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _cmd_campaign(args) -> int:
|
|
282
|
+
"""Handle campaign command."""
|
|
283
|
+
from .campaign import run_production_campaign
|
|
284
|
+
|
|
285
|
+
results = run_production_campaign(
|
|
286
|
+
n_qubits=args.qubits,
|
|
287
|
+
sigma=args.sigma,
|
|
288
|
+
total_runs=args.runs,
|
|
289
|
+
target_infidelity=args.target_infidelity,
|
|
290
|
+
campaign_name=args.name,
|
|
291
|
+
resume=args.resume,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
results.print_summary()
|
|
295
|
+
|
|
296
|
+
return (
|
|
297
|
+
0
|
|
298
|
+
if results.best_result and results.best_result.fidelity >= (1 - args.target_infidelity)
|
|
299
|
+
else 1
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _cmd_benchmark(args) -> int:
|
|
304
|
+
"""Handle benchmark command."""
|
|
305
|
+
from .benchmarks import benchmark_gpu
|
|
306
|
+
|
|
307
|
+
benchmark_gpu(
|
|
308
|
+
n_qubits=args.qubits,
|
|
309
|
+
sigma=args.sigma,
|
|
310
|
+
verbose=True,
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
return 0
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _cmd_crossover(args) -> int:
|
|
317
|
+
"""Handle crossover command."""
|
|
318
|
+
from .benchmarks import find_gpu_crossover
|
|
319
|
+
|
|
320
|
+
qubit_range = list(range(args.min_qubits, args.max_qubits + 1, 2))
|
|
321
|
+
|
|
322
|
+
find_gpu_crossover(
|
|
323
|
+
qubit_range=qubit_range,
|
|
324
|
+
verbose=True,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
return 0
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _cmd_info(args) -> int:
|
|
331
|
+
"""Handle info command."""
|
|
332
|
+
from . import __version__, print_backend_info
|
|
333
|
+
|
|
334
|
+
print(f"Gaussian State Optimizer v{__version__}")
|
|
335
|
+
print()
|
|
336
|
+
print_backend_info()
|
|
337
|
+
|
|
338
|
+
return 0
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def _cmd_campaigns(args) -> int:
|
|
342
|
+
"""Handle campaigns subcommands."""
|
|
343
|
+
if args.campaigns_command == "list":
|
|
344
|
+
from .campaign import list_campaigns
|
|
345
|
+
|
|
346
|
+
campaigns = list_campaigns()
|
|
347
|
+
|
|
348
|
+
if not campaigns:
|
|
349
|
+
print("No campaigns found.")
|
|
350
|
+
return 0
|
|
351
|
+
|
|
352
|
+
print(f"{'Name':<50} {'Runs':<8} {'Best Fidelity':<20}")
|
|
353
|
+
print("-" * 80)
|
|
354
|
+
|
|
355
|
+
for c in campaigns:
|
|
356
|
+
runs = c.get("total_runs", "N/A")
|
|
357
|
+
fid = c.get("best_fidelity")
|
|
358
|
+
fid_str = f"{fid:.12f}" if fid else "N/A"
|
|
359
|
+
print(f"{c['name']:<50} {runs:<8} {fid_str:<20}")
|
|
360
|
+
|
|
361
|
+
return 0
|
|
362
|
+
|
|
363
|
+
elif args.campaigns_command == "load":
|
|
364
|
+
from .campaign import load_campaign_results
|
|
365
|
+
|
|
366
|
+
results = load_campaign_results(args.name)
|
|
367
|
+
results.print_summary()
|
|
368
|
+
|
|
369
|
+
return 0
|
|
370
|
+
|
|
371
|
+
else:
|
|
372
|
+
print("Usage: gso campaigns {list|load}")
|
|
373
|
+
return 1
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
if __name__ == "__main__":
|
|
377
|
+
sys.exit(main())
|
wings/compat.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
logger = logging.getLogger(__name__)
|
|
5
|
+
|
|
6
|
+
# Conditional imports for cuQuantum
|
|
7
|
+
try:
|
|
8
|
+
import cupy as cp
|
|
9
|
+
from cuquantum.bindings import custatevec as cusv
|
|
10
|
+
|
|
11
|
+
HAS_CUSTATEVEC = True
|
|
12
|
+
except ImportError:
|
|
13
|
+
HAS_CUSTATEVEC = False
|
|
14
|
+
cp = None
|
|
15
|
+
cusv = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CuQuantumCompat:
|
|
19
|
+
"""
|
|
20
|
+
Compatibility layer for cuQuantum API differences across versions.
|
|
21
|
+
|
|
22
|
+
Handles the cudaDataType and ComputeType enum access which varies
|
|
23
|
+
between cuQuantum versions (pre-24.x vs 24.x+).
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
# Standard CUDA data type values (from cuda_runtime_api.h)
|
|
27
|
+
_CUDA_DTYPE_MAP = {
|
|
28
|
+
"CUDA_R_32F": 0,
|
|
29
|
+
"CUDA_R_64F": 1,
|
|
30
|
+
"CUDA_C_32F": 4,
|
|
31
|
+
"CUDA_C_64F": 5,
|
|
32
|
+
"CUDA_C_128F": 5, # Alias for complex128
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_COMPUTE_TYPE_MAP = {
|
|
36
|
+
"COMPUTE_32F": 4,
|
|
37
|
+
"COMPUTE_64F": 16,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
self._cuda_c_64f: Optional[int] = None
|
|
42
|
+
self._compute_64f: Optional[int] = None
|
|
43
|
+
self._initialized = False
|
|
44
|
+
|
|
45
|
+
def _initialize(self) -> None:
|
|
46
|
+
"""Lazy initialization to detect available API."""
|
|
47
|
+
if self._initialized:
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
self._cuda_c_64f = self._detect_cuda_dtype()
|
|
51
|
+
self._compute_64f = self._detect_compute_type()
|
|
52
|
+
self._initialized = True
|
|
53
|
+
|
|
54
|
+
def _detect_cuda_dtype(self) -> int:
|
|
55
|
+
"""Detect CUDA_C_64F value from cusv or fall back to known constant."""
|
|
56
|
+
if not HAS_CUSTATEVEC:
|
|
57
|
+
return self._CUDA_DTYPE_MAP["CUDA_C_64F"]
|
|
58
|
+
|
|
59
|
+
# Try various API locations (differs by cuQuantum version)
|
|
60
|
+
access_paths = [
|
|
61
|
+
lambda: int(cusv.cudaDataType.CUDA_C_64F),
|
|
62
|
+
lambda: int(cusv.cudaDataType.CUDA_C_128F),
|
|
63
|
+
lambda: int(cusv.CUDA_C_64F),
|
|
64
|
+
lambda: cusv.cudaDataType["CUDA_C_64F"],
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
for accessor in access_paths:
|
|
68
|
+
try:
|
|
69
|
+
value = accessor()
|
|
70
|
+
logger.debug(f"Found CUDA_C_64F via {accessor.__code__.co_consts}: {value}")
|
|
71
|
+
return value
|
|
72
|
+
except (AttributeError, TypeError, KeyError):
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
logger.debug("Using fallback CUDA_C_64F value: 5")
|
|
76
|
+
return self._CUDA_DTYPE_MAP["CUDA_C_64F"]
|
|
77
|
+
|
|
78
|
+
def _detect_compute_type(self) -> int:
|
|
79
|
+
"""Detect COMPUTE_64F value from cusv or fall back to known constant."""
|
|
80
|
+
if not HAS_CUSTATEVEC:
|
|
81
|
+
return self._COMPUTE_TYPE_MAP["COMPUTE_64F"]
|
|
82
|
+
|
|
83
|
+
access_paths = [
|
|
84
|
+
lambda: int(cusv.ComputeType.COMPUTE_64F),
|
|
85
|
+
lambda: int(cusv.COMPUTE_64F),
|
|
86
|
+
lambda: cusv.ComputeType["COMPUTE_64F"],
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
for accessor in access_paths:
|
|
90
|
+
try:
|
|
91
|
+
value = accessor()
|
|
92
|
+
logger.debug(f"Found COMPUTE_64F: {value}")
|
|
93
|
+
return value
|
|
94
|
+
except (AttributeError, TypeError, KeyError):
|
|
95
|
+
continue
|
|
96
|
+
|
|
97
|
+
logger.debug("Using fallback COMPUTE_64F value: 16")
|
|
98
|
+
return self._COMPUTE_TYPE_MAP["COMPUTE_64F"]
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def CUDA_C_64F(self) -> int:
|
|
102
|
+
self._initialize()
|
|
103
|
+
return self._cuda_c_64f
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def COMPUTE_64F(self) -> int:
|
|
107
|
+
self._initialize()
|
|
108
|
+
return self._compute_64f
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# Global compatibility instance
|
|
112
|
+
cuquantum_compat = CuQuantumCompat()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# Convenience accessors (replaces the old global variables)
|
|
116
|
+
def get_cuda_dtype() -> int:
|
|
117
|
+
"""Get the CUDA data type constant for complex128."""
|
|
118
|
+
return cuquantum_compat.CUDA_C_64F
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def get_compute_type() -> int:
|
|
122
|
+
"""Get the compute type constant for 64-bit precision."""
|
|
123
|
+
return cuquantum_compat.COMPUTE_64F
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
__all__ = [
|
|
127
|
+
"HAS_CUSTATEVEC",
|
|
128
|
+
"CuQuantumCompat",
|
|
129
|
+
"cuquantum_compat",
|
|
130
|
+
"get_cuda_dtype",
|
|
131
|
+
"get_compute_type",
|
|
132
|
+
]
|