coordinate-system 4.0.3__cp313-cp313-win_amd64.whl → 5.2.0__cp313-cp313-win_amd64.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.
@@ -0,0 +1,530 @@
1
+ """
2
+ Fourier Frame System - Quantum Coordinate Transformations
3
+ =========================================================
4
+
5
+ Implements Fourier coordinate frames for quantum state transformations
6
+ between position and momentum representations.
7
+
8
+ Features:
9
+ - FourierFrame: Coordinate frames for Fourier transformations
10
+ - QuantumState: Quantum states in specific basis
11
+ - StateVector: Complete state representations
12
+ - **Operator Overloading**: Use @ and * for transformations
13
+ - Position ↔ Momentum transformations
14
+ - Gaussian wave packet creation
15
+ - Uncertainty principle demonstrations
16
+
17
+ Operator Overloading:
18
+ --------------------
19
+ - `frame @ state` : Transform state to this frame
20
+ - `frame * state` : Same as @ (alternative)
21
+ - `~frame` : Get dual frame (position ↔ momentum)
22
+ - `state | frame` : Transform state to frame (bra-ket notation)
23
+
24
+ Author: PanGuoJun
25
+ Date: 2025-12-01
26
+ """
27
+
28
+ import numpy as np
29
+ from typing import List, Tuple, Union, Optional
30
+
31
+ try:
32
+ from .coordinate_system import vec3, quat, coord3
33
+ except ImportError:
34
+ import coordinate_system
35
+ vec3 = coordinate_system.vec3
36
+ quat = coordinate_system.quat
37
+ coord3 = coordinate_system.coord3
38
+
39
+
40
+ class QuantumState:
41
+ """
42
+ Quantum state |ψ⟩ - Representation in a specific basis
43
+
44
+ Represents a quantum state with:
45
+ - basis_vector: Position or momentum value
46
+ - amplitude: Complex amplitude in this basis
47
+ - basis: Type of basis ('position' or 'momentum')
48
+
49
+ Operator Overloading:
50
+ --------------------
51
+ - `state | frame` : Transform to frame (bra-ket notation)
52
+ """
53
+
54
+ def __init__(self, basis_vector: vec3, amplitude: complex = 1.0, basis: str = 'position'):
55
+ """
56
+ Initialize quantum state
57
+
58
+ Args:
59
+ basis_vector: Basis vector (position or momentum value)
60
+ amplitude: Complex amplitude in this basis
61
+ basis: Basis type ('position' or 'momentum')
62
+ """
63
+ self.basis_vector = basis_vector
64
+ self.amplitude = amplitude
65
+ self.basis = basis
66
+
67
+ def transform(self, frame: 'FourierFrame') -> 'StateVector':
68
+ """
69
+ Transform to another coordinate frame
70
+
71
+ Args:
72
+ frame: Target Fourier frame
73
+
74
+ Returns:
75
+ Transformed state vector
76
+ """
77
+ return frame.transform(self)
78
+
79
+ def __or__(self, other: 'FourierFrame') -> 'StateVector':
80
+ """
81
+ Bra-ket notation: state | frame
82
+
83
+ Transforms the state to the given frame
84
+
85
+ Args:
86
+ other: Target Fourier frame
87
+
88
+ Returns:
89
+ Transformed state vector
90
+ """
91
+ if isinstance(other, FourierFrame):
92
+ return other.transform(self)
93
+ return NotImplemented
94
+
95
+ def __repr__(self) -> str:
96
+ basis_symbol = 'x' if self.basis == 'position' else 'p'
97
+ return f"{self.amplitude:.3f}|{basis_symbol}={self.basis_vector.x:.1f}⟩"
98
+
99
+
100
+ class StateVector:
101
+ """
102
+ State vector - Complete representation in a coordinate system
103
+
104
+ Represents a quantum state as a superposition:
105
+ |ψ⟩ = Σᵢ cᵢ|bᵢ⟩
106
+
107
+ where cᵢ are complex amplitudes and |bᵢ⟩ are basis states.
108
+
109
+ Operator Overloading:
110
+ --------------------
111
+ - `state | frame` : Transform to frame (bra-ket notation)
112
+ """
113
+
114
+ def __init__(self, states: Union[List[QuantumState], List[Tuple[vec3, complex]]],
115
+ basis: str = 'position'):
116
+ """
117
+ Initialize state vector
118
+
119
+ Args:
120
+ states: List of QuantumState objects or (vector, amplitude) tuples
121
+ basis: Basis type ('position' or 'momentum')
122
+ """
123
+ if isinstance(states, list) and states and isinstance(states[0], QuantumState):
124
+ self.components = [(s.basis_vector, s.amplitude) for s in states]
125
+ else:
126
+ self.components = states # Direct (vector, amplitude) list
127
+ self.basis = basis
128
+ self._normalize()
129
+
130
+ def _normalize(self):
131
+ """Normalize the state vector to unit probability"""
132
+ total_prob = sum(abs(amp)**2 for _, amp in self.components)
133
+ if total_prob > 0:
134
+ norm = 1.0 / np.sqrt(total_prob)
135
+ self.components = [(vec, amp * norm) for vec, amp in self.components]
136
+
137
+ def transform(self, frame: 'FourierFrame') -> 'StateVector':
138
+ """
139
+ Transform to another coordinate frame
140
+
141
+ Args:
142
+ frame: Target Fourier frame
143
+
144
+ Returns:
145
+ Transformed state vector
146
+ """
147
+ return frame.transform(self)
148
+
149
+ def __or__(self, other: 'FourierFrame') -> 'StateVector':
150
+ """
151
+ Bra-ket notation: state | frame
152
+
153
+ Transforms the state to the given frame
154
+
155
+ Args:
156
+ other: Target Fourier frame
157
+
158
+ Returns:
159
+ Transformed state vector
160
+ """
161
+ if isinstance(other, FourierFrame):
162
+ return other.transform(self)
163
+ return NotImplemented
164
+
165
+ def probability_density(self) -> List[Tuple[vec3, float]]:
166
+ """
167
+ Compute probability density distribution |ψ(x)|²
168
+
169
+ Returns:
170
+ List of (position/momentum, probability) tuples
171
+ """
172
+ return [(vec, abs(amp)**2) for vec, amp in self.components]
173
+
174
+ def expectation_value(self) -> float:
175
+ """
176
+ Compute expectation value ⟨x⟩ or ⟨p⟩
177
+
178
+ Returns:
179
+ Expectation value in current basis
180
+ """
181
+ return sum(vec.x * abs(amp)**2 for vec, amp in self.components)
182
+
183
+ def variance(self) -> float:
184
+ """
185
+ Compute variance σ² = ⟨x²⟩ - ⟨x⟩²
186
+
187
+ Returns:
188
+ Variance in current basis
189
+ """
190
+ mean = self.expectation_value()
191
+ mean_square = sum((vec.x ** 2) * abs(amp)**2 for vec, amp in self.components)
192
+ return mean_square - mean ** 2
193
+
194
+ def standard_deviation(self) -> float:
195
+ """
196
+ Compute standard deviation σ = √(⟨x²⟩ - ⟨x⟩²)
197
+
198
+ Returns:
199
+ Standard deviation in current basis
200
+ """
201
+ return np.sqrt(self.variance())
202
+
203
+ def __repr__(self) -> str:
204
+ main_components = []
205
+ for vec, amp in self.components:
206
+ if abs(amp) > 0.05: # Only show significant components
207
+ basis_symbol = 'x' if self.basis == 'position' else 'p'
208
+ main_components.append(f"{amp:.3f}|{basis_symbol}={vec.x:.1f}⟩")
209
+
210
+ if len(main_components) > 3:
211
+ return " + ".join(main_components[:3]) + " + ..."
212
+ return " + ".join(main_components) if main_components else "0"
213
+
214
+
215
+ class FourierFrame:
216
+ """
217
+ Fourier coordinate frame - Basis vectors for Fourier transformations
218
+
219
+ Implements position ↔ momentum transformations via Fourier transform:
220
+
221
+ Position → Momentum: ψ̃(p) = (1/√2π) ∫ ψ(x) e^(-ipx) dx
222
+ Momentum → Position: ψ(x) = (1/√2π) ∫ ψ̃(p) e^(ipx) dp
223
+
224
+ Operator Overloading:
225
+ --------------------
226
+ - `frame @ state` : Transform state to this frame (matrix multiplication)
227
+ - `frame * state` : Same as @ (alternative syntax)
228
+ - `~frame` : Get dual frame (position ↔ momentum)
229
+
230
+ Examples:
231
+ ---------
232
+ >>> position_frame = FourierFrame(domain='position')
233
+ >>> momentum_frame = FourierFrame(domain='momentum')
234
+ >>> psi_x = QuantumState(vec3(0,0,0), 1.0, 'position')
235
+ >>>
236
+ >>> # Method 1: Using @ operator
237
+ >>> psi_p = momentum_frame @ psi_x
238
+ >>>
239
+ >>> # Method 2: Using * operator
240
+ >>> psi_p = momentum_frame * psi_x
241
+ >>>
242
+ >>> # Method 3: Using bra-ket notation |
243
+ >>> psi_p = psi_x | momentum_frame
244
+ >>>
245
+ >>> # Method 4: Get dual and transform
246
+ >>> psi_p = (~position_frame) @ psi_x
247
+ """
248
+
249
+ def __init__(self, dimension: int = 1, domain: str = 'position',
250
+ sample_points: int = 64, x_range: Tuple[float, float] = (-5, 5)):
251
+ """
252
+ Initialize Fourier frame
253
+
254
+ Args:
255
+ dimension: Spatial dimension (currently only 1D supported)
256
+ domain: Domain type ('position' or 'momentum')
257
+ sample_points: Number of sample points for discrete representation
258
+ x_range: Range of position/momentum values (min, max)
259
+ """
260
+ self.dim = dimension
261
+ self.domain = domain
262
+ self.N = sample_points
263
+ self.range = x_range
264
+ self._setup_basis()
265
+
266
+ def _setup_basis(self):
267
+ """Setup basis vectors for the coordinate frame"""
268
+ if self.dim == 1:
269
+ if self.domain == 'position':
270
+ # Position basis |x⟩
271
+ self.basis_vectors = [
272
+ vec3(x, 0, 0)
273
+ for x in np.linspace(self.range[0], self.range[1], self.N)
274
+ ]
275
+ else:
276
+ # Momentum basis |p⟩
277
+ self.basis_vectors = [
278
+ vec3(p, 0, 0)
279
+ for p in np.linspace(self.range[0], self.range[1], self.N)
280
+ ]
281
+
282
+ def transform(self, obj: Union[QuantumState, StateVector, vec3]) -> Union[StateVector, 'StateVector']:
283
+ """
284
+ Universal coordinate transformation method
285
+
286
+ Args:
287
+ obj: Object to transform (QuantumState, StateVector, or vec3)
288
+
289
+ Returns:
290
+ Transformed object
291
+ """
292
+ if isinstance(obj, QuantumState):
293
+ return self._transform_single_state(obj)
294
+ elif isinstance(obj, StateVector):
295
+ return self._transform_state_vector(obj)
296
+ elif isinstance(obj, vec3):
297
+ return self._transform_single_vector(obj)
298
+ else:
299
+ raise TypeError(f"Unsupported type: {type(obj)}")
300
+
301
+ def inverse_transform(self, obj: Union[QuantumState, StateVector, vec3]) -> Union[StateVector, 'StateVector']:
302
+ """
303
+ Inverse coordinate transformation
304
+
305
+ Args:
306
+ obj: Object to inverse transform
307
+
308
+ Returns:
309
+ Inverse transformed object
310
+ """
311
+ # Create inverse frame for transformation
312
+ dual = ~self
313
+ return dual.transform(obj)
314
+
315
+ # ========== Operator Overloading ==========
316
+
317
+ def __matmul__(self, other: Union[QuantumState, StateVector, vec3]) -> Union[StateVector, 'StateVector']:
318
+ """
319
+ Matrix multiplication operator: frame @ state
320
+
321
+ Transforms the state to this frame
322
+
323
+ Args:
324
+ other: State to transform
325
+
326
+ Returns:
327
+ Transformed state
328
+ """
329
+ return self.transform(other)
330
+
331
+ def __mul__(self, other: Union[QuantumState, StateVector, vec3]) -> Union[StateVector, 'StateVector']:
332
+ """
333
+ Multiplication operator: frame * state
334
+
335
+ Transforms the state to this frame (alternative to @)
336
+
337
+ Args:
338
+ other: State to transform
339
+
340
+ Returns:
341
+ Transformed state
342
+ """
343
+ return self.transform(other)
344
+
345
+ def __invert__(self) -> 'FourierFrame':
346
+ """
347
+ Inversion operator: ~frame
348
+
349
+ Get the dual frame (position ↔ momentum)
350
+
351
+ Returns:
352
+ Dual Fourier frame
353
+ """
354
+ if self.domain == 'position':
355
+ return FourierFrame(self.dim, 'momentum', self.N, self.range)
356
+ else:
357
+ return FourierFrame(self.dim, 'position', self.N, self.range)
358
+
359
+ # ========== Internal Transform Methods ==========
360
+
361
+ def _transform_single_state(self, state: QuantumState) -> StateVector:
362
+ """Transform a single quantum state"""
363
+ if state.basis != self.domain:
364
+ # Transform between different domains
365
+ return self._fourier_transform_single(state)
366
+ else:
367
+ # Same domain, return state vector directly
368
+ return StateVector([state], self.domain)
369
+
370
+ def _transform_state_vector(self, state_vector: StateVector) -> StateVector:
371
+ """Transform a state vector"""
372
+ if state_vector.basis != self.domain:
373
+ # Transform between different domains
374
+ return self._fourier_transform_vector(state_vector)
375
+ else:
376
+ # Same domain, return directly
377
+ return state_vector
378
+
379
+ def _transform_single_vector(self, vector: vec3) -> StateVector:
380
+ """Transform a single vector"""
381
+ results = []
382
+ for basis_vec in self.basis_vectors:
383
+ if self.dim == 1:
384
+ # Use Fourier kernel for 1D
385
+ if self.domain == 'position':
386
+ # Momentum → Position
387
+ amplitude = (1/np.sqrt(2*np.pi)) * np.exp(1j * vector.x * basis_vec.x)
388
+ else:
389
+ # Position → Momentum
390
+ amplitude = (1/np.sqrt(2*np.pi)) * np.exp(-1j * vector.x * basis_vec.x)
391
+
392
+ results.append(QuantumState(basis_vec, amplitude, self.domain))
393
+
394
+ return StateVector(results, self.domain)
395
+
396
+ def _fourier_transform_single(self, state: QuantumState) -> StateVector:
397
+ """Fourier transform a single quantum state"""
398
+ results = []
399
+ for target_basis in self.basis_vectors:
400
+ if self.dim == 1:
401
+ if state.basis == 'position' and self.domain == 'momentum':
402
+ # ⟨p|x⟩ = (1/√2π) exp(-i p x)
403
+ kernel = (1/np.sqrt(2*np.pi)) * np.exp(-1j * target_basis.x * state.basis_vector.x)
404
+ amplitude = kernel * state.amplitude
405
+ else:
406
+ # ⟨x|p⟩ = (1/√2π) exp(i p x)
407
+ kernel = (1/np.sqrt(2*np.pi)) * np.exp(1j * state.basis_vector.x * target_basis.x)
408
+ amplitude = kernel * state.amplitude
409
+
410
+ results.append(QuantumState(target_basis, amplitude, self.domain))
411
+
412
+ return StateVector(results, self.domain)
413
+
414
+ def _fourier_transform_vector(self, state_vector: StateVector) -> StateVector:
415
+ """Fourier transform a state vector"""
416
+ results = []
417
+ for target_basis in self.basis_vectors:
418
+ total_amplitude = 0 + 0j
419
+
420
+ # Transform all components of the original state vector
421
+ for component, amp in state_vector.components:
422
+ if self.dim == 1:
423
+ if state_vector.basis == 'position' and self.domain == 'momentum':
424
+ # ⟨p|x⟩ = (1/√2π) exp(-i p x)
425
+ kernel = (1/np.sqrt(2*np.pi)) * np.exp(-1j * target_basis.x * component.x)
426
+ else:
427
+ # ⟨x|p⟩ = (1/√2π) exp(i p x)
428
+ kernel = (1/np.sqrt(2*np.pi)) * np.exp(1j * component.x * target_basis.x)
429
+
430
+ total_amplitude += kernel * amp
431
+
432
+ results.append(QuantumState(target_basis, total_amplitude, self.domain))
433
+
434
+ return StateVector(results, self.domain)
435
+
436
+ def __repr__(self) -> str:
437
+ return f"FourierFrame(domain='{self.domain}', dim={self.dim}, samples={self.N})"
438
+
439
+
440
+ # ========== Utility Functions ==========
441
+
442
+ def create_gaussian_wavepacket(center: float = 0.0, width: float = 1.0,
443
+ momentum: float = 0.0,
444
+ frame: Optional[FourierFrame] = None) -> StateVector:
445
+ """
446
+ Create Gaussian wave packet
447
+
448
+ ψ(x) = (1/(πσ²)^(1/4)) exp(-(x-x₀)²/(2σ²)) exp(ip₀x)
449
+
450
+ Args:
451
+ center: Center position x₀
452
+ width: Width σ (standard deviation)
453
+ momentum: Central momentum p₀
454
+ frame: Fourier frame (creates default if None)
455
+
456
+ Returns:
457
+ StateVector representing the Gaussian wave packet
458
+ """
459
+ if frame is None:
460
+ frame = FourierFrame(dimension=1, domain='position', sample_points=64)
461
+
462
+ states = []
463
+ normalization = (1.0 / (np.pi * width**2))**0.25
464
+
465
+ for basis_vec in frame.basis_vectors:
466
+ x = basis_vec.x
467
+ # Gaussian envelope × plane wave
468
+ amplitude = normalization * np.exp(-(x - center)**2 / (2 * width**2)) * np.exp(1j * momentum * x)
469
+ states.append(QuantumState(basis_vec, amplitude, frame.domain))
470
+
471
+ return StateVector(states, frame.domain)
472
+
473
+
474
+ def fourier_transform(state_vector: StateVector, sample_points: int = 64) -> StateVector:
475
+ """
476
+ Fourier transform function: Position ↔ Momentum
477
+
478
+ Args:
479
+ state_vector: State vector to transform
480
+ sample_points: Number of sample points for result
481
+
482
+ Returns:
483
+ Transformed state vector
484
+ """
485
+ if state_vector.basis == 'position':
486
+ momentum_frame = FourierFrame(dimension=1, domain='momentum', sample_points=sample_points)
487
+ return momentum_frame @ state_vector # Using @ operator
488
+ else:
489
+ position_frame = FourierFrame(dimension=1, domain='position', sample_points=sample_points)
490
+ return position_frame @ state_vector # Using @ operator
491
+
492
+
493
+ def compute_uncertainty_product(state_vector: StateVector) -> Tuple[float, float, float]:
494
+ """
495
+ Compute uncertainty product ΔxΔp for a state
496
+
497
+ Demonstrates Heisenberg uncertainty principle: ΔxΔp ≥ ℏ/2
498
+
499
+ Args:
500
+ state_vector: State vector in position basis
501
+
502
+ Returns:
503
+ Tuple of (Δx, Δp, ΔxΔp)
504
+ """
505
+ # Position uncertainty
506
+ if state_vector.basis != 'position':
507
+ raise ValueError("State must be in position basis")
508
+
509
+ delta_x = state_vector.standard_deviation()
510
+
511
+ # Transform to momentum space using @ operator
512
+ momentum_state = fourier_transform(state_vector)
513
+ delta_p = momentum_state.standard_deviation()
514
+
515
+ # Uncertainty product
516
+ product = delta_x * delta_p
517
+
518
+ return delta_x, delta_p, product
519
+
520
+
521
+ # ========== Export ==========
522
+
523
+ __all__ = [
524
+ 'FourierFrame',
525
+ 'QuantumState',
526
+ 'StateVector',
527
+ 'create_gaussian_wavepacket',
528
+ 'fourier_transform',
529
+ 'compute_uncertainty_product',
530
+ ]