mtft 0.3.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.
- mtft/__init__.py +44 -0
- mtft/arithmetic.py +234 -0
- mtft/burning_ship.py +202 -0
- mtft/constants.py +235 -0
- mtft/cosmology.py +214 -0
- mtft/dark_sector.py +172 -0
- mtft/decay.py +206 -0
- mtft/dimensional_bridge.py +194 -0
- mtft/forms.py +175 -0
- mtft/hosotani.py +158 -0
- mtft/info_geometry.py +188 -0
- mtft/koide.py +256 -0
- mtft/lattice.py +429 -0
- mtft/modular.py +194 -0
- mtft/particles.py +193 -0
- mtft/verify.py +270 -0
- mtft/viz.py +313 -0
- mtft/x0_143.py +321 -0
- mtft-0.3.0.dist-info/LICENSE +21 -0
- mtft-0.3.0.dist-info/METADATA +170 -0
- mtft-0.3.0.dist-info/RECORD +23 -0
- mtft-0.3.0.dist-info/WHEEL +5 -0
- mtft-0.3.0.dist-info/top_level.txt +1 -0
mtft/__init__.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MTFT — Modular Time Field Theory (v0.3.0)
|
|
3
|
+
============================================
|
|
4
|
+
|
|
5
|
+
16 modules covering the complete MTFT framework from arithmetic
|
|
6
|
+
weights through lattice gauge theory and experimental verification.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__version__ = "0.3.0"
|
|
10
|
+
|
|
11
|
+
# ── Tier 0: Constants & Arithmetic ───────────────────────────
|
|
12
|
+
from mtft.constants import (
|
|
13
|
+
SM, GAUGE, HIGGS, PDG, PhysicalConstants, CriticalDepths, MassRatios,
|
|
14
|
+
FEIGENBAUM_DELTA, FEIGENBAUM_ALPHA, T_INF, LAMBERT_OMEGA, EULER_GAMMA,
|
|
15
|
+
QUARKS, LEPTONS, ZETA_2, XI,
|
|
16
|
+
)
|
|
17
|
+
from mtft.arithmetic import (
|
|
18
|
+
weight, weight_array, damped_weights,
|
|
19
|
+
S1, stiffness_S, center_stiffness, mass_gap_stiffness,
|
|
20
|
+
su3_hessian_eigenvalues, find_confinement_depth,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# ── Tier 1: Modular Geometry & Forms ─────────────────────────
|
|
24
|
+
from mtft.modular import TauField, sl2z_transform
|
|
25
|
+
from mtft.forms import dedekind_eta, jacobi_theta3, eisenstein_E2k, verify_spectral_identity
|
|
26
|
+
|
|
27
|
+
# ── Tier 2: Gauge-Higgs ──────────────────────────────────────
|
|
28
|
+
from mtft.hosotani import HosotaniPotential
|
|
29
|
+
from mtft.particles import Particle, StandardModel
|
|
30
|
+
|
|
31
|
+
# ── Tier 3: Phenomenology ────────────────────────────────────
|
|
32
|
+
from mtft.dark_sector import TauVortexHalo, rotation_curve, tully_fisher
|
|
33
|
+
from mtft.info_geometry import fisher_rao_metric, ricci_scalar_logistic
|
|
34
|
+
from mtft.cosmology import FriedmannMTFT
|
|
35
|
+
|
|
36
|
+
# ── Tier 4: Lattice & Fermions ───────────────────────────────
|
|
37
|
+
from mtft.lattice import LatticeConfig, MTFTAction, metropolis_sweep, avg_plaquette, avg_polyakov
|
|
38
|
+
from mtft.x0_143 import tano_mass_predictions, koide_angle_tano, generation_count, JACOBIAN
|
|
39
|
+
from mtft.koide import koide_ratio, koide_leptons, predict_tau_mass, koide_manifold_point
|
|
40
|
+
from mtft.burning_ship import burning_ship_iterate, ANISOTROPIC
|
|
41
|
+
|
|
42
|
+
# ── Tier 5: Dimensional Bridge & Decay ───────────────────────
|
|
43
|
+
from mtft.dimensional_bridge import electron_mass_from_eta, charge_from_feigenbaum
|
|
44
|
+
from mtft.decay import ModularDecay
|
mtft/arithmetic.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MTFT Arithmetic Weights and Holonomy Stiffness
|
|
3
|
+
================================================
|
|
4
|
+
|
|
5
|
+
The arithmetic weights wₙ = Σ_{d|n} (log d)/d are the atoms of MTFT.
|
|
6
|
+
Their Dirichlet series satisfies W(s) = −ζ(s)ζ′(s+1).
|
|
7
|
+
|
|
8
|
+
Key series at modular depth y:
|
|
9
|
+
aₙ(y) = wₙ e^{−2πyn} (damped weights)
|
|
10
|
+
S₁(y) = Σ aₙ(y) (partition function / stiffness action)
|
|
11
|
+
S(y) = Σ n² aₙ(y) (holonomy stiffness)
|
|
12
|
+
C_N(y) = Σ n² aₙ(y) cos(2πn/N) (center-projected stiffness)
|
|
13
|
+
μ_N(y) = min_m Σ n² aₙ(y) (1 − cos(2πnm/N)) (mass gap)
|
|
14
|
+
|
|
15
|
+
The fine-structure constant is α⁻¹ = 2/S₁(y_spec).
|
|
16
|
+
The confinement lock is C_3(y_conf) = 0 (Hessian isotropy).
|
|
17
|
+
|
|
18
|
+
Reference: Papers 5, 7, 9, 13, 24; Dictionary IV–V.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import math
|
|
24
|
+
from functools import lru_cache
|
|
25
|
+
|
|
26
|
+
import numpy as np
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ── Arithmetic weight function ───────────────────────────────
|
|
30
|
+
|
|
31
|
+
def weight(n: int) -> float:
|
|
32
|
+
"""
|
|
33
|
+
Compute wₙ = Σ_{d|n} (log d)/d.
|
|
34
|
+
|
|
35
|
+
These are rigid number-theoretic objects — not fitted.
|
|
36
|
+
w₁ = 0, w₂ = (log 2)/2, w₃ = (log 3)/3, w₆ = w₂ + w₃ + (log 6)/6, ...
|
|
37
|
+
"""
|
|
38
|
+
if n < 1:
|
|
39
|
+
raise ValueError("n must be ≥ 1")
|
|
40
|
+
total = 0.0
|
|
41
|
+
for d in range(1, n + 1):
|
|
42
|
+
if n % d == 0:
|
|
43
|
+
if d > 1:
|
|
44
|
+
total += math.log(d) / d
|
|
45
|
+
return total
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@lru_cache(maxsize=8192)
|
|
49
|
+
def _weight_cached(n: int) -> float:
|
|
50
|
+
return weight(n)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def weight_array(n_max: int) -> np.ndarray:
|
|
54
|
+
"""Compute wₙ for n = 1, ..., n_max as a NumPy array."""
|
|
55
|
+
return np.array([_weight_cached(n) for n in range(1, n_max + 1)])
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# ── Euler-shifted weights (Paper 20) ─────────────────────────
|
|
59
|
+
|
|
60
|
+
def weight_euler(n: int) -> float:
|
|
61
|
+
"""
|
|
62
|
+
Euler-shifted weight: w_n^(e) = w_n + σ_{-1}(n).
|
|
63
|
+
|
|
64
|
+
The substitution log k → log(ek) activates w₁ = 0 → w₁^(e) = 1,
|
|
65
|
+
creating the electron as the vacuum's first excitation.
|
|
66
|
+
"""
|
|
67
|
+
sigma_minus1 = sum(1.0 / d for d in range(1, n + 1) if n % d == 0)
|
|
68
|
+
return weight(n) + sigma_minus1
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# ── Damped coefficients ──────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
def damped_weight(n: int, y: float) -> float:
|
|
74
|
+
"""aₙ(y) = wₙ exp(−2πyn)."""
|
|
75
|
+
return _weight_cached(n) * math.exp(-2.0 * math.pi * y * n)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def damped_weights(y: float, n_max: int = 500) -> np.ndarray:
|
|
79
|
+
"""Array of aₙ(y) for n = 1..n_max."""
|
|
80
|
+
ns = np.arange(1, n_max + 1)
|
|
81
|
+
ws = weight_array(n_max)
|
|
82
|
+
return ws * np.exp(-2.0 * math.pi * y * ns)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# ── Stiffness series ─────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
def S1(y: float, n_max: int = 500) -> float:
|
|
88
|
+
"""
|
|
89
|
+
Partition function / stiffness action:
|
|
90
|
+
S₁(y) = Σ wₙ e^{−2πyn}
|
|
91
|
+
|
|
92
|
+
The fine-structure constant is α⁻¹ = 2/S₁(y_spec).
|
|
93
|
+
"""
|
|
94
|
+
return float(np.sum(damped_weights(y, n_max)))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def stiffness_S(y: float, n_max: int = 500) -> float:
|
|
98
|
+
"""
|
|
99
|
+
Holonomy stiffness:
|
|
100
|
+
S(y) = Σ n² wₙ e^{−2πyn}
|
|
101
|
+
"""
|
|
102
|
+
ns = np.arange(1, n_max + 1)
|
|
103
|
+
ws = weight_array(n_max)
|
|
104
|
+
return float(np.sum(ns**2 * ws * np.exp(-2 * math.pi * y * ns)))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def center_stiffness(y: float, N: int = 3, n_max: int = 500) -> float:
|
|
108
|
+
"""
|
|
109
|
+
Z_N center-projected stiffness:
|
|
110
|
+
C_N(y) = Σ n² wₙ e^{−2πyn} cos(2πn/N)
|
|
111
|
+
|
|
112
|
+
C_3(y_conf) = 0 is the confinement lock.
|
|
113
|
+
"""
|
|
114
|
+
ns = np.arange(1, n_max + 1)
|
|
115
|
+
ws = weight_array(n_max)
|
|
116
|
+
cos_terms = np.cos(2.0 * math.pi * ns / N)
|
|
117
|
+
return float(np.sum(ns**2 * ws * np.exp(-2 * math.pi * y * ns) * cos_terms))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def mass_gap_stiffness(y: float, N: int = 3, n_max: int = 500) -> float:
|
|
121
|
+
"""
|
|
122
|
+
SU(N) mass gap stiffness (minimum over modes m):
|
|
123
|
+
μ_N(y) = min_{m=1..N-1} Σ n² wₙ e^{−2πyn} (1 − cos(2πnm/N))
|
|
124
|
+
|
|
125
|
+
Theorem: μ_N(y) > 0 unconditionally for all N≥2, y>0.
|
|
126
|
+
"""
|
|
127
|
+
ns = np.arange(1, n_max + 1)
|
|
128
|
+
ws = weight_array(n_max)
|
|
129
|
+
damped = ns**2 * ws * np.exp(-2 * math.pi * y * ns)
|
|
130
|
+
|
|
131
|
+
mu_min = float("inf")
|
|
132
|
+
for m in range(1, N):
|
|
133
|
+
gap_terms = 1.0 - np.cos(2 * math.pi * ns * m / N)
|
|
134
|
+
mu_m = float(np.sum(damped * gap_terms))
|
|
135
|
+
mu_min = min(mu_min, mu_m)
|
|
136
|
+
return mu_min
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# ── SU(3) Hessian eigenvalues (Paper 5 §24.4, Bridge §4.3) ──
|
|
140
|
+
|
|
141
|
+
def su3_hessian_eigenvalues(y: float, n_max: int = 500) -> tuple[float, float]:
|
|
142
|
+
"""
|
|
143
|
+
SU(3) holonomy Hessian eigenvalues:
|
|
144
|
+
λ₁ = (S_N + 2C_N) / 3
|
|
145
|
+
λ₂ = (S_N − C_N) / 3
|
|
146
|
+
|
|
147
|
+
At y_conf ≈ 0.18174: λ₁/λ₂ = 1.000001 (the spectral lock).
|
|
148
|
+
"""
|
|
149
|
+
S = stiffness_S(y, n_max)
|
|
150
|
+
C = center_stiffness(y, N=3, n_max=n_max)
|
|
151
|
+
lam1 = (S + 2 * C) / 3.0
|
|
152
|
+
lam2 = (S - C) / 3.0
|
|
153
|
+
return lam1, lam2
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def find_confinement_depth(
|
|
157
|
+
y_min: float = 0.10, y_max: float = 0.25, tol: float = 1e-8, n_max: int = 500
|
|
158
|
+
) -> float:
|
|
159
|
+
"""
|
|
160
|
+
Find y_conf where C_3(y) = 0 (SU(3) Hessian isotropy).
|
|
161
|
+
|
|
162
|
+
Uses bisection on C_3(y).
|
|
163
|
+
"""
|
|
164
|
+
# C_3 starts positive and crosses zero
|
|
165
|
+
c_lo = center_stiffness(y_min, N=3, n_max=n_max)
|
|
166
|
+
c_hi = center_stiffness(y_max, N=3, n_max=n_max)
|
|
167
|
+
|
|
168
|
+
if c_lo * c_hi > 0:
|
|
169
|
+
# Try a wider scan
|
|
170
|
+
for y_test in np.linspace(y_min, y_max, 200):
|
|
171
|
+
c_test = center_stiffness(y_test, N=3, n_max=n_max)
|
|
172
|
+
if c_test * c_lo < 0:
|
|
173
|
+
y_max = y_test
|
|
174
|
+
c_hi = c_test
|
|
175
|
+
break
|
|
176
|
+
|
|
177
|
+
lo, hi = y_min, y_max
|
|
178
|
+
for _ in range(100):
|
|
179
|
+
mid = (lo + hi) / 2.0
|
|
180
|
+
c_mid = center_stiffness(mid, N=3, n_max=n_max)
|
|
181
|
+
if abs(c_mid) < tol:
|
|
182
|
+
return mid
|
|
183
|
+
if c_mid * c_lo > 0:
|
|
184
|
+
lo = mid
|
|
185
|
+
c_lo = c_mid
|
|
186
|
+
else:
|
|
187
|
+
hi = mid
|
|
188
|
+
return (lo + hi) / 2.0
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# ── Lambert series ───────────────────────────────────────────
|
|
192
|
+
|
|
193
|
+
def lambert_series(q: complex, n_max: int = 200) -> complex:
|
|
194
|
+
"""
|
|
195
|
+
MTFT Lambert series: W(q) = Σ_{d≥1} (log d)/d · q^d/(1−q^d).
|
|
196
|
+
|
|
197
|
+
This is the q-series feeding the modular holonomy potential.
|
|
198
|
+
"""
|
|
199
|
+
total = 0.0 + 0j
|
|
200
|
+
for d in range(2, n_max + 1):
|
|
201
|
+
qd = q ** d
|
|
202
|
+
if abs(1.0 - qd) < 1e-30:
|
|
203
|
+
continue
|
|
204
|
+
total += (math.log(d) / d) * qd / (1.0 - qd)
|
|
205
|
+
return total
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# ── Torque flux convergence (Paper 7, §9) ────────────────────
|
|
209
|
+
|
|
210
|
+
def torque_partial_sum(N: int) -> float:
|
|
211
|
+
"""
|
|
212
|
+
Partial sum of the normalised torque: (1/N²) Σ_{n=1}^{N} n·wₙ.
|
|
213
|
+
|
|
214
|
+
Converges to T∞ = −ζ′(2)/2 ≈ 0.4688.
|
|
215
|
+
"""
|
|
216
|
+
total = 0.0
|
|
217
|
+
for n in range(1, N + 1):
|
|
218
|
+
total += n * _weight_cached(n)
|
|
219
|
+
return total / (N ** 2)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# ── Dirichlet series identity check ──────────────────────────
|
|
223
|
+
|
|
224
|
+
def dirichlet_F(s: complex, n_max: int = 500) -> complex:
|
|
225
|
+
"""
|
|
226
|
+
Compute F(s) = Σ f(n)/n^s where f = σ * Λ.
|
|
227
|
+
|
|
228
|
+
Should equal −ζ(s−1)ζ′(s) (the master Dirichlet identity).
|
|
229
|
+
"""
|
|
230
|
+
total = 0.0 + 0j
|
|
231
|
+
for n in range(1, n_max + 1):
|
|
232
|
+
f_n = sum(math.log(d) for d in range(1, n + 1) if n % d == 0)
|
|
233
|
+
total += f_n / n ** s
|
|
234
|
+
return total
|
mtft/burning_ship.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Burning Ship Fractal: The Fermion Vacuum
|
|
3
|
+
=========================================
|
|
4
|
+
|
|
5
|
+
The Burning Ship iteration:
|
|
6
|
+
z_{n+1} = (|Re(z_n)| + i|Im(z_n)|)² + c
|
|
7
|
+
|
|
8
|
+
Unlike the Mandelbrot z² + c (analytic), the absolute values create
|
|
9
|
+
fold lines where the map is non-analytic. This governs the fermion
|
|
10
|
+
sector of MTFT:
|
|
11
|
+
|
|
12
|
+
Mandelbrot (analytic) → gauge sector → Yang-Mills mass gap
|
|
13
|
+
Burning Ship (non-analytic) → fermion sector → Koide formula
|
|
14
|
+
|
|
15
|
+
Phase space has four sectors from sgn(x), sgn(y):
|
|
16
|
+
S₊₊, S₋₊, S₊₋, S₋₋
|
|
17
|
+
|
|
18
|
+
with Jacobian:
|
|
19
|
+
J = [[2x, −2y], [2 sgn(x)sgn(y)|y|, 2 sgn(x)sgn(y)|x|]]
|
|
20
|
+
det(J) = 4|z|² (continuous)
|
|
21
|
+
tr(J) = 2x + 2 sgn(x)sgn(y)|x| (discontinuous at x=0)
|
|
22
|
+
|
|
23
|
+
Anisotropic Feigenbaum constants:
|
|
24
|
+
δₓ ≈ 7.30 (attractor fold, quark direction)
|
|
25
|
+
δᵧ ≈ 3.38 (barrier fold, lepton direction)
|
|
26
|
+
β_x = +0.29, β_y = −0.21, |β_x| + |β_y| = 1/2
|
|
27
|
+
|
|
28
|
+
Reference: Paper 4, Paper 6, Chapter 10–11.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import math
|
|
34
|
+
from dataclasses import dataclass
|
|
35
|
+
|
|
36
|
+
import numpy as np
|
|
37
|
+
|
|
38
|
+
from mtft.constants import FEIGENBAUM_DELTA, DELTA_X, DELTA_Y, BETA_X, BETA_Y
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# ═══════════════════════════════════════════════════════════════
|
|
42
|
+
# Burning Ship Iteration
|
|
43
|
+
# ═══════════════════════════════════════════════════════════════
|
|
44
|
+
|
|
45
|
+
def burning_ship_iterate(c: complex, max_iter: int = 200, escape: float = 100.0) -> int:
|
|
46
|
+
"""
|
|
47
|
+
Iterate z_{n+1} = (|Re z| + i|Im z|)² + c.
|
|
48
|
+
|
|
49
|
+
Returns escape time (max_iter if bounded).
|
|
50
|
+
"""
|
|
51
|
+
z = 0.0 + 0.0j
|
|
52
|
+
for n in range(max_iter):
|
|
53
|
+
x, y = abs(z.real), abs(z.imag)
|
|
54
|
+
z = complex(x, y) ** 2 + c
|
|
55
|
+
if abs(z) > escape:
|
|
56
|
+
return n
|
|
57
|
+
return max_iter
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def burning_ship_array(
|
|
61
|
+
re_range: tuple = (-2.5, 1.5),
|
|
62
|
+
im_range: tuple = (-2.0, 1.0),
|
|
63
|
+
resolution: int = 500,
|
|
64
|
+
max_iter: int = 200,
|
|
65
|
+
) -> np.ndarray:
|
|
66
|
+
"""
|
|
67
|
+
Compute escape-time array for the Burning Ship fractal.
|
|
68
|
+
|
|
69
|
+
Returns (resolution × resolution) integer array.
|
|
70
|
+
"""
|
|
71
|
+
re = np.linspace(re_range[0], re_range[1], resolution)
|
|
72
|
+
im = np.linspace(im_range[0], im_range[1], resolution)
|
|
73
|
+
result = np.zeros((resolution, resolution), dtype=int)
|
|
74
|
+
for i, y in enumerate(im):
|
|
75
|
+
for j, x in enumerate(re):
|
|
76
|
+
result[i, j] = burning_ship_iterate(complex(x, y), max_iter)
|
|
77
|
+
return result
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# ═══════════════════════════════════════════════════════════════
|
|
81
|
+
# Phase Space Sectors and Jacobian
|
|
82
|
+
# ═══════════════════════════════════════════════════════════════
|
|
83
|
+
|
|
84
|
+
def sector(z: complex) -> str:
|
|
85
|
+
"""Identify the phase-space sector of z."""
|
|
86
|
+
sx = "+" if z.real >= 0 else "-"
|
|
87
|
+
sy = "+" if z.imag >= 0 else "-"
|
|
88
|
+
return f"S_{sx}{sy}"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def jacobian(z: complex) -> np.ndarray:
|
|
92
|
+
"""
|
|
93
|
+
Jacobian of the Burning Ship map at z = x + iy:
|
|
94
|
+
|
|
95
|
+
J = [[2x, −2y],
|
|
96
|
+
[2 sgn(x)sgn(y)|y|, 2 sgn(x)sgn(y)|x|]]
|
|
97
|
+
|
|
98
|
+
det(J) = 4|z|² (continuous across folds)
|
|
99
|
+
tr(J) = 2x + 2 sgn(x)sgn(y)|x| (discontinuous at x=0)
|
|
100
|
+
"""
|
|
101
|
+
x, y = z.real, z.imag
|
|
102
|
+
sx = 1.0 if x >= 0 else -1.0
|
|
103
|
+
sy = 1.0 if y >= 0 else -1.0
|
|
104
|
+
return np.array([
|
|
105
|
+
[2 * x, -2 * y],
|
|
106
|
+
[2 * sx * sy * abs(y), 2 * sx * sy * abs(x)],
|
|
107
|
+
])
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def jacobian_determinant(z: complex) -> float:
|
|
111
|
+
"""det(J) = 4|z|² — continuous across all folds."""
|
|
112
|
+
return 4.0 * abs(z) ** 2
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def jacobian_trace(z: complex) -> float:
|
|
116
|
+
"""tr(J) = 2x + 2 sgn(x)sgn(y)|x| — discontinuous at x=0."""
|
|
117
|
+
x, y = z.real, z.imag
|
|
118
|
+
sx = 1.0 if x >= 0 else -1.0
|
|
119
|
+
sy = 1.0 if y >= 0 else -1.0
|
|
120
|
+
return 2.0 * x + 2.0 * sx * sy * abs(x)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# ═══════════════════════════════════════════════════════════════
|
|
124
|
+
# Anisotropic Feigenbaum Constants
|
|
125
|
+
# ═══════════════════════════════════════════════════════════════
|
|
126
|
+
|
|
127
|
+
@dataclass(frozen=True)
|
|
128
|
+
class AnisotropicScaling:
|
|
129
|
+
"""
|
|
130
|
+
Anisotropic universality of the Burning Ship (Paper 4).
|
|
131
|
+
|
|
132
|
+
The standard Feigenbaum δ splits into direction-dependent constants:
|
|
133
|
+
δₓ ≈ δ^1.29 ≈ 7.30 (attractor fold / quark direction)
|
|
134
|
+
δᵧ ≈ δ^0.79 ≈ 3.38 (barrier fold / lepton direction)
|
|
135
|
+
|
|
136
|
+
Fold approach exponents:
|
|
137
|
+
β_x = +0.29 (attractor approach rate)
|
|
138
|
+
β_y = −0.21 (barrier approach rate)
|
|
139
|
+
|β_x| + |β_y| = 1/2 (fold budget constraint)
|
|
140
|
+
|
|
141
|
+
Power laws:
|
|
142
|
+
δ ∝ ρ_x^{+0.29} (x-fold)
|
|
143
|
+
δ ∝ ρ_y^{−0.21} (y-fold)
|
|
144
|
+
"""
|
|
145
|
+
delta: float = FEIGENBAUM_DELTA
|
|
146
|
+
delta_x: float = DELTA_X
|
|
147
|
+
delta_y: float = DELTA_Y
|
|
148
|
+
beta_x: float = BETA_X
|
|
149
|
+
beta_y: float = BETA_Y
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def fold_budget(self) -> float:
|
|
153
|
+
"""Should be ≈ 0.5."""
|
|
154
|
+
return abs(self.beta_x) + abs(self.beta_y)
|
|
155
|
+
|
|
156
|
+
def generation_mass_ratio(self, direction: str = "lepton") -> float:
|
|
157
|
+
"""
|
|
158
|
+
Mass ratio between adjacent generations:
|
|
159
|
+
m_{n+1}/m_n ~ δ_eff²
|
|
160
|
+
|
|
161
|
+
For leptons: δ_y² ≈ 11.4
|
|
162
|
+
For quarks: δ_x² ≈ 53.3
|
|
163
|
+
"""
|
|
164
|
+
d = self.delta_y if direction == "lepton" else self.delta_x
|
|
165
|
+
return d ** 2
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
ANISOTROPIC = AnisotropicScaling()
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# ═══════════════════════════════════════════════════════════════
|
|
172
|
+
# Fold Proximity Data (Paper 4, Table 2)
|
|
173
|
+
# ═══════════════════════════════════════════════════════════════
|
|
174
|
+
|
|
175
|
+
FOLD_PROXIMITY = {
|
|
176
|
+
# period: (min_|x|, min_|y|, x_crossings, y_crossings)
|
|
177
|
+
3: (2.51e-1, 4.31e-1, 0, 0),
|
|
178
|
+
6: (4.37e-2, 1.32e-1, 3, 0),
|
|
179
|
+
12: (2.82e-2, 4.72e-2, 3, 0),
|
|
180
|
+
24: (2.22e-2, 8.35e-4, 7, 4),
|
|
181
|
+
48: (7.02e-3, 1.92e-3, 15, 4),
|
|
182
|
+
384: (9.02e-4, 2.60e-6, 255, 128),
|
|
183
|
+
768: (1.11e-5, 3.70e-6, 511, 255),
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# ═══════════════════════════════════════════════════════════════
|
|
188
|
+
# Three Generations from Self-Similar Satellites (Paper 6 §5)
|
|
189
|
+
# ═══════════════════════════════════════════════════════════════
|
|
190
|
+
|
|
191
|
+
def satellite_mass_scale(n: int, delta_eff: float = None) -> float:
|
|
192
|
+
"""
|
|
193
|
+
Mass scale of the n-th generation satellite relative to 1st:
|
|
194
|
+
|
|
195
|
+
m_n / m_1 ~ δ_eff^{−2(n−1)}
|
|
196
|
+
|
|
197
|
+
Higher-order satellites (n ≥ 4) fall below the EW scale
|
|
198
|
+
and are not realised as stable particles.
|
|
199
|
+
"""
|
|
200
|
+
if delta_eff is None:
|
|
201
|
+
delta_eff = DELTA_Y
|
|
202
|
+
return delta_eff ** (-2 * (n - 1))
|