0
# Utilities and I/O
1
2
Data persistence, file operations, and utility functions for QuTiP objects and calculations.
3
4
## Capabilities
5
6
### File I/O Operations
7
8
Save and load QuTiP objects to/from disk.
9
10
```python { .api }
11
def qsave(obj, name: str, format: str = 'pickle') -> None:
12
"""
13
Save QuTiP object to file.
14
15
Parameters:
16
- obj: QuTiP object to save (Qobj, Result, etc.)
17
- name: Filename (without extension)
18
- format: File format ('pickle', 'numpy')
19
"""
20
21
def qload(name: str, format: str = 'pickle') -> object:
22
"""
23
Load QuTiP object from file.
24
25
Parameters:
26
- name: Filename (without extension)
27
- format: File format ('pickle', 'numpy')
28
29
Returns:
30
- object: Loaded QuTiP object
31
"""
32
33
def file_data_read(filename: str) -> np.ndarray:
34
"""
35
Read numerical data from file.
36
37
Parameters:
38
- filename: Path to data file
39
40
Returns:
41
- ndarray: Loaded data array
42
"""
43
44
def file_data_store(filename: str, data: np.ndarray, numtype: str = "complex",
45
numformat: str = "decimal") -> None:
46
"""
47
Store numerical data to file.
48
49
Parameters:
50
- filename: Output filename
51
- data: Data array to store
52
- numtype: 'real' or 'complex'
53
- numformat: 'decimal' or 'exp'
54
"""
55
```
56
57
### Package Information
58
59
Information about QuTiP installation and citation.
60
61
```python { .api }
62
def about() -> None:
63
"""Display information about QuTiP installation and dependencies."""
64
65
def cite() -> str:
66
"""
67
Return citation information for QuTiP in BibTeX format.
68
69
Returns:
70
- str: BibTeX citation string
71
"""
72
```
73
74
### Physical Constants and Conversions
75
76
Utility functions for physics calculations.
77
78
```python { .api }
79
def n_thermal(w: float, w_th: float) -> float:
80
"""
81
Calculate average thermal occupation number.
82
83
Parameters:
84
- w: Frequency
85
- w_th: Thermal frequency scale (kB*T/ħ)
86
87
Returns:
88
- float: Thermal occupation ⟨n⟩ = 1/(exp(ω/ωₜₕ) - 1)
89
"""
90
91
def clebsch(j1: float, j2: float, j3: float, m1: float, m2: float, m3: float) -> float:
92
"""
93
Calculate Clebsch-Gordan coefficient ⟨j₁m₁j₂m₂|j₃m₃⟩.
94
95
Parameters:
96
- j1, j2, j3: Angular momentum quantum numbers
97
- m1, m2, m3: Magnetic quantum numbers
98
99
Returns:
100
- float: Clebsch-Gordan coefficient
101
"""
102
103
def convert_unit(value: float, unit_from: str, unit_to: str) -> float:
104
"""
105
Convert between different physical units.
106
107
Parameters:
108
- value: Numerical value to convert
109
- unit_from: Source unit
110
- unit_to: Target unit
111
112
Returns:
113
- float: Converted value
114
"""
115
```
116
117
### Mathematical Utilities
118
119
General mathematical functions for quantum calculations.
120
121
```python { .api }
122
def iterated_fit(func, data, init_params: list, maxiter: int = 1000,
123
tol: float = 1e-8) -> tuple:
124
"""
125
Iterative fitting routine for complex functions.
126
127
Parameters:
128
- func: Function to fit
129
- data: Data to fit to
130
- init_params: Initial parameter guess
131
- maxiter: Maximum iterations
132
- tol: Convergence tolerance
133
134
Returns:
135
- tuple: (fitted_params, residuals, convergence_info)
136
"""
137
138
def polynomial_fit(x: np.ndarray, y: np.ndarray, degree: int) -> np.ndarray:
139
"""
140
Fit polynomial to data points.
141
142
Parameters:
143
- x: X-coordinate data
144
- y: Y-coordinate data
145
- degree: Polynomial degree
146
147
Returns:
148
- ndarray: Polynomial coefficients
149
"""
150
```
151
152
### Testing and Debugging
153
154
Tools for testing and validating QuTiP objects.
155
156
```python { .api }
157
def assert_equal(obj1, obj2, tol: float = 1e-12) -> None:
158
"""
159
Assert two QuTiP objects are equal within tolerance.
160
161
Parameters:
162
- obj1: First object
163
- obj2: Second object
164
- tol: Numerical tolerance
165
166
Raises:
167
- AssertionError: If objects are not equal
168
"""
169
170
def assert_hermitian(op: Qobj, tol: float = 1e-12) -> None:
171
"""
172
Assert that operator is Hermitian.
173
174
Parameters:
175
- op: Operator to test
176
- tol: Numerical tolerance
177
178
Raises:
179
- AssertionError: If operator is not Hermitian
180
"""
181
182
def assert_unitary(U: Qobj, tol: float = 1e-12) -> None:
183
"""
184
Assert that operator is unitary.
185
186
Parameters:
187
- U: Operator to test
188
- tol: Numerical tolerance
189
190
Raises:
191
- AssertionError: If operator is not unitary
192
"""
193
194
def run_tests() -> None:
195
"""Run QuTiP test suite."""
196
```
197
198
### Settings and Configuration
199
200
Global settings for QuTiP behavior.
201
202
```python { .api }
203
class Settings:
204
"""
205
Global settings object for QuTiP configuration.
206
207
Attributes:
208
atol: Absolute tolerance for numerical comparisons
209
rtol: Relative tolerance for numerical comparisons
210
auto_tidyup: Automatically clean small matrix elements
211
auto_tidyup_atol: Absolute tolerance for auto tidyup
212
num_cpus: Number of CPUs for parallel processing
213
debug: Enable debug mode
214
"""
215
def __init__(self):
216
self.core = {
217
'atol': 1e-12,
218
'rtol': 1e-12,
219
'auto_tidyup': True,
220
'auto_tidyup_atol': 1e-12
221
}
222
self.compile = {
223
'num_cpus': 0 # 0 = auto-detect
224
}
225
226
# Global settings instance
227
settings = Settings()
228
```
229
230
### Performance Utilities
231
232
Tools for performance monitoring and optimization.
233
234
```python { .api }
235
def profile_solver(solver_func, *args, **kwargs) -> dict:
236
"""
237
Profile solver performance.
238
239
Parameters:
240
- solver_func: Solver function to profile
241
- *args, **kwargs: Arguments for solver
242
243
Returns:
244
- dict: Profiling results with timing information
245
"""
246
247
def memory_usage() -> dict:
248
"""
249
Get current memory usage information.
250
251
Returns:
252
- dict: Memory usage statistics
253
"""
254
```
255
256
### Usage Examples
257
258
```python
259
import qutip as qt
260
import numpy as np
261
import tempfile
262
import os
263
264
# File I/O operations
265
# Create some quantum objects
266
psi = qt.bell_state('00')
267
rho = psi * psi.dag()
268
H = qt.tensor(qt.sigmaz(), qt.sigmaz())
269
270
# Save objects to files
271
with tempfile.TemporaryDirectory() as tmpdir:
272
# Save quantum objects
273
qt.qsave(psi, os.path.join(tmpdir, 'bell_state'))
274
qt.qsave(rho, os.path.join(tmpdir, 'bell_dm'))
275
qt.qsave(H, os.path.join(tmpdir, 'hamiltonian'))
276
277
# Load them back
278
psi_loaded = qt.qload(os.path.join(tmpdir, 'bell_state'))
279
rho_loaded = qt.qload(os.path.join(tmpdir, 'bell_dm'))
280
H_loaded = qt.qload(os.path.join(tmpdir, 'hamiltonian'))
281
282
# Verify they're the same
283
print(f"State fidelity: {qt.fidelity(psi, psi_loaded):.6f}")
284
print(f"DM fidelity: {qt.fidelity(rho, rho_loaded):.6f}")
285
print(f"Hamiltonian difference: {(H - H_loaded).norm():.2e}")
286
287
# Package information
288
print("QuTiP Information:")
289
qt.about()
290
291
print("\nCitation:")
292
citation = qt.cite()
293
print(citation[:200] + "...") # Show first 200 characters
294
295
# Physical utilities
296
# Thermal occupation number
297
frequency = 1.0 # Oscillator frequency
298
temperature = 0.1 # Temperature in same units
299
n_avg = qt.n_thermal(frequency, temperature)
300
print(f"Average thermal occupation at T={temperature}: {n_avg:.3f}")
301
302
# Clebsch-Gordan coefficients for spin-1/2 + spin-1/2 = spin-1
303
j1, j2, j3 = 0.5, 0.5, 1.0
304
m1, m2, m3 = 0.5, 0.5, 1.0
305
cg_coeff = qt.clebsch(j1, j2, j3, m1, m2, m3)
306
print(f"Clebsch-Gordan ⟨1/2,1/2; 1/2,1/2|1,1⟩: {cg_coeff:.3f}")
307
308
# All possible CG coefficients for this coupling
309
print("All CG coefficients for j1=1/2, j2=1/2 -> j3=1:")
310
for m3_val in [1, 0, -1]:
311
for m1_val in [0.5, -0.5]:
312
for m2_val in [0.5, -0.5]:
313
if abs(m1_val + m2_val - m3_val) < 1e-10: # Selection rule
314
cg = qt.clebsch(0.5, 0.5, 1.0, m1_val, m2_val, m3_val)
315
print(f" ⟨1/2,{m1_val:3.1f}; 1/2,{m2_val:3.1f}|1,{m3_val:2.0f}⟩ = {cg:6.3f}")
316
317
# Testing utilities
318
# Create test objects
319
op1 = qt.sigmax()
320
op2 = qt.sigmax()
321
op_hermitian = qt.sigmaz()
322
op_unitary = qt.rx(np.pi/4)
323
324
# Test equality
325
try:
326
qt.assert_equal(op1, op2)
327
print("Operators are equal ✓")
328
except AssertionError:
329
print("Operators are not equal ✗")
330
331
# Test if operator is Hermitian
332
try:
333
qt.assert_hermitian(op_hermitian)
334
print("Operator is Hermitian ✓")
335
except AssertionError:
336
print("Operator is not Hermitian ✗")
337
338
# Test if operator is unitary
339
try:
340
qt.assert_unitary(op_unitary)
341
print("Operator is unitary ✓")
342
except AssertionError:
343
print("Operator is not unitary ✗")
344
345
# Settings configuration
346
print(f"Current absolute tolerance: {qt.settings.core['atol']}")
347
print(f"Auto tidyup enabled: {qt.settings.core['auto_tidyup']}")
348
349
# Temporarily change settings
350
old_atol = qt.settings.core['atol']
351
qt.settings.core['atol'] = 1e-10
352
print(f"New absolute tolerance: {qt.settings.core['atol']}")
353
354
# Restore settings
355
qt.settings.core['atol'] = old_atol
356
357
# Data file operations
358
# Generate some data
359
times = np.linspace(0, 10, 100)
360
expectation_values = np.exp(-0.1 * times) * np.cos(times)
361
362
# Save to file
363
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.dat') as f:
364
data_file = f.name
365
366
qt.file_data_store(data_file, np.column_stack([times, expectation_values]),
367
numtype="real")
368
369
# Read back
370
loaded_data = qt.file_data_read(data_file)
371
print(f"Original data shape: {np.column_stack([times, expectation_values]).shape}")
372
print(f"Loaded data shape: {loaded_data.shape}")
373
374
# Clean up
375
os.unlink(data_file)
376
377
# Mathematical utilities example
378
def exponential_decay(t, A, gamma, omega, phi):
379
"""Damped oscillation function."""
380
return A * np.exp(-gamma * t) * np.cos(omega * t + phi)
381
382
# Generate noisy data
383
t_data = np.linspace(0, 5, 50)
384
true_params = [1.0, 0.2, 2.0, 0.0] # A, gamma, omega, phi
385
y_clean = exponential_decay(t_data, *true_params)
386
y_noisy = y_clean + 0.05 * np.random.randn(len(t_data))
387
388
# Fit using scipy.optimize (QuTiP's iterated_fit wrapper)
389
try:
390
from scipy.optimize import curve_fit
391
fitted_params, covariance = curve_fit(exponential_decay, t_data, y_noisy,
392
p0=[1.1, 0.25, 1.8, 0.1])
393
print(f"True parameters: {true_params}")
394
print(f"Fitted parameters: {fitted_params}")
395
print(f"Parameter errors: {np.sqrt(np.diag(covariance))}")
396
except ImportError:
397
print("SciPy not available for fitting example")
398
399
# Performance monitoring
400
def example_calculation():
401
"""Simple calculation for profiling."""
402
N = 50
403
psi = qt.rand_ket(N)
404
H = qt.rand_herm(N)
405
return qt.expect(H, psi)
406
407
# Time the calculation
408
import time
409
start_time = time.time()
410
result = example_calculation()
411
end_time = time.time()
412
print(f"Calculation result: {result:.6f}")
413
print(f"Execution time: {end_time - start_time:.4f} seconds")
414
```
415
416
## Types
417
418
```python { .api }
419
class Settings:
420
"""
421
Global configuration object.
422
423
Attributes:
424
core: Core numerical settings (tolerances, etc.)
425
compile: Compilation and performance settings
426
"""
427
428
# Utility functions return various types:
429
# - File I/O functions return None or loaded objects
430
# - Physical functions return float values
431
# - Testing functions return None or raise AssertionError
432
# - Information functions return None (print to console) or str
433
```