Upload fractus/nn/farey.py with huggingface_hub
Browse files- fractus/nn/farey.py +55 -0
fractus/nn/farey.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Farey sequence and phase selection for phase-routed MoE.
|
| 2 |
+
|
| 3 |
+
Ported from the original system (src/math/farey.rs).
|
| 4 |
+
|
| 5 |
+
The Farey sequence F_n is the ordered set of irreducible fractions p/q in
|
| 6 |
+
[0, 1] with q <= n. It is generated iteratively by the mediant property.
|
| 7 |
+
|
| 8 |
+
For the MoE: we take F_{2E} (order twice the number of experts) and select
|
| 9 |
+
E angles uniformly among the fractions, converted to angles 2π·p/q ∈ [0, 2π).
|
| 10 |
+
This yields a dense, non-collapsing, deterministic phase distribution —
|
| 11 |
+
useful for von Mises routing.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
import math
|
| 15 |
+
from typing import List, Tuple
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def farey_sequence(n: int) -> List[Tuple[int, int]]:
|
| 19 |
+
"""Generates the Farey sequence F_n as a list of (p, q) in ascending order.
|
| 20 |
+
|
| 21 |
+
Algorithm via the mediant (as in farey.rs:18-49).
|
| 22 |
+
F_n contains exactly 1 + Σ_{q=1}^{n} φ(q) terms (φ = Euler's totient).
|
| 23 |
+
"""
|
| 24 |
+
if n < 1:
|
| 25 |
+
raise ValueError("n must be >= 1")
|
| 26 |
+
fractions: List[Tuple[int, int]] = []
|
| 27 |
+
a, b = 0, 1
|
| 28 |
+
c, d = 1, n
|
| 29 |
+
fractions.append((a, b))
|
| 30 |
+
while c <= n:
|
| 31 |
+
k = (n + b) // d
|
| 32 |
+
next_c = k * c - a
|
| 33 |
+
next_d = k * d - b
|
| 34 |
+
a, b = c, d
|
| 35 |
+
c, d = next_c, next_d
|
| 36 |
+
fractions.append((a, b))
|
| 37 |
+
return fractions
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def expert_phases(n_experts: int) -> List[float]:
|
| 41 |
+
"""Selects n_experts angles ∈ [0, 2π) from F_{2·n_experts}.
|
| 42 |
+
|
| 43 |
+
As in farey.rs:53-64: we build F_{2E} (double order), then select
|
| 44 |
+
E angles uniformly from the n_frac = len(F_{2E}) available fractions.
|
| 45 |
+
"""
|
| 46 |
+
if n_experts < 1:
|
| 47 |
+
raise ValueError("n_experts must be >= 1")
|
| 48 |
+
fractions = farey_sequence(2 * n_experts)
|
| 49 |
+
n_frac = len(fractions)
|
| 50 |
+
angles_all = [2.0 * math.pi * p / q for (p, q) in fractions]
|
| 51 |
+
phases: List[float] = []
|
| 52 |
+
for i in range(n_experts):
|
| 53 |
+
idx = min(int(i * n_frac / n_experts), n_frac - 1)
|
| 54 |
+
phases.append(angles_all[idx])
|
| 55 |
+
return phases
|