wavefunction 0.0.1__tar.gz

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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2001 ... 2025 Juha Meskanen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: wavefunction
3
+ Version: 0.0.1
4
+ Summary: Quantum Wavefunction with Spectral Complexity measure
5
+ Author-email: Juha Meskanen <juha@meskanen.com>
6
+ Maintainer-email: Juha Meskanen <juha@meskanen.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/juhakm/wavefunction
9
+ Project-URL: Bug Reports, https://github.com/juhakm/wavefunction
10
+ Project-URL: Say Thanks!, https://github.com/juhakm/wavefunction
11
+ Project-URL: Source, https://github.com/juhakm/wavefunction
12
+ Keywords: quantum,quantum-field-theory,information-theory,wavefunction,spinor,emergent-physics,minimal-spectral-length,computational-physics
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Intended Audience :: Education
16
+ Classifier: Topic :: Scientific/Engineering
17
+ Classifier: Topic :: Scientific/Engineering :: Physics
18
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
19
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
20
+ Classifier: Programming Language :: Python
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Typing :: Typed
26
+ Classifier: Operating System :: OS Independent
27
+ Requires-Python: >=3.9
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: numpy<1.27,>=1.25
31
+ Requires-Dist: scipy>=1.10
32
+ Requires-Dist: numba>=0.59
33
+ Requires-Dist: matplotlib
34
+ Dynamic: license-file
35
+
36
+ # Wavefunction
37
+
38
+ Quantum Mechanical complex valued wavefunction with Spectral Complexity measure.
39
+
40
+ ## Install
41
+
42
+ ```
43
+ pip install wavefunction
44
+ ```
45
+
46
+ [https://pypi.org/project/wavefunction/](https://pypi.org/project/wavefunction/)
47
+
@@ -0,0 +1,12 @@
1
+ # Wavefunction
2
+
3
+ Quantum Mechanical complex valued wavefunction with Spectral Complexity measure.
4
+
5
+ ## Install
6
+
7
+ ```
8
+ pip install wavefunction
9
+ ```
10
+
11
+ [https://pypi.org/project/wavefunction/](https://pypi.org/project/wavefunction/)
12
+
@@ -0,0 +1,85 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.setuptools]
6
+ include-package-data = true
7
+ packages = ["wavefunction"]
8
+
9
+ [project]
10
+ name = "wavefunction"
11
+ version = "0.0.1"
12
+ description = "Quantum Wavefunction with Spectral Complexity measure"
13
+ readme = {file = "README.md", content-type = "text/markdown"}
14
+ requires-python = ">=3.9"
15
+ license = "MIT"
16
+
17
+ keywords = [
18
+ "quantum",
19
+ "quantum-field-theory",
20
+ "information-theory",
21
+ "wavefunction",
22
+ "spinor",
23
+ "emergent-physics",
24
+ "minimal-spectral-length",
25
+ "computational-physics"
26
+ ]
27
+
28
+
29
+ authors = [
30
+ {name = "Juha Meskanen", email = "juha@meskanen.com" }
31
+ ]
32
+ maintainers = [
33
+ {name = "Juha Meskanen", email = "juha@meskanen.com" }
34
+ ]
35
+
36
+ classifiers = [
37
+ # Development maturity
38
+ "Development Status :: 4 - Beta",
39
+
40
+ # Intended audience
41
+ "Intended Audience :: Science/Research",
42
+ "Intended Audience :: Education",
43
+
44
+ # Topic classification
45
+ "Topic :: Scientific/Engineering",
46
+ "Topic :: Scientific/Engineering :: Physics",
47
+ "Topic :: Scientific/Engineering :: Mathematics",
48
+ "Topic :: Scientific/Engineering :: Information Analysis",
49
+
50
+ # Programming language
51
+ "Programming Language :: Python",
52
+ "Programming Language :: Python :: 3",
53
+ "Programming Language :: Python :: 3.9",
54
+ "Programming Language :: Python :: 3.10",
55
+ "Programming Language :: Python :: 3.11",
56
+
57
+ # Typing / implementation
58
+ "Typing :: Typed",
59
+ "Operating System :: OS Independent",
60
+ ]
61
+
62
+
63
+ dependencies = [
64
+ "numpy>=1.25,<1.27",
65
+ "scipy>=1.10",
66
+ "numba>=0.59",
67
+ "matplotlib",
68
+ ]
69
+
70
+
71
+ [project.urls]
72
+ "Homepage" = "https://github.com/juhakm/wavefunction"
73
+ "Bug Reports" = "https://github.com/juhakm/wavefunction"
74
+ "Say Thanks!" = "https://github.com/juhakm/wavefunction"
75
+ "Source" = "https://github.com/juhakm/wavefunction"
76
+
77
+
78
+ [tool.mypy]
79
+ files = ["wavefunction/*.py"]
80
+ ignore_missing_imports = false
81
+
82
+
83
+ [tool.setuptools.package-data]
84
+ "wavefunction" = ["py.typed"]
85
+
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,6 @@
1
+ from .wavefunction import Wavefunction
2
+
3
+
4
+ __all__ = [
5
+ "Wavefunction"
6
+ ]
File without changes
@@ -0,0 +1,675 @@
1
+ """Spectral Complexity measure for complex-valued wavefunctions.
2
+
3
+ Theory background (Meskanen 2026 — "The Wavefunction as Compression")
4
+ ======================================================================
5
+ The central hypothesis is that the quantum wavefunction is the universe's
6
+ data-compression codec. Internal observers — themselves composed of
7
+ compressed structures — perceive their constituent degrees of freedom as
8
+ wave-like because they are observing *compressed information*. The codec
9
+ that produces this compression is the Fourier / spectral decomposition.
10
+
11
+ Spectral Complexity C_s
12
+ -----------------------
13
+ A wavefunction ψ(x) can always be written as a superposition of spectral
14
+ modes, each characterised by two attributes:
15
+
16
+ frequency ω — the rate of oscillation, unbounded above zero
17
+ phase φ — the offset of the oscillation, bounded in [0, 2π)
18
+
19
+ The *spectral complexity* C_s(ψ) is the total continuous information cost
20
+ needed to specify the set of modes that materially compose ψ:
21
+
22
+ C_s(ψ) = Σ_i [ ω_i / Δω + φ_cost(φ_i) ]
23
+
24
+ Frequency cost (dominant term)
25
+ ω_i / Δω is the number of resolution steps Δω needed to locate
26
+ frequency ω_i. It is unbounded, continuous, and grows linearly with
27
+ frequency. This term *dominates* C_s and is the reason the measure
28
+ exponentially suppresses high-frequency (rough, chaotic) states.
29
+ The identification Δω = ℏ ln 2 connects the minimum frequency
30
+ resolution to Planck's constant (Meskanen 2026, §3.1).
31
+
32
+ Phase cost (subdominant, bounded)
33
+ Each phase φ_i ∈ [0, 2π) requires a finite amount of information to
34
+ specify. The cost is *global* over all modes: it measures how much
35
+ information is needed to distinguish the phases from one another.
36
+ With only two modes at phases 0 and π, very little is needed; with
37
+ many modes at crowded, uneven phases, somewhat more is required.
38
+ In practice this term is bounded by log₂(N_modes) and is a
39
+ second-order correction. The current implementation uses a simple
40
+ uniform fixed cost per non-reference mode as a tractable proxy; the
41
+ reference mode (highest amplitude) is exempt because only *relative*
42
+ phases are observable — a global phase shift leaves |ψ(x)|² unchanged.
43
+
44
+ Amplitude and the fidelity engine
45
+ Amplitude does not appear as a separate encoding cost. Instead it
46
+ determines *which modes are included* in the description via a
47
+ power-ranked fidelity engine: modes are added in descending power
48
+ order until the accumulated power reaches a target fraction of the
49
+ total. Modes below this threshold are simply absent from the
50
+ description — they are not part of the codec output and contribute
51
+ zero complexity cost. This correctly handles the case where many
52
+ weak modes coexist with a few dominant ones: the dominant modes
53
+ determine C_s; the weak modes are free.
54
+
55
+ Solomonoff suppression and the probability profile
56
+ Under Solomonoff-like induction the prior probability of a
57
+ configuration is P(ψ) ∝ 2^{-C_s(ψ)}. Because C_s is a *sum* over
58
+ independent modes, the probability *factorises*:
59
+
60
+ P(ψ) ∝ Π_i 2^{-ω_i/Δω}
61
+
62
+ Each mode is suppressed independently and exponentially by its
63
+ frequency. The resulting probability profile is Boltzmann-like with
64
+ inverse temperature β = ln(2)/Δω:
65
+
66
+ P(mode i present) ∝ exp(−ln(2) · ω_i / Δω)
67
+
68
+ Smooth, low-frequency, compressible states dominate the measure.
69
+ Boltzmann brains, random fluctuations, and chaotic configurations
70
+ are exponentially suppressed — not by fine-tuning, but because they
71
+ require many high-frequency modes to describe.
72
+
73
+ The conjecture C_s ∝ S_Euclidean
74
+ The central open conjecture (Meskanen 2026, §4) is that the minimum
75
+ spectral complexity path through configuration space coincides with
76
+ the minimum Euclidean action path of standard quantum gravity. If
77
+ true, quantum gravity is Solomonoff induction over compressed
78
+ descriptions of geometry, and ℏ is the minimum spectral resolution
79
+ of a finite informational universe.
80
+ """
81
+
82
+ from __future__ import annotations
83
+
84
+ import numpy as np
85
+ from dataclasses import dataclass
86
+ from typing import Optional
87
+
88
+
89
+ # ---------------------------------------------------------------------------
90
+ # Spectral mode
91
+ # ---------------------------------------------------------------------------
92
+
93
+ @dataclass
94
+ class SpectralMode:
95
+ """A single Fourier mode in the spectral decomposition of a wavefunction.
96
+
97
+ Attributes:
98
+ frequency: Angular frequency ω (rad / spatial-unit). Signed —
99
+ positive and negative frequencies are physically distinct for
100
+ complex ψ. The frequency cost uses |ω|.
101
+ amplitude: Real-valued mode amplitude A ≥ 0, equal to
102
+ |FFT_k| / N after normalisation. Used only by the fidelity
103
+ engine to rank modes by power; it does not appear in C_s.
104
+ phase: Mode phase φ ∈ [0, 2π), equal to arg(FFT_k) mod 2π.
105
+ Relative phases between modes determine interference structure
106
+ and enter C_s through the (subdominant) phase cost term.
107
+ """
108
+
109
+ frequency: float
110
+ amplitude: float
111
+ phase: float
112
+
113
+ def __post_init__(self) -> None:
114
+ self.amplitude = float(abs(self.amplitude))
115
+ self.phase = float(self.phase % (2.0 * np.pi))
116
+
117
+
118
+ # ---------------------------------------------------------------------------
119
+ # Wavefunction
120
+ # ---------------------------------------------------------------------------
121
+
122
+ class Wavefunction:
123
+ """A normalised complex wavefunction on a uniform 1-D spatial grid.
124
+
125
+ The wavefunction ψ(x) is stored as a complex NumPy array of length N.
126
+ Its primary analytical interface is the spectral complexity C_s(ψ),
127
+ a continuous, computable measure of how many spectral resources are
128
+ required to describe ψ to a given fidelity.
129
+
130
+ Spectral complexity formula
131
+ ---------------------------
132
+ C_s(ψ) = Σ_{i ∈ retained} [ |ω_i| / Δω + φ_cost(i) ]
133
+
134
+ where the sum runs over modes retained by the fidelity engine
135
+ (see below), and:
136
+
137
+ |ω_i| / Δω — frequency cost: dominant, continuous, unbounded.
138
+ Mirrors E = ℏω; under Solomonoff suppression
139
+ 2^{-C_s} this produces an exponential / Boltzmann
140
+ distribution over frequency.
141
+
142
+ φ_cost(i) — phase cost: subdominant, bounded. Zero for the
143
+ reference mode (highest amplitude — global phase
144
+ unobservable); a fixed resolution cost
145
+ `phase_resolution` for every other retained mode.
146
+ Represents the information needed to distinguish
147
+ this mode's phase from the reference.
148
+
149
+ Fidelity engine
150
+ ---------------
151
+ Not all FFT bins materially contribute to ψ. The fidelity engine
152
+ ranks bins by power (|FFT_k|²) and greedily accumulates them until
153
+ the retained set accounts for at least `fidelity_target` of the
154
+ total power. Only retained modes enter C_s. This has two effects:
155
+
156
+ 1. Correctness: two wavefunctions with the same |ψ(x)|² but
157
+ different numbers of negligible-power modes receive the same C_s.
158
+ The codec describes the *observable state*, not a particular
159
+ representation.
160
+
161
+ 2. Stability: noise and numerical artefacts in low-power bins do
162
+ not inflate C_s.
163
+
164
+ Planck identification
165
+ ---------------------
166
+ The minimum resolvable frequency Δω defaults to 2π / (N dx), the
167
+ natural FFT resolution of the grid. The identification
168
+ ℏ = Δω / ln(2) connects this resolution to Planck's constant
169
+ (Meskanen 2026, §3.1). This is a correspondence to be investigated,
170
+ not a derivation.
171
+
172
+ Args:
173
+ psi: Complex wavefunction amplitudes on a uniform spatial grid.
174
+ Normalised to unit L² norm on construction.
175
+ dx: Spatial grid spacing. Determines angular frequencies via
176
+ ω_k = 2π k / (N dx). Defaults to 1.0.
177
+ delta_omega: Minimum resolvable angular frequency Δω. Defaults
178
+ to the natural FFT resolution 2π / (N dx).
179
+ fidelity_target: Fraction of total spectral power that the
180
+ retained modes must collectively explain. Must be in (0, 1].
181
+ Higher values retain more modes and increase C_s.
182
+ Defaults to 0.999 (99.9 % of power).
183
+ phase_resolution: Continuous cost assigned to the phase of each
184
+ non-reference retained mode. Represents the information
185
+ needed to resolve that mode's phase from the reference to
186
+ the required precision. Bounded and subdominant relative to
187
+ the frequency cost. Defaults to 1.0 (one unit per mode,
188
+ interpretable as ~ 1 bit of phase separation information).
189
+
190
+ Attributes:
191
+ dx: Spatial grid spacing.
192
+ delta_omega: Minimum resolvable angular frequency Δω.
193
+ fidelity_target: Power-fidelity threshold for mode retention.
194
+ phase_resolution: Per-mode phase cost for non-reference modes.
195
+ hbar_identified: Δω / ln(2) — the value of ℏ implied by the
196
+ grid resolution under the Meskanen (2026) identification.
197
+ """
198
+
199
+ def __init__(
200
+ self,
201
+ psi: np.ndarray,
202
+ dx: float = 1.0,
203
+ delta_omega: Optional[float] = None,
204
+ fidelity_target: float = 0.999,
205
+ phase_resolution: float = 1.0,
206
+ ) -> None:
207
+ self._psi: np.ndarray = self._normalise(np.asarray(psi, dtype=complex))
208
+ self.dx: float = float(dx)
209
+ self.fidelity_target: float = float(fidelity_target)
210
+ self.phase_resolution: float = float(phase_resolution)
211
+
212
+ N = len(self._psi)
213
+ self.delta_omega: float = (
214
+ float(delta_omega) if delta_omega is not None
215
+ else 2.0 * np.pi / (N * self.dx)
216
+ )
217
+ self.hbar_identified: float = self.delta_omega / np.log(2.0)
218
+
219
+ # ------------------------------------------------------------------
220
+ # Core properties
221
+ # ------------------------------------------------------------------
222
+
223
+ @property
224
+ def psi(self) -> np.ndarray:
225
+ """Normalised complex wavefunction array ψ(x), shape (N,)."""
226
+ return self._psi
227
+
228
+ @property
229
+ def N(self) -> int:
230
+ """Number of spatial grid points."""
231
+ return len(self._psi)
232
+
233
+ @property
234
+ def x(self) -> np.ndarray:
235
+ """Spatial grid positions x_n = n · dx, shape (N,)."""
236
+ return np.arange(self.N) * self.dx
237
+
238
+ @property
239
+ def probability_density(self) -> np.ndarray:
240
+ """|ψ(x)|² — Born-rule probability density, shape (N,).
241
+
242
+ Normalised so that sum(|ψ|²) = 1 (discrete L² norm).
243
+ """
244
+ return np.abs(self._psi) ** 2
245
+
246
+ # ------------------------------------------------------------------
247
+ # Fidelity engine — mode selection
248
+ # ------------------------------------------------------------------
249
+
250
+ def retained_modes(self) -> list[SpectralMode]:
251
+ """Return the set of spectral modes retained by the fidelity engine.
252
+
253
+ Modes are ranked by power (|FFT_k|²) in descending order and
254
+ accumulated greedily until the retained set accounts for at least
255
+ `fidelity_target` of the total power. The result is the minimal
256
+ set of modes that reproduces ψ(x) to the required fidelity.
257
+
258
+ The reference mode (highest power, first in the ranked list) is
259
+ flagged implicitly: its phase is the global reference and costs
260
+ nothing. All other retained modes pay `phase_resolution`.
261
+
262
+ Returns:
263
+ List of SpectralMode objects sorted by ascending |ω|, one per
264
+ retained FFT bin. The highest-power mode appears somewhere
265
+ in this list and is identifiable as the one with the largest
266
+ amplitude.
267
+ """
268
+ N = self.N
269
+ fft_coeffs: np.ndarray = np.fft.fft(self._psi)
270
+ freqs: np.ndarray = 2.0 * np.pi * np.fft.fftfreq(N, d=self.dx)
271
+ power: np.ndarray = np.abs(fft_coeffs) ** 2
272
+ total_power: float = float(power.sum())
273
+
274
+ if total_power == 0.0:
275
+ return []
276
+
277
+ # Rank bins by descending power
278
+ sorted_idx: np.ndarray = np.argsort(power)[::-1]
279
+
280
+ accumulated: float = 0.0
281
+ kept: list[int] = []
282
+ for idx in sorted_idx:
283
+ accumulated += float(power[idx])
284
+ kept.append(int(idx))
285
+ if accumulated / total_power >= self.fidelity_target:
286
+ break
287
+
288
+ modes: list[SpectralMode] = [
289
+ SpectralMode(
290
+ frequency=float(freqs[k]),
291
+ amplitude=float(np.abs(fft_coeffs[k])) / N,
292
+ phase=float(np.angle(fft_coeffs[k]) % (2.0 * np.pi)),
293
+ )
294
+ for k in kept
295
+ ]
296
+ modes.sort(key=lambda m: abs(m.frequency))
297
+ return modes
298
+
299
+ # ------------------------------------------------------------------
300
+ # Spectral complexity C_s(ψ)
301
+ # ------------------------------------------------------------------
302
+
303
+ def spectral_complexity(self, verbose: bool = False) -> float:
304
+ """Compute the spectral complexity C_s(ψ).
305
+
306
+ C_s is the total continuous information cost of specifying the
307
+ retained spectral modes:
308
+
309
+ C_s(ψ) = Σ_{i ∈ retained} [ |ω_i| / Δω + φ_cost(i) ]
310
+
311
+ where φ_cost(i) = 0 for the reference mode (highest amplitude)
312
+ and `phase_resolution` for all other retained modes.
313
+
314
+ The frequency term |ω_i| / Δω is the dominant, unbounded
315
+ contribution. The phase term is a bounded correction that
316
+ accounts for the information needed to distinguish each mode's
317
+ phase from the reference.
318
+
319
+ Under Solomonoff suppression P(ψ) ∝ 2^{-C_s(ψ)}, and because
320
+ the sum factorises over modes:
321
+
322
+ P(ψ) ∝ Π_i 2^{-|ω_i|/Δω} · 2^{-φ_cost(i)}
323
+
324
+ The probability profile is exponential in frequency — each mode
325
+ independently suppressed by its oscillation rate.
326
+
327
+ Args:
328
+ verbose: If True, print a per-mode breakdown to stdout.
329
+
330
+ Returns:
331
+ C_s as a non-negative float. Zero only if no modes are
332
+ retained (degenerate zero wavefunction).
333
+ """
334
+ modes: list[SpectralMode] = self.retained_modes()
335
+ if not modes:
336
+ return 0.0
337
+
338
+ # Reference mode: highest amplitude — pays zero phase cost.
339
+ # Only relative phases are observable; the highest-amplitude mode
340
+ # is the natural phase reference. Ties broken by lowest |ω| for
341
+ # numerical stability (avoids C_s jumping by 1 when two equal-power
342
+ # modes exchange amplitudes under tiny perturbations).
343
+ ref_amplitude: float = max(m.amplitude for m in modes)
344
+ ref_freq_abs: float = min(
345
+ abs(m.frequency) for m in modes if m.amplitude == ref_amplitude
346
+ )
347
+
348
+ total: float = 0.0
349
+
350
+ if verbose:
351
+ print(f"\n {'i':>4} {'ω':>10} {'A':>9} {'φ/2π':>7} "
352
+ f"{'|ω|/Δω':>10} {'φ_cost':>7} {'mode C_s':>9}")
353
+ print(" " + "-" * 62)
354
+
355
+ for i, mode in enumerate(modes):
356
+ freq_cost: float = abs(mode.frequency) / self.delta_omega
357
+ # Reference mode (global phase) is unobservable — zero phase cost
358
+ is_reference: bool = (
359
+ mode.amplitude == ref_amplitude
360
+ and abs(mode.frequency) == ref_freq_abs
361
+ )
362
+ phase_cost: float = 0.0 if is_reference else self.phase_resolution
363
+ mode_cs: float = freq_cost + phase_cost
364
+ total += mode_cs
365
+
366
+ if verbose:
367
+ print(f" {i:>4} {mode.frequency:>10.4f} {mode.amplitude:>9.5f}"
368
+ f" {mode.phase / (2*np.pi):>7.4f}"
369
+ f" {freq_cost:>10.3f} {phase_cost:>7.2f} {mode_cs:>9.3f}"
370
+ + (" ← ref" if is_reference else ""))
371
+
372
+ if verbose:
373
+ print(" " + "-" * 62)
374
+ n_ret = len(modes)
375
+ print(f" C_s = {total:.4f} "
376
+ f"({n_ret} modes retained at fidelity ≥ {self.fidelity_target})\n")
377
+
378
+ return total
379
+
380
+ # ------------------------------------------------------------------
381
+ # Derived quantities
382
+ # ------------------------------------------------------------------
383
+
384
+ def solomonoff_weight(self) -> float:
385
+ """Unnormalised Solomonoff prior weight 2^{-C_s(ψ)}.
386
+
387
+ Under Solomonoff-like induction, configurations are weighted by
388
+ their compressibility. The weight is exponential in C_s:
389
+
390
+ w(ψ) = 2^{-C_s(ψ)}
391
+
392
+ Because C_s factorises over modes, this equals the product of
393
+ per-mode suppression factors:
394
+
395
+ w(ψ) = Π_i 2^{-|ω_i|/Δω} · 2^{-φ_cost(i)}
396
+
397
+ Smooth, low-frequency wavefunctions receive exponentially higher
398
+ weight than chaotic, high-frequency ones.
399
+
400
+ Returns:
401
+ Float in (0, 1]. Returns 1.0 for the zero wavefunction
402
+ (no retained modes, C_s = 0).
403
+ """
404
+ return 2.0 ** (-self.spectral_complexity())
405
+
406
+ def mode_suppression_factors(self) -> dict[float, float]:
407
+ """Per-mode Boltzmann suppression factors from the frequency cost.
408
+
409
+ For each retained mode i, the frequency term |ω_i| / Δω
410
+ contributes an independent suppression factor:
411
+
412
+ s_i = 2^{-|ω_i|/Δω} = exp(−ln2 · |ω_i| / Δω)
413
+
414
+ This is a Boltzmann factor with inverse temperature
415
+ β = ln(2) / Δω. The identification ℏ = Δω / ln(2) makes
416
+ β = 1 / ℏ in natural units, consistent with E = ℏω.
417
+
418
+ Returns:
419
+ Dict mapping ω_i (float) → unnormalised suppression factor s_i.
420
+ The factors are *not* normalised to a probability distribution
421
+ here; use solomonoff_weight() for the joint weight of the full
422
+ wavefunction.
423
+ """
424
+ return {
425
+ m.frequency: 2.0 ** (-abs(m.frequency) / self.delta_omega)
426
+ for m in self.retained_modes()
427
+ }
428
+
429
+ # ------------------------------------------------------------------
430
+ # Convenience constructors
431
+ # ------------------------------------------------------------------
432
+
433
+ @classmethod
434
+ def gaussian_packet(
435
+ cls,
436
+ N: int = 256,
437
+ x0: float = 0.0,
438
+ sigma: float = 1.0,
439
+ k0: float = 1.0,
440
+ dx: float = 0.1,
441
+ **kwargs,
442
+ ) -> "Wavefunction":
443
+ """Construct a Gaussian wave packet.
444
+
445
+ ψ(x) = exp(−(x−x0)² / 4σ²) · exp(i k0 x), then normalised.
446
+
447
+ A Gaussian packet is narrow in both position and momentum space
448
+ and serves as a natural low-C_s reference state: it has a single
449
+ dominant frequency k0 and a smooth Gaussian envelope that
450
+ concentrates spectral power near k0.
451
+
452
+ Args:
453
+ N: Number of grid points.
454
+ x0: Packet centre in position space.
455
+ sigma: Position-space width (standard deviation).
456
+ k0: Carrier wavenumber (dominant angular frequency ω ≈ k0).
457
+ dx: Spatial grid spacing.
458
+ **kwargs: Passed to Wavefunction.__init__
459
+ (e.g. fidelity_target, phase_resolution).
460
+
461
+ Returns:
462
+ Normalised Wavefunction instance.
463
+ """
464
+ x = np.arange(N) * dx
465
+ psi = np.exp(-((x - x0) ** 2) / (4.0 * sigma ** 2)) * np.exp(1j * k0 * x)
466
+ return cls(psi, dx=dx, **kwargs)
467
+
468
+ @classmethod
469
+ def plane_wave_superposition(
470
+ cls,
471
+ N: int = 256,
472
+ amplitudes: list[float] = (0.6, 0.8),
473
+ wavenumbers: list[float] = (1.0, 3.0),
474
+ phases: list[float] = (0.0, 0.0),
475
+ dx: float = 0.1,
476
+ **kwargs,
477
+ ) -> "Wavefunction":
478
+ """Construct an explicit superposition of plane waves.
479
+
480
+ ψ(x) = Σ_i α_i · exp(i (k_i x + φ_i)), then normalised.
481
+
482
+ Useful for constructing states with known spectral structure and
483
+ testing how C_s responds to adding modes or shifting phases.
484
+
485
+ Args:
486
+ N: Number of grid points.
487
+ amplitudes: Real amplitudes α_i for each plane wave.
488
+ wavenumbers: Wavenumbers k_i (angular frequencies ω_i = k_i).
489
+ phases: Initial phases φ_i for each plane wave.
490
+ dx: Spatial grid spacing.
491
+ **kwargs: Passed to Wavefunction.__init__.
492
+
493
+ Returns:
494
+ Normalised Wavefunction instance.
495
+ """
496
+ x = np.arange(N) * dx
497
+ psi = np.zeros(N, dtype=complex)
498
+ for a, k, phi in zip(amplitudes, wavenumbers, phases):
499
+ psi += a * np.exp(1j * (k * x + phi))
500
+ return cls(psi, dx=dx, **kwargs)
501
+
502
+ @classmethod
503
+ def random_state(
504
+ cls,
505
+ N: int = 256,
506
+ seed: int = 42,
507
+ dx: float = 0.1,
508
+ **kwargs,
509
+ ) -> "Wavefunction":
510
+ """Construct a maximally chaotic (high-C_s) random wavefunction.
511
+
512
+ Draws real and imaginary parts independently from N(0,1). The
513
+ resulting state activates all FFT bins with roughly equal power,
514
+ giving the maximum number of retained modes and hence the highest
515
+ possible C_s for a given N. Useful as an upper-bound reference.
516
+
517
+ Args:
518
+ N: Number of grid points.
519
+ seed: Random seed for reproducibility.
520
+ dx: Spatial grid spacing.
521
+ **kwargs: Passed to Wavefunction.__init__.
522
+
523
+ Returns:
524
+ Normalised Wavefunction instance.
525
+ """
526
+ rng = np.random.default_rng(seed)
527
+ psi = rng.standard_normal(N) + 1j * rng.standard_normal(N)
528
+ return cls(psi, dx=dx, **kwargs)
529
+
530
+ # ------------------------------------------------------------------
531
+ # Arithmetic
532
+ # ------------------------------------------------------------------
533
+
534
+ def __add__(self, other: "Wavefunction") -> "Wavefunction":
535
+ """Superpose two wavefunctions: ψ_new = normalise(ψ_a + ψ_b).
536
+
537
+ The result is renormalised. Interference fringes in the
538
+ superposition share spectral modes, so C_s(ψ_a + ψ_b) is
539
+ typically less than C_s(ψ_a) + C_s(ψ_b) — the codec description
540
+ of the superposition is cheaper than two independent descriptions.
541
+
542
+ Args:
543
+ other: Wavefunction on the same grid (same N and dx).
544
+
545
+ Returns:
546
+ New normalised Wavefunction.
547
+
548
+ Raises:
549
+ ValueError: If grid sizes differ.
550
+ """
551
+ if self.N != other.N:
552
+ raise ValueError(
553
+ f"Grid size mismatch: {self.N} vs {other.N}")
554
+ return Wavefunction(
555
+ self._psi + other._psi,
556
+ dx=self.dx,
557
+ delta_omega=self.delta_omega,
558
+ fidelity_target=self.fidelity_target,
559
+ phase_resolution=self.phase_resolution,
560
+ )
561
+
562
+ def __mul__(self, scalar: complex) -> "Wavefunction":
563
+ """Scale ψ by a complex scalar (result is renormalised)."""
564
+ return Wavefunction(
565
+ self._psi * scalar,
566
+ dx=self.dx,
567
+ delta_omega=self.delta_omega,
568
+ fidelity_target=self.fidelity_target,
569
+ phase_resolution=self.phase_resolution,
570
+ )
571
+
572
+ def __rmul__(self, scalar: complex) -> "Wavefunction":
573
+ return self.__mul__(scalar)
574
+
575
+ def inner_product(self, other: "Wavefunction") -> complex:
576
+ """Discrete inner product ⟨self|other⟩ = Σ_x ψ*(x) φ(x) dx.
577
+
578
+ Args:
579
+ other: Wavefunction on the same grid.
580
+
581
+ Returns:
582
+ Complex scalar.
583
+ """
584
+ return complex(np.sum(self._psi.conj() * other._psi) * self.dx)
585
+
586
+ # ------------------------------------------------------------------
587
+ # Internal helpers
588
+ # ------------------------------------------------------------------
589
+
590
+ @staticmethod
591
+ def _normalise(psi: np.ndarray) -> np.ndarray:
592
+ """Normalise ψ to unit L² norm.
593
+
594
+ Args:
595
+ psi: Complex array.
596
+
597
+ Returns:
598
+ ψ / ‖ψ‖.
599
+
600
+ Raises:
601
+ ValueError: If ψ is identically zero.
602
+ """
603
+ norm: float = float(np.sqrt(np.sum(np.abs(psi) ** 2)))
604
+ if norm == 0.0:
605
+ raise ValueError("Cannot normalise a zero wavefunction.")
606
+ return psi / norm
607
+
608
+ def __repr__(self) -> str:
609
+ cs = self.spectral_complexity()
610
+ n_modes = len(self.retained_modes())
611
+ return (
612
+ f"Wavefunction(N={self.N}, dx={self.dx}, "
613
+ f"C_s={cs:.3f}, modes={n_modes}, "
614
+ f"ℏ_id={self.hbar_identified:.3e})"
615
+ )
616
+
617
+
618
+ # ---------------------------------------------------------------------------
619
+ # Demo
620
+ # ---------------------------------------------------------------------------
621
+
622
+ if __name__ == "__main__":
623
+ print(__doc__)
624
+ print("=" * 65)
625
+ print("Demo")
626
+ print("=" * 65)
627
+
628
+ # 1. Gaussian packet — few dominant modes, low C_s
629
+ gp = Wavefunction.gaussian_packet(N=256, x0=12.8, sigma=2.0, k0=2.0, dx=0.1)
630
+ print("\n[1] Gaussian wave packet")
631
+ gp.spectral_complexity(verbose=True)
632
+ print(gp)
633
+
634
+ # 2. Two-component superposition — moderate C_s
635
+ sp = Wavefunction.plane_wave_superposition(
636
+ N=256, amplitudes=[0.6, 0.8],
637
+ wavenumbers=[1.0, 5.0], phases=[0.0, np.pi / 4], dx=0.1)
638
+ print("\n[2] Two-component superposition")
639
+ sp.spectral_complexity(verbose=True)
640
+ print(sp)
641
+
642
+ # 3. Random state — all modes active, high C_s
643
+ rnd = Wavefunction.random_state(N=256, seed=0, dx=0.1)
644
+ print("\n[3] Random (high-entropy) state")
645
+ print(f" C_s = {rnd.spectral_complexity():.2f} (verbose suppressed)")
646
+ print(rnd)
647
+
648
+ # 4. Solomonoff weights — exponential ordering
649
+ print("\nSolomonoff weights 2^{{-C_s}}:")
650
+ for label, wf in [("Gaussian", gp), ("Superposition", sp), ("Random", rnd)]:
651
+ print(f" {label:>16s}: {wf.solomonoff_weight():.4e}")
652
+
653
+ # 5. Interference economy
654
+ gp2 = Wavefunction.gaussian_packet(N=256, x0=20.0, sigma=2.0, k0=2.0, dx=0.1)
655
+ combined = gp + gp2
656
+ print(f"\n[5] Interference economy:")
657
+ print(f" C_s(ψ₁) = {gp.spectral_complexity():.2f}")
658
+ print(f" C_s(ψ₂) = {gp2.spectral_complexity():.2f}")
659
+ print(f" C_s(ψ₁ + ψ₂) = {combined.spectral_complexity():.2f}")
660
+ print(" Superposition is cheaper than two independent descriptions.")
661
+
662
+ # 6. Fidelity engine: weak modes don't inflate C_s
663
+ x = np.arange(64)
664
+ psi_clean = sum(np.exp(1j * 2*np.pi*k*x/64) for k in [2, 7, 13])
665
+ rng = np.random.default_rng(0)
666
+ psi_noisy = psi_clean + 0.01 * sum(
667
+ np.exp(1j * (2*np.pi*k*x/64 + rng.uniform(0, 2*np.pi)))
668
+ for k in range(20, 50))
669
+ wf_clean = Wavefunction(psi_clean, dx=0.1)
670
+ wf_noisy = Wavefunction(psi_noisy, dx=0.1)
671
+ print(f"\n[6] Fidelity engine — weak modes ignored:")
672
+ print(f" C_s(clean, 3 modes) = {wf_clean.spectral_complexity():.3f}")
673
+ print(f" C_s(+ 30 weak noise modes) = {wf_noisy.spectral_complexity():.3f}")
674
+ print(f" Modes retained (clean/noisy) = "
675
+ f"{len(wf_clean.retained_modes())} / {len(wf_noisy.retained_modes())}")
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: wavefunction
3
+ Version: 0.0.1
4
+ Summary: Quantum Wavefunction with Spectral Complexity measure
5
+ Author-email: Juha Meskanen <juha@meskanen.com>
6
+ Maintainer-email: Juha Meskanen <juha@meskanen.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/juhakm/wavefunction
9
+ Project-URL: Bug Reports, https://github.com/juhakm/wavefunction
10
+ Project-URL: Say Thanks!, https://github.com/juhakm/wavefunction
11
+ Project-URL: Source, https://github.com/juhakm/wavefunction
12
+ Keywords: quantum,quantum-field-theory,information-theory,wavefunction,spinor,emergent-physics,minimal-spectral-length,computational-physics
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Intended Audience :: Education
16
+ Classifier: Topic :: Scientific/Engineering
17
+ Classifier: Topic :: Scientific/Engineering :: Physics
18
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
19
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
20
+ Classifier: Programming Language :: Python
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Typing :: Typed
26
+ Classifier: Operating System :: OS Independent
27
+ Requires-Python: >=3.9
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: numpy<1.27,>=1.25
31
+ Requires-Dist: scipy>=1.10
32
+ Requires-Dist: numba>=0.59
33
+ Requires-Dist: matplotlib
34
+ Dynamic: license-file
35
+
36
+ # Wavefunction
37
+
38
+ Quantum Mechanical complex valued wavefunction with Spectral Complexity measure.
39
+
40
+ ## Install
41
+
42
+ ```
43
+ pip install wavefunction
44
+ ```
45
+
46
+ [https://pypi.org/project/wavefunction/](https://pypi.org/project/wavefunction/)
47
+
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ wavefunction/__init__.py
5
+ wavefunction/py.typed
6
+ wavefunction/wavefunction.py
7
+ wavefunction.egg-info/PKG-INFO
8
+ wavefunction.egg-info/SOURCES.txt
9
+ wavefunction.egg-info/dependency_links.txt
10
+ wavefunction.egg-info/requires.txt
11
+ wavefunction.egg-info/top_level.txt
@@ -0,0 +1,4 @@
1
+ numpy<1.27,>=1.25
2
+ scipy>=1.10
3
+ numba>=0.59
4
+ matplotlib
@@ -0,0 +1 @@
1
+ wavefunction