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/config.py ADDED
@@ -0,0 +1,443 @@
1
+ """Configuration classes for optimization."""
2
+
3
+ import json
4
+ import multiprocessing as mp
5
+ import os
6
+ from dataclasses import asdict, dataclass, field
7
+ from datetime import datetime
8
+ from enum import Enum
9
+ from typing import Any, Callable, Optional
10
+
11
+ import numpy as np
12
+ from numpy.typing import NDArray
13
+
14
+ from .ansatz import AnsatzProtocol
15
+ from .paths import get_path_config
16
+
17
+ __all__ = [
18
+ "TargetFunction",
19
+ "OptimizerConfig",
20
+ "OptimizationPipeline",
21
+ "OptimizationStrategy",
22
+ "CampaignConfig",
23
+ ]
24
+
25
+
26
+ class TargetFunction(Enum):
27
+ """Available target wavefunction types."""
28
+
29
+ GAUSSIAN = "gaussian"
30
+ LORENTZIAN = "lorentzian"
31
+ SECH = "sech" # Hyperbolic secant (soliton-like)
32
+ CUSTOM = "custom"
33
+
34
+
35
+ @dataclass
36
+ class OptimizerConfig:
37
+ """
38
+ Configuration for the GaussianOptimizer.
39
+
40
+ Supports multiple target wavefunctions, custom ansatze, and multi-GPU execution.
41
+
42
+ Examples
43
+ --------
44
+ Basic Gaussian:
45
+
46
+ >>> config = OptimizerConfig(n_qubits=8, sigma=0.5)
47
+
48
+ Shifted Gaussian:
49
+
50
+ >>> config = OptimizerConfig(n_qubits=8, sigma=0.5, x0=2.0) # Center at x=2.0
51
+
52
+ Lorentzian:
53
+
54
+ >>> config = OptimizerConfig(
55
+ ... n_qubits=8,
56
+ ... target_function=TargetFunction.LORENTZIAN,
57
+ ... gamma=0.3, # Width parameter
58
+ ... x0=1.5, # Shift to x=1.5
59
+ ... )
60
+
61
+ Custom wavefunction:
62
+
63
+ >>> def double_gaussian(x):
64
+ ... return np.exp(-((x-1)**2)/0.5) + np.exp(-((x+1)**2)/0.5)
65
+ >>>
66
+ >>> config = OptimizerConfig(
67
+ ... n_qubits=10,
68
+ ... target_function=TargetFunction.CUSTOM,
69
+ ... custom_target_fn=double_gaussian,
70
+ ... )
71
+
72
+ Multi-GPU:
73
+
74
+ >>> config = OptimizerConfig(
75
+ ... n_qubits=14,
76
+ ... use_multi_gpu=True,
77
+ ... gpu_device_ids=[0, 1, 2, 3],
78
+ ... )
79
+ """
80
+
81
+ # ========================================
82
+ # Problem Parameters
83
+ # ========================================
84
+ n_qubits: int = 9
85
+ sigma: float = 1.0
86
+ x0: float = 0.0 # Center position (shift wavefunction left/right)
87
+ box_size: Optional[float] = None
88
+
89
+ # ========================================
90
+ # Target Wavefunction
91
+ # ========================================
92
+ target_function: TargetFunction = TargetFunction.GAUSSIAN
93
+ gamma: Optional[float] = None # Width for Lorentzian (uses sigma if None)
94
+ custom_target_fn: Optional[Callable[[np.ndarray], np.ndarray]] = None
95
+
96
+ # ========================================
97
+ # Ansatz Configuration
98
+ # ========================================
99
+ ansatz: Optional[AnsatzProtocol] = None
100
+ ansatz_depth: Optional[int] = None
101
+ ansatz_kwargs: Optional[dict[str, Any]] = None
102
+
103
+ # ========================================
104
+ # Optimizer Settings
105
+ # ========================================
106
+ method: str = "L-BFGS-B"
107
+ max_iter: int = 10000
108
+ max_fun: int = 50000
109
+ tolerance: float = 1e-12
110
+ gtol: float = 1e-12
111
+ use_analytic_gradients: bool = True
112
+
113
+ # High precision mode
114
+ high_precision: bool = True
115
+ adaptive_tolerance: bool = True
116
+
117
+ # For difficult cases
118
+ use_multistart: bool = False
119
+ n_restarts: int = 5
120
+
121
+ # Refinement stage
122
+ enable_refinement: bool = True
123
+ target_fidelity: float = 0.9999999
124
+ refinement_iter: int = 5000
125
+
126
+ # ========================================
127
+ # Visualization
128
+ # ========================================
129
+ plot_result: bool = True
130
+ save_plot: bool = True
131
+
132
+ # ========================================
133
+ # GPU Configuration
134
+ # ========================================
135
+ use_gpu: bool = True
136
+ gpu_precision: str = "double" # 'double' or 'single'
137
+ gpu_batch_size: int = 64
138
+ gpu_blocking: bool = True
139
+
140
+ # cuStateVec
141
+ use_custatevec: bool = True
142
+ custatevec_batch_size: int = 128
143
+
144
+ # Multi-GPU support
145
+ use_multi_gpu: bool = False
146
+ gpu_device_ids: Optional[list[int]] = None # None = auto-detect all GPUs
147
+ simulators_per_gpu: int = 2 # Number of simulators per GPU for batching
148
+
149
+ # ========================================
150
+ # Parallelization
151
+ # ========================================
152
+ n_workers: Optional[int] = None # None = auto-detect
153
+ parallel_gradients: bool = True
154
+ parallel_backend: str = "thread" # 'thread' or 'process'
155
+ gradient_chunk_size: int = 8
156
+
157
+ # ========================================
158
+ # Output
159
+ # ========================================
160
+ verbose: bool = True
161
+
162
+ def __post_init__(self):
163
+ # Auto-detect number of workers if not specified
164
+ if self.n_workers is None:
165
+ self.n_workers = max(1, mp.cpu_count() - 1)
166
+
167
+ # Only auto-calculate box_size if not explicitly provided
168
+ if self.box_size is None:
169
+ if self.sigma < 0.5:
170
+ self.box_size = max(4.0, 12 * self.sigma)
171
+ else:
172
+ self.box_size = 10.0
173
+
174
+ # Ensure adequate coverage
175
+ min_box = 8 * self.sigma
176
+ if self.box_size < min_box:
177
+ if self.verbose:
178
+ print(
179
+ f"Info: Auto-adjusting box size from {self.box_size:.2f} to {min_box:.2f} for sigma={self.sigma}"
180
+ )
181
+ self.box_size = min_box
182
+ else:
183
+ if self.verbose:
184
+ print(f"Using user-specified box size: +/-{self.box_size:.2f}")
185
+
186
+ # Validate custom target function
187
+ if self.target_function == TargetFunction.CUSTOM and self.custom_target_fn is None:
188
+ raise ValueError("custom_target_fn must be provided when target_function is CUSTOM")
189
+
190
+ if self.verbose:
191
+ print(f"Target function: {self.target_function.value}")
192
+ if self.x0 != 0.0:
193
+ print(f"Wavefunction center: x0 = {self.x0}")
194
+ print(f"Parallelization: {self.n_workers} workers, backend='{self.parallel_backend}'")
195
+ if self.use_multi_gpu:
196
+ gpu_str = f"devices {self.gpu_device_ids}" if self.gpu_device_ids else "auto-detect"
197
+ print(f"Multi-GPU enabled: {gpu_str}")
198
+
199
+ @property
200
+ def n_params(self) -> int:
201
+ """Number of variational parameters."""
202
+ if self.ansatz is not None and hasattr(self.ansatz, 'n_params'):
203
+ return self.ansatz.n_params
204
+ return self.n_qubits * self.n_qubits
205
+
206
+ @property
207
+ def n_states(self) -> int:
208
+ """Number of basis states (2^n_qubits)."""
209
+ return 2**self.n_qubits
210
+
211
+ @property
212
+ def positions(self) -> NDArray[np.float64]:
213
+ """Position grid for wavefunction."""
214
+ return np.linspace(-self.box_size, self.box_size, self.n_states)
215
+
216
+ @property
217
+ def delta_x(self) -> float:
218
+ """Grid spacing."""
219
+ return 2 * self.box_size / (self.n_states - 1)
220
+
221
+
222
+ @dataclass
223
+ class OptimizationPipeline:
224
+ """Configuration for optimization pipeline stages."""
225
+
226
+ mode: str = "adaptive" # 'adaptive', 'ultra', 'hybrid', 'single_stage'
227
+
228
+ target_fidelity: float = 0.9999
229
+ target_infidelity: Optional[float] = None
230
+
231
+ max_total_time: float = 3600 # seconds
232
+
233
+ use_init_search: bool = True
234
+ init_strategies: Optional[list[str]] = None
235
+
236
+ use_adam_stage: bool = True
237
+ adam_max_steps: int = 1000
238
+ adam_lr: float = 0.01
239
+ adam_max_time: Optional[float] = None
240
+ adam_time_fraction: float = 0.4
241
+
242
+ use_basin_hopping: bool = False
243
+ basin_hopping_threshold: float = 0.9999
244
+ basin_hopping_iterations: int = 30
245
+
246
+ use_lbfgs_refinement: bool = True
247
+ lbfgs_tolerances: Optional[list[float]] = None
248
+ lbfgs_time_fraction: float = 0.8
249
+
250
+ use_fine_tuning: bool = True
251
+ fine_tuning_threshold: float = 0.9999
252
+
253
+ verbose: bool = True
254
+
255
+ def __post_init__(self):
256
+ if self.target_infidelity is None:
257
+ self.target_infidelity = 1 - self.target_fidelity
258
+ if self.init_strategies is None:
259
+ self.init_strategies = ["smart", "gaussian_product", "random", "random", "random"]
260
+ if self.lbfgs_tolerances is None:
261
+ self.lbfgs_tolerances = [1e-10, 1e-12, 1e-14]
262
+
263
+
264
+ class OptimizationStrategy(Enum):
265
+ """Available optimization strategies for campaign runs."""
266
+
267
+ SMART = "smart"
268
+ GAUSSIAN_PRODUCT = "gaussian_product"
269
+ RANDOM = "random"
270
+ PERTURB_BEST = "perturb_best"
271
+ ZERO = "zero"
272
+
273
+
274
+ @dataclass
275
+ class CampaignConfig:
276
+ """
277
+ Configuration for large-scale optimization campaigns.
278
+
279
+ Designed for running thousands of optimizations to guarantee
280
+ finding the global minimum with machine precision.
281
+ """
282
+
283
+ # ========================================
284
+ # Problem Parameters
285
+ # ========================================
286
+ n_qubits: int = 8
287
+ sigma: float = 0.5
288
+ x0: float = 0.0
289
+ box_size: Optional[float] = None
290
+ target_function: TargetFunction = TargetFunction.GAUSSIAN
291
+ gamma: Optional[float] = None
292
+ custom_target_fn: Optional[Callable[[np.ndarray], np.ndarray]] = None
293
+
294
+ # ========================================
295
+ # Campaign Scale
296
+ # ========================================
297
+ total_runs: int = 1000
298
+ runs_per_batch: int = 50
299
+
300
+ # ========================================
301
+ # Optimization Targets
302
+ # ========================================
303
+ target_infidelity: float = 1e-10
304
+ target_fidelity: Optional[float] = None
305
+ acceptable_infidelity: float = 1e-8
306
+
307
+ # ========================================
308
+ # Strategy Distribution
309
+ # ========================================
310
+ strategy_weights: dict[str, float] = field(
311
+ default_factory=lambda: {
312
+ "smart": 0.3,
313
+ "gaussian_product": 0.2,
314
+ "random": 0.4,
315
+ "perturb_best": 0.1,
316
+ }
317
+ )
318
+
319
+ # ========================================
320
+ # Per-Run Settings
321
+ # ========================================
322
+ max_iter_per_run: int = 5000
323
+ tolerance_per_run: float = 1e-12
324
+ use_ultra_precision: bool = True
325
+ ultra_precision_time_limit: float = 300
326
+
327
+ # ========================================
328
+ # Refinement Settings
329
+ # ========================================
330
+ refine_top_n: int = 10
331
+ refinement_time_limit: float = 600
332
+
333
+ # ========================================
334
+ # Parallelization
335
+ # ========================================
336
+ n_parallel_runs: Optional[int] = None
337
+ use_gpu: bool = True
338
+ use_custatevec: bool = True
339
+ use_multi_gpu: bool = False
340
+ gpu_device_ids: Optional[list[int]] = None
341
+ gpu_precision: str = "double"
342
+
343
+ # ========================================
344
+ # Checkpointing
345
+ # ========================================
346
+ checkpoint_interval: int = 10
347
+ checkpoint_dir: Optional[str] = None
348
+ resume_from_checkpoint: bool = True
349
+
350
+ # ========================================
351
+ # Output Settings
352
+ # ========================================
353
+ campaign_name: Optional[str] = None
354
+ output_dir: Optional[str] = None
355
+ save_all_results: bool = False
356
+ save_top_n_results: int = 100
357
+ verbose: int = 1
358
+
359
+ # ========================================
360
+ # Seed Management
361
+ # ========================================
362
+ base_seed: int = 42
363
+
364
+ def __post_init__(self):
365
+ """Initialize computed fields."""
366
+ if self.target_fidelity is None:
367
+ self.target_fidelity = 1 - self.target_infidelity
368
+
369
+ if self.box_size is None:
370
+ self.box_size = max(4 * self.sigma, 2.0)
371
+
372
+ if self.n_parallel_runs is None:
373
+ self.n_parallel_runs = max(1, mp.cpu_count() - 2)
374
+
375
+ if self.campaign_name is None:
376
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
377
+ fn_suffix = (
378
+ f"_{self.target_function.value}"
379
+ if self.target_function != TargetFunction.GAUSSIAN
380
+ else ""
381
+ )
382
+ self.campaign_name = (
383
+ f"campaign_q{self.n_qubits}_s{self.sigma:.2f}{fn_suffix}_{timestamp}"
384
+ )
385
+
386
+ if self.checkpoint_dir is None:
387
+ self.checkpoint_dir = str(
388
+ get_path_config(verbose=False).checkpoint_dir / self.campaign_name
389
+ )
390
+ if self.output_dir is None:
391
+ self.output_dir = str(get_path_config(verbose=False).campaign_dir / self.campaign_name)
392
+
393
+ os.makedirs(self.checkpoint_dir, exist_ok=True)
394
+ os.makedirs(self.output_dir, exist_ok=True)
395
+
396
+ total_weight = sum(self.strategy_weights.values())
397
+ self.strategy_weights = {k: v / total_weight for k, v in self.strategy_weights.items()}
398
+
399
+ @property
400
+ def n_params(self) -> int:
401
+ return self.n_qubits * self.n_qubits
402
+
403
+ def get_strategy_for_run(self, run_id: int) -> str:
404
+ """Deterministically assign strategy based on run_id."""
405
+ np.random.seed(self.base_seed + run_id)
406
+ strategies = list(self.strategy_weights.keys())
407
+ weights = list(self.strategy_weights.values())
408
+ return np.random.choice(strategies, p=weights)
409
+
410
+ def get_seed_for_run(self, run_id: int) -> int:
411
+ """Get reproducible seed for run."""
412
+ return self.base_seed + run_id * 1000
413
+
414
+ def to_dict(self) -> dict:
415
+ """Convert to dictionary for serialization."""
416
+ d = asdict(self)
417
+ d["target_function"] = self.target_function.value
418
+ d["custom_target_fn"] = None # Cannot serialize functions
419
+ return d
420
+
421
+ def save(self, filepath: Optional[str] = None) -> str:
422
+ """Save configuration to JSON."""
423
+ if filepath is None:
424
+ filepath = os.path.join(self.output_dir, "campaign_config.json")
425
+
426
+ with open(filepath, "w") as f:
427
+ json.dump(self.to_dict(), f, indent=2, default=str)
428
+
429
+ return filepath
430
+
431
+ @classmethod
432
+ def load(cls, filepath: str) -> "CampaignConfig":
433
+ """Load configuration from JSON."""
434
+ with open(filepath) as f:
435
+ data = json.load(f)
436
+
437
+ if isinstance(data.get("target_function"), str):
438
+ data["target_function"] = TargetFunction(data["target_function"])
439
+
440
+ if isinstance(data.get("strategy_weights"), str):
441
+ data["strategy_weights"] = json.loads(data["strategy_weights"])
442
+
443
+ return cls(**data)
wings/convenience.py ADDED
@@ -0,0 +1,259 @@
1
+ """High-level convenience functions for interactive use."""
2
+
3
+ from typing import Any, Optional
4
+
5
+ from .config import OptimizerConfig, TargetFunction
6
+ from .optimizer import GaussianOptimizer
7
+
8
+ __all__ = [
9
+ "optimize_gaussian_state",
10
+ "quick_optimize",
11
+ ]
12
+
13
+
14
+ def optimize_gaussian_state(
15
+ n_qubits: int = 8,
16
+ sigma: float = 1.0,
17
+ x0: float = 0.0,
18
+ box_size: Optional[float] = None,
19
+ target_function: "TargetFunction" = None,
20
+ gamma: Optional[float] = None,
21
+ custom_target_fn=None,
22
+ target_fidelity: float = 0.999999,
23
+ target_infidelity: Optional[float] = None,
24
+ high_precision: bool = True,
25
+ max_time: float = 1800,
26
+ use_gpu: bool = True,
27
+ use_custatevec: bool = True,
28
+ use_multi_gpu: bool = False,
29
+ gpu_device_ids: Optional[list] = None,
30
+ plot: bool = True,
31
+ save: bool = True,
32
+ verbose: bool = True,
33
+ ) -> tuple[dict[str, Any], GaussianOptimizer]:
34
+ """
35
+ Main optimization function with high precision capabilities.
36
+
37
+ This is the recommended entry point for interactive use.
38
+
39
+ Parameters
40
+ ----------
41
+ n_qubits : int
42
+ Number of qubits (default: 8)
43
+ sigma : float
44
+ Gaussian width parameter (default: 1.0)
45
+ box_size : float, optional
46
+ Box size for position grid. If None, auto-calculated based on sigma.
47
+ target_fidelity : float
48
+ Target fidelity to achieve (default: 0.999999)
49
+ target_infidelity : float, optional
50
+ Alternative to target_fidelity: specify 1-F directly (e.g., 1e-10)
51
+ high_precision : bool
52
+ Enable high precision mode (default: True)
53
+ max_time : float
54
+ Maximum optimization time in seconds (default: 1800 = 30 min)
55
+ use_gpu : bool
56
+ Use GPU acceleration if available (default: True)
57
+ use_custatevec : bool
58
+ Use cuStateVec if available (default: True)
59
+ plot : bool
60
+ Generate result plots (default: True)
61
+ save : bool
62
+ Save results to files (default: True)
63
+ verbose : bool
64
+ Print progress information (default: True)
65
+
66
+ Returns
67
+ -------
68
+ results : dict
69
+ Dictionary containing optimization results:
70
+ - 'fidelity': Final fidelity achieved
71
+ - 'infidelity': 1 - fidelity
72
+ - 'params': Optimal parameters
73
+ - 'time': Total optimization time
74
+ - 'n_evaluations': Number of function evaluations
75
+ - 'circuit_mean', 'circuit_std': Statistics of prepared state
76
+ - 'target_mean', 'target_std': Statistics of target Gaussian
77
+ optimizer : GaussianOptimizer
78
+ The optimizer instance (for further analysis)
79
+
80
+ Examples
81
+ --------
82
+ Basic usage:
83
+
84
+ >>> results, opt = optimize_gaussian_state(n_qubits=8, sigma=0.5)
85
+ >>> print(f"Fidelity: {results['fidelity']:.12f}")
86
+
87
+ High precision with specific target:
88
+
89
+ >>> results, opt = optimize_gaussian_state(
90
+ ... n_qubits=10,
91
+ ... sigma=0.5,
92
+ ... target_infidelity=1e-11,
93
+ ... max_time=3600,
94
+ ... )
95
+ """
96
+ if verbose:
97
+ print("=" * 80)
98
+ print("HIGH PRECISION GAUSSIAN STATE OPTIMIZER")
99
+ print("=" * 80)
100
+
101
+ # Determine target
102
+ if target_infidelity is not None:
103
+ effective_target_infidelity = target_infidelity
104
+ else:
105
+ effective_target_infidelity = 1 - target_fidelity
106
+
107
+ # Auto-calculate box size if not provided
108
+ if box_size is None:
109
+ box_size = max(10.0, 8 * sigma)
110
+
111
+ # Create configuration
112
+ if target_function is None:
113
+ target_function = TargetFunction.GAUSSIAN
114
+
115
+ # Create configuration
116
+ config = OptimizerConfig(
117
+ n_qubits=n_qubits,
118
+ sigma=sigma,
119
+ x0=x0,
120
+ box_size=box_size,
121
+ # Target function
122
+ target_function=target_function,
123
+ gamma=gamma,
124
+ custom_target_fn=custom_target_fn,
125
+ # Optimizer settings
126
+ method="L-BFGS-B",
127
+ max_iter=10000,
128
+ max_fun=200000,
129
+ tolerance=1e-14,
130
+ gtol=1e-14,
131
+ high_precision=high_precision,
132
+ use_analytic_gradients=True,
133
+ use_gpu=use_gpu,
134
+ use_custatevec=use_custatevec,
135
+ use_multi_gpu=use_multi_gpu,
136
+ gpu_device_ids=gpu_device_ids,
137
+ gpu_precision="double",
138
+ verbose=verbose,
139
+ target_fidelity=1 - effective_target_infidelity,
140
+ )
141
+
142
+ if verbose:
143
+ print("\nConfiguration:")
144
+ print(f" n_qubits: {config.n_qubits}")
145
+ print(f" Target function: {target_function.value}")
146
+ print(f" Target sigma: {config.sigma:.6f}")
147
+ if x0 != 0.0:
148
+ print(f" Center (x0): {x0:.6f}")
149
+ print(f" Box size: ±{config.box_size:.4f}")
150
+ print(f" Grid points: {config.n_states}")
151
+ print(f" Grid spacing: {config.delta_x:.8f}")
152
+ print(f" Target infidelity: {effective_target_infidelity:.2e}")
153
+ print()
154
+
155
+ # Create optimizer
156
+ optimizer = GaussianOptimizer(config)
157
+
158
+ # Run ultra-precision optimization
159
+ results = optimizer.optimize_ultra_precision(
160
+ target_infidelity=effective_target_infidelity,
161
+ max_total_time=max_time,
162
+ )
163
+
164
+ # Display results
165
+ if verbose:
166
+ print("\n" + "=" * 80)
167
+ print("OPTIMIZATION COMPLETE")
168
+ print("=" * 80)
169
+ print(f"Fidelity achieved: {results['fidelity']:.15f}")
170
+ print(f"Infidelity (1-F): {results['infidelity']:.3e}")
171
+ print(f"Time taken: {results['time']:.2f} seconds")
172
+ print(f"Function evaluations: {results['n_evaluations']}")
173
+ print()
174
+ print("State properties:")
175
+ print(
176
+ f" Circuit mean: {results['circuit_mean']:.10f} (target: {results['target_mean']:.6f})"
177
+ )
178
+ print(
179
+ f" Circuit std: {results['circuit_std']:.10f} (target: {results['target_std']:.6f})"
180
+ )
181
+
182
+ if results["fidelity"] >= (1 - effective_target_infidelity):
183
+ print(f"\n✓ SUCCESS: Achieved target infidelity of {effective_target_infidelity:.2e}")
184
+ else:
185
+ print(f"\n⚠ Target not achieved. Current: 1-F = {results['infidelity']:.3e}")
186
+ _print_suggestions(results["fidelity"])
187
+
188
+ # Plot results
189
+ if plot:
190
+ plot_file = f"gaussian_q{n_qubits}_s{sigma:.4f}.png" if save else None
191
+ optimizer.plot_results(results, save_path=plot_file)
192
+
193
+ # Save results
194
+ if save:
195
+ optimizer.save_results(results)
196
+
197
+ return results, optimizer
198
+
199
+
200
+ def _print_suggestions(fidelity: float) -> None:
201
+ """Print optimization suggestions based on achieved fidelity."""
202
+ if fidelity < 0.999:
203
+ print("\nSuggestions to improve fidelity:")
204
+ print(" 1. Increase max_time")
205
+ print(" 2. Ensure high_precision=True")
206
+ print(" 3. Check box_size matches Gaussian extent (~8*sigma)")
207
+ print(" 4. Increase n_qubits for better resolution")
208
+ else:
209
+ print("\nFor higher precision:")
210
+ print(" - Increase max_time (current optimization may need more iterations)")
211
+ print(" - Try running multiple times (different initial conditions)")
212
+ print(" - Use run_production_campaign() for systematic search")
213
+
214
+
215
+ def quick_optimize(
216
+ n_qubits: int,
217
+ sigma: float,
218
+ x0: float = 0.0,
219
+ target_function: "TargetFunction" = None,
220
+ verbose: bool = True,
221
+ ) -> tuple[float, dict[str, Any]]:
222
+ """
223
+ Quick optimization with sensible defaults.
224
+
225
+ Useful for testing or when you just want a quick result.
226
+
227
+ Parameters
228
+ ----------
229
+ n_qubits : int
230
+ Number of qubits
231
+ sigma : float
232
+ Gaussian width
233
+ verbose : bool
234
+ Print progress (default: True)
235
+
236
+ Returns
237
+ -------
238
+ fidelity : float
239
+ Best fidelity achieved
240
+ results : dict
241
+ Full results dictionary
242
+
243
+ Examples
244
+ --------
245
+ >>> fidelity, results = quick_optimize(8, 0.5)
246
+ >>> print(f"Achieved fidelity: {fidelity:.10f}")
247
+ """
248
+ results, _ = optimize_gaussian_state(
249
+ n_qubits=n_qubits,
250
+ sigma=sigma,
251
+ x0=x0,
252
+ target_function=target_function,
253
+ target_infidelity=1e-10,
254
+ max_time=300, # 5 minutes
255
+ plot=False,
256
+ save=False,
257
+ verbose=verbose,
258
+ )
259
+ return results["fidelity"], results