mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
The experiment: use the Φ-corkscrew system to search its own manifold
for the direction that maximizes compression ratio. 5 domain experts
designed their components in parallel.
EXPERIMENT: EXPERIMENT_RADIAL_SELF_FIND.md
- Hypothesis: ∃ d* on S⁷: walking γ_{d*} monotonically increases C(n)
- Method: Self-referential geodesic search with radial exploration
- Predictions: gradient exists, ascent converges, self-encoding helps
AGENT 1 — GeometricPhysicist: experiment_geodesic_search.md
- Geodesic: γ_d(t) = cos(t)·x + sin(t)·d (great circles on S⁷)
- Gradient ascent: exponential map + parallel transport
- Direction sampling: uniform, Φ-guided, gradient-biased
- 3 core functions: geodesic_search, gradient_ascent_step, sample_directions
AGENT 2 — InformationTheorist: experiment_compression_metric.md
- C(n) = L_S / |RLE(DNA(phinary(n)))|
- Bounds: Ω(L_S/log n) ≤ C(n) ≤ O(L_S/log log n)
- Key insight: phinary constraint inherently favors compressibility
- Entropy H(n), Kolmogorov K(n), spectral radius analysis
AGENT 3 — SystemsEngineer: experiment_feedback_loop.md (2,033 lines!)
- 12-state, 15-transition state machine
- 3-layer strange loop containment (bounded, contractive, depth cap)
- Radial exploration: OUTWARD/INWARD/OSCILLATE modes
- Full FAMM-DAG integration with meltdown recovery
- 7 convergence criteria
AGENT 4 — FormalVerifier: experiment_formal_verification.md
- 8 Lean 4 theorems + master theorem
- Key: Bijection Preservation (search transform preserves injectivity)
- Paradox Prevention theorem (self-referential safety)
- 10 invariants, 5 verification conditions
- Integrates with ChentsovFinite.lean, quine.py proofs
AGENT 5 — MetaMathematician: experiment_meta_analysis.md
- Strange loop converges (C(n) is Lyapunov function, S⁷ compact)
- Fixed points exist (Brouwer + Kleene recursion theorem)
- Gödel boundary is epistemological, not ontological
- System finds itself but cannot prove global optimality
- 12 formal theorems
Total: 6 files, ~6,000 lines of experiment design
Refs: PHI_CORKSCREW_PERFECT_RECOVERY.md, PROOF_SELFSIGHT.md,
ChentsovFinite.lean, GoldenSpiralManifold.lean
980 lines
28 KiB
Markdown
980 lines
28 KiB
Markdown
# GEODESIC SEARCH on S^7 — Algorithm Specification
|
||
|
||
## Component: Radial Self-Finding Experiment — Geodesic Search Engine
|
||
|
||
**Author**: Geometric Physicist (Information Geometry)
|
||
**Status**: DESIGN_PHASE
|
||
**Dependencies**: `EXPERIMENT_RADIAL_SELF_FIND.md`
|
||
|
||
---
|
||
|
||
## 1. Mathematical Preliminaries
|
||
|
||
### 1.1 The Manifold: S^7 (Fisher Sphere)
|
||
|
||
The state space is the 7-sphere embedded in R^8:
|
||
|
||
```
|
||
S^7 = {x ∈ R^8 : ||x||² = 1, x_i ≥ 0}
|
||
```
|
||
|
||
In √p-coordinates, each point x corresponds to a probability distribution
|
||
p ∈ Δ_7 (the 7-simplex) via:
|
||
|
||
```
|
||
x = (√p_1, √p_2, ..., √p_8), where Σ_i p_i = 1, p_i ≥ 0
|
||
```
|
||
|
||
The **Fisher-Rao metric** on Δ_7:
|
||
|
||
```
|
||
g_ij = δ_ij / p_i + 1/p_8 (for i,j = 1,...,7)
|
||
```
|
||
|
||
In √p-coordinates, this becomes the **round metric** on S^7 (the metric
|
||
induced from the Euclidean metric on R^8). This is the Chentsov theorem:
|
||
the Fisher-Rao metric on the simplex is isometric to the round sphere.
|
||
|
||
### 1.2 Tangent Space
|
||
|
||
At a point x ∈ S^7, the tangent space is:
|
||
|
||
```
|
||
T_x S^7 = {v ∈ R^8 : ⟨v, x⟩ = 0}
|
||
```
|
||
|
||
A **direction** d at x is a unit vector in T_x S^7:
|
||
|
||
```
|
||
d ∈ T_x S^7, ||d|| = 1
|
||
```
|
||
|
||
The set of all directions at x forms a 6-sphere S^6 ⊂ T_x S^7.
|
||
|
||
**Projection to tangent space** (for any vector v ∈ R^8):
|
||
|
||
```
|
||
Proj_{T_x}(v) = v - ⟨v, x⟩ · x
|
||
```
|
||
|
||
### 1.3 Geodesics on S^7
|
||
|
||
Geodesics on the round sphere are **great circles**. The geodesic
|
||
starting at x in direction d with arc-length parameter t is:
|
||
|
||
```
|
||
γ_d(t) = cos(t) · x + sin(t) · d (G1)
|
||
```
|
||
|
||
**Properties:**
|
||
- γ_d(0) = x
|
||
- γ_d'(0) = d
|
||
- ||γ_d(t)|| = 1 for all t (stays on S^7)
|
||
- Arc-length parameter: ||γ_d'(t)|| = 1
|
||
|
||
**Range restriction**: Since x_i ≥ 0 (probability simplex), geodesics
|
||
may leave the valid region. The maximal valid step is:
|
||
|
||
```
|
||
t_max(d) = min_i { arctan(-x_i / d_i) : d_i < 0 } (G2)
|
||
```
|
||
|
||
If all d_i ≥ 0, then t_max = +∞ (stays in positive orthant).
|
||
|
||
### 1.4 Exponential Map
|
||
|
||
The exponential map at x ∈ S^7 is the geodesic flow:
|
||
|
||
```
|
||
exp_x(v) = cos(||v||) · x + sin(||v||) · (v / ||v||) (EM)
|
||
```
|
||
|
||
for v ∈ T_x S^7, v ≠ 0. For v = 0, exp_x(0) = x.
|
||
|
||
**Inverse (logarithm map)**: For y ∈ S^7 not antipodal to x:
|
||
|
||
```
|
||
log_x(y) = arccos(⟨x, y⟩) · (y - ⟨x, y⟩ x) / ||y - ⟨x, y⟩ x|| (LM)
|
||
```
|
||
|
||
### 1.5 Parallel Transport
|
||
|
||
To transport a tangent vector v ∈ T_x S^7 along the geodesic from x to
|
||
y = γ_d(t), use the standard formula for parallel transport on the sphere:
|
||
|
||
```
|
||
P_{x→y}(v) = v - (⟨v, y⟩ / (1 + ⟨x, y⟩)) · (x + y) (PT)
|
||
```
|
||
|
||
**Properties:**
|
||
- P_{x→y}(v) ∈ T_y S^7 (remains tangent)
|
||
- Isometric: ||P_{x→y}(v)|| = ||v||
|
||
- Inner-product preserving: ⟨P(v), P(w)⟩ = ⟨v, w⟩
|
||
|
||
---
|
||
|
||
## 2. Direction Representation
|
||
|
||
### 2.1 Defining a Direction
|
||
|
||
A direction d at point S_0 ∈ S^7 is represented as:
|
||
|
||
```
|
||
struct Direction {
|
||
d: R^8, // unit vector
|
||
constraints: {
|
||
⟨d, S_0⟩ = 0, // tangent to S^7
|
||
||d|| = 1, // unit length
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.2 Creating a Direction from an Arbitrary Vector
|
||
|
||
Given v ∈ R^8, construct a valid direction at S_0:
|
||
|
||
```
|
||
function make_direction(S_0: S^7, v: R^8) → Direction:
|
||
v_tangent = v - ⟨v, S_0⟩ · S_0 // Project to T_{S_0} S^7
|
||
if ||v_tangent|| < ε:
|
||
return null // v is parallel to S_0, no valid direction
|
||
d = v_tangent / ||v_tangent|| // Normalize
|
||
return Direction{d}
|
||
```
|
||
|
||
### 2.3 Direction ↔ Spiral Correspondence
|
||
|
||
Each direction d corresponds to a family of probability distributions
|
||
along the geodesic. The spiral index function maps these back to N:
|
||
|
||
```
|
||
n(d, t) = spiral_index(γ_d(t)) = argmin_n ||f(n) - γ_d(t)||²
|
||
```
|
||
|
||
where f(n) = (√n · cos(nψ), √n · sin(nψ)) is the Φ-corkscrew.
|
||
|
||
The **compression ratio** along direction d is:
|
||
|
||
```
|
||
C(d, t) = compression_ratio(n(d, t))
|
||
= original_size / |RLE(phinary(n(d, t)))|
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Core Algorithm: `geodesic_search`
|
||
|
||
### 3.1 Pseudocode
|
||
|
||
```
|
||
function geodesic_search(
|
||
S_0: S^7, // Starting point on Fisher sphere
|
||
N_directions: int, // Number of directions to explore
|
||
T_steps: int, // Number of steps along each geodesic
|
||
t_max: float = π/2, // Maximum geodesic distance
|
||
step_pattern: str = "geometric" // "uniform", "geometric", "adaptive"
|
||
) → (d*, t*, S*, C*):
|
||
|
||
// ---- Step 1: Sample directions ----
|
||
D = sample_directions(S_0, N_directions)
|
||
|
||
// ---- Step 2: Define step sizes ----
|
||
if step_pattern == "uniform":
|
||
T = linspace(0, t_max, T_steps)
|
||
elif step_pattern == "geometric":
|
||
T = t_max * (1 - exp(-3 * linspace(0, 1, T_steps))) / (1 - e^{-3})
|
||
elif step_pattern == "adaptive":
|
||
T = golden_section_steps(0, t_max, T_steps)
|
||
|
||
// ---- Step 3: Evaluate all (direction, step) pairs ----
|
||
best_C = -∞
|
||
best_triple = null
|
||
|
||
for i = 1 to N_directions:
|
||
d_i = D[i]
|
||
|
||
// Compute t_max for this direction (boundary of simplex)
|
||
t_boundary = compute_boundary_limit(S_0, d_i)
|
||
T_eff = T ∩ [0, t_boundary] // Clip to valid range
|
||
|
||
for j = 1 to |T_eff|:
|
||
t_j = T_eff[j]
|
||
S_ij = γ_{d_i}(t_j) = cos(t_j)·S_0 + sin(t_j)·d_i // (G1)
|
||
|
||
// Map to probability simplex
|
||
p_ij = S_ij ⊙ S_ij // element-wise square: p_k = (S_ij,k)²
|
||
p_ij = p_ij / Σ_k p_ij,k // renormalize (numerical safety)
|
||
|
||
// Encode and measure compression
|
||
n_ij = spiral_index(S_ij)
|
||
C_ij = compression_ratio(n_ij)
|
||
|
||
// Update best
|
||
if C_ij > best_C:
|
||
best_C = C_ij
|
||
best_triple = (d_i, t_j, S_ij, C_ij)
|
||
|
||
// ---- Step 4: Return best ----
|
||
(d*, t*, S*, C*) = best_triple
|
||
return (d*, t*, S*, C*)
|
||
```
|
||
|
||
### 3.2 Step Size Patterns
|
||
|
||
**Uniform**: `t_j = j · t_max / T_steps`
|
||
Good for: Initial broad exploration.
|
||
|
||
**Geometric** (default): `t_j = t_max · (1 - e^{-3j/T_steps}) / (1 - e^{-3})`
|
||
Good for: More samples near S_0 where changes are smaller.
|
||
|
||
**Adaptive (Golden Section)**: Uses golden-ratio spacing to concentrate
|
||
samples where compression changes most rapidly.
|
||
|
||
### 3.3 Boundary Computation
|
||
|
||
```
|
||
function compute_boundary_limit(S_0: S^7, d: Direction) → float:
|
||
"""
|
||
Compute the maximum geodesic distance before leaving
|
||
the positive orthant (p_i ≥ 0 for all i).
|
||
"""
|
||
t_max_valid = +∞
|
||
for i = 1 to 8:
|
||
if d_i < 0 and S_0,i > 0:
|
||
// Solve: cos(t)·S_0,i + sin(t)·d_i = 0
|
||
// => tan(t) = -S_0,i / d_i
|
||
t_i = arctan(-S_0,i / d_i)
|
||
if t_i > 0:
|
||
t_max_valid = min(t_max_valid, t_i)
|
||
return t_max_valid
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Gradient Computation: `compute_gradient`
|
||
|
||
### 4.1 Problem Statement
|
||
|
||
We need the Riemannian gradient of the compression ratio C with respect
|
||
to position on S^7. Since C is evaluated through the discrete
|
||
`spiral_index` function (argmin), it is piecewise constant with
|
||
jumps at boundaries. We use **finite differences on the sphere**.
|
||
|
||
### 4.2 Finite Difference Gradient
|
||
|
||
```
|
||
function compute_gradient(
|
||
S: S^7, // Current point
|
||
f: S^7 → R, // Objective function (here: f(x) = C(spiral_index(x)))
|
||
ε: float = 1e-4, // Finite difference step
|
||
method: str = "central" // "forward", "central", "complex"
|
||
) → ∇f ∈ T_S S^7:
|
||
|
||
// Build orthonormal basis for T_S S^7
|
||
B = build_tangent_basis(S) // Returns {e_1, ..., e_7} ⊂ R^8
|
||
|
||
// Compute directional derivatives
|
||
∇f = 0 ∈ R^8
|
||
for k = 1 to 7:
|
||
e_k = B[k]
|
||
|
||
if method == "central":
|
||
S_plus = exp_S(ε · e_k) = cos(ε)·S + sin(ε)·e_k
|
||
S_minus = exp_S(-ε · e_k) = cos(ε)·S - sin(ε)·e_k
|
||
∂f/∂e_k = (f(S_plus) - f(S_minus)) / (2ε)
|
||
|
||
elif method == "forward":
|
||
S_plus = exp_S(ε · e_k)
|
||
∂f/∂e_k = (f(S_plus) - f(S)) / ε
|
||
|
||
∇f += (∂f/∂e_k) · e_k
|
||
|
||
return ∇f // Lives in T_S S^7 by construction
|
||
```
|
||
|
||
### 4.3 Tangent Basis Construction (Gram-Schmidt)
|
||
|
||
```
|
||
function build_tangent_basis(S: S^7) → List[R^8]:
|
||
"""
|
||
Build orthonormal basis for T_S S^7 using modified Gram-Schmidt.
|
||
"""
|
||
basis = []
|
||
for i = 1 to 8:
|
||
e = standard_basis_vector(i) // (0,...,1,...,0)
|
||
|
||
// Project to tangent space
|
||
e = e - ⟨e, S⟩ · S
|
||
|
||
// Orthogonalize against existing basis vectors
|
||
for b in basis:
|
||
e = e - ⟨e, b⟩ · b
|
||
|
||
// Normalize (skip if numerically zero)
|
||
if ||e|| > ε_machine:
|
||
e = e / ||e||
|
||
basis.append(e)
|
||
|
||
// Verify: should have exactly 7 basis vectors
|
||
assert len(basis) == 7
|
||
return basis
|
||
```
|
||
|
||
### 4.4 Gradient via Automatic Differentiation (Alternative)
|
||
|
||
If the spiral_index function is differentiable (e.g., using a smooth
|
||
relaxation), we can use automatic differentiation:
|
||
|
||
```
|
||
// Smooth relaxation of spiral_index:
|
||
// Instead of argmin, use soft-argmin:
|
||
n_smooth(x) = Σ_n n · softmax(-β·||f(n) - x||²)_n
|
||
|
||
// Where β > 0 is an inverse temperature parameter.
|
||
// As β → ∞, n_smooth → argmin.
|
||
// Typical values: β ∈ [10, 1000]
|
||
|
||
// Chain rule:
|
||
∇_x C = (∂C/∂n) · (∂n_smooth/∂x)
|
||
|
||
// Project to tangent space:
|
||
∇_S C = Proj_{T_S}(∇_x C)
|
||
```
|
||
|
||
### 4.5 Gradient with Respect to Direction
|
||
|
||
When optimizing over directions d ∈ S^6 (the direction sphere at S_0):
|
||
|
||
```
|
||
function compute_direction_gradient(
|
||
S_0: S^7, // Fixed starting point
|
||
d: Direction, // Current direction
|
||
f: S^7 → R, // f(x) = C(spiral_index(x))
|
||
ε: float = 1e-4
|
||
) → ∇_d F ∈ T_d S^6:
|
||
|
||
// Define F(d) = max_t f(γ_d(t)) [or f(γ_d(t*)) for fixed t*]
|
||
|
||
// Build basis for T_d S^6 = {v ∈ T_{S_0} S^7 : ⟨v, d⟩ = 0}
|
||
B = build_direction_basis(S_0, d) // Returns 6 orthonormal vectors
|
||
|
||
// Finite differences on the direction sphere
|
||
∇F = 0 ∈ R^8
|
||
for k = 1 to 6:
|
||
b_k = B[k]
|
||
|
||
// Exponential map on S^6 (embedded in T_{S_0} S^7):
|
||
d_plus = cos(ε)·d + sin(ε)·b_k
|
||
d_minus = cos(ε)·d - sin(ε)·b_k
|
||
|
||
F_plus = evaluate_along_geodesic(S_0, d_plus, f)
|
||
F_minus = evaluate_along_geodesic(S_0, d_minus, f)
|
||
|
||
∂F/∂b_k = (F_plus - F_minus) / (2ε)
|
||
∇F += (∂F/∂b_k) · b_k
|
||
|
||
return ∇F
|
||
|
||
function build_direction_basis(S_0: S^7, d: Direction) → List[R^8]:
|
||
"""
|
||
Build orthonormal basis for T_d S^6, which is the subspace of
|
||
T_{S_0} S^7 orthogonal to d.
|
||
"""
|
||
// Start with full tangent basis at S_0
|
||
B_full = build_tangent_basis(S_0) // 7 vectors
|
||
|
||
// Remove component along d
|
||
basis = []
|
||
for b in B_full:
|
||
b_orth = b - ⟨b, d⟩ · d
|
||
if ||b_orth|| > ε_machine:
|
||
b_orth = b_orth / ||b_orth||
|
||
basis.append(b_orth)
|
||
|
||
// Should now have 6 vectors
|
||
assert len(basis) == 6
|
||
return basis
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Core Algorithm: `gradient_ascent_step`
|
||
|
||
### 5.1 Standard Riemannian Gradient Ascent
|
||
|
||
```
|
||
function gradient_ascent_step(
|
||
S_current: S^7, // Current point
|
||
f: S^7 → R, // Objective: compression ratio
|
||
learning_rate: float, // Step size η
|
||
grad_method: str = "fd" // "fd" or "smooth"
|
||
) → S_next:
|
||
|
||
// Compute Riemannian gradient
|
||
if grad_method == "fd":
|
||
∇f = compute_gradient(S_current, f, ε=1e-4, method="central")
|
||
elif grad_method == "smooth":
|
||
∇f = compute_smooth_gradient(S_current, f, β=100)
|
||
|
||
// Check for stationarity
|
||
if ||∇f|| < ε_stationary:
|
||
return S_current // Local maximum reached
|
||
|
||
// Normalize for unit-step control (optional)
|
||
// ∇f = ∇f / ||∇f||
|
||
|
||
// Riemannian gradient ascent via exponential map:
|
||
v = learning_rate · ∇f
|
||
S_next = exp_{S_current}(v)
|
||
= cos(||v||) · S_current + sin(||v||) · (v / ||v||) // (EM)
|
||
|
||
// Ensure we stay in the positive orthant
|
||
if any(S_next,i < 0):
|
||
// Project to nearest valid point on S^7 ∩ {x_i ≥ 0}
|
||
S_next = project_to_simplex_sphere(S_next)
|
||
|
||
return S_next
|
||
```
|
||
|
||
### 5.2 Adaptive Step Size (Line Search)
|
||
|
||
```
|
||
function gradient_ascent_step_adaptive(
|
||
S_current: S^7,
|
||
f: S^7 → R,
|
||
η_init: float = 0.1,
|
||
α: float = 0.5, // Backtracking factor
|
||
c: float = 1e-4, // Armijo constant
|
||
max_backtrack: int = 10
|
||
) → S_next:
|
||
|
||
∇f = compute_gradient(S_current, f)
|
||
grad_norm = ||∇f||
|
||
|
||
if grad_norm < ε_stationary:
|
||
return S_current
|
||
|
||
// Unit-norm gradient direction
|
||
g = ∇f / grad_norm
|
||
|
||
η = η_init
|
||
f_current = f(S_current)
|
||
|
||
for step = 1 to max_backtrack:
|
||
S_trial = cos(η·grad_norm)·S_current + sin(η·grad_norm)·g
|
||
S_trial = project_to_simplex_sphere(S_trial)
|
||
|
||
f_trial = f(S_trial)
|
||
|
||
// Armijo condition: sufficient increase
|
||
if f_trial ≥ f_current + c · η · grad_norm²:
|
||
return S_trial
|
||
|
||
η = α · η // Backtrack
|
||
|
||
// No improvement found — return current point
|
||
return S_current
|
||
```
|
||
|
||
### 5.3 Projection to Valid Simplex Sphere
|
||
|
||
```
|
||
function project_to_simplex_sphere(y: R^8) → S^7:
|
||
"""
|
||
Project y to the nearest point on S^7 ∩ {x_i ≥ 0}.
|
||
Uses alternating projection: sphere → orthant → sphere → ...
|
||
"""
|
||
x = y / ||y|| // Project to sphere
|
||
|
||
for iter = 1 to max_proj_iter:
|
||
// Clip negative components
|
||
x_clipped = max(x, 0) // element-wise
|
||
|
||
// If already in orthant, done
|
||
if ||x_clipped - x|| < ε:
|
||
return x_clipped / ||x_clipped||
|
||
|
||
// Project back to sphere
|
||
x = x_clipped / ||x_clipped||
|
||
|
||
return x
|
||
```
|
||
|
||
### 5.4 Momentum-Based Gradient Ascent on Manifold
|
||
|
||
For faster convergence, use Riemannian momentum:
|
||
|
||
```
|
||
function gradient_ascent_momentum(
|
||
S_current: S^7,
|
||
v_prev: T_{S_prev} S^7, // Previous velocity (in old tangent space)
|
||
S_prev: S^7, // Previous point
|
||
f: S^7 → R,
|
||
η: float, // Learning rate
|
||
μ: float = 0.9 // Momentum coefficient
|
||
) → (S_next, v_next):
|
||
|
||
// Compute gradient at current point
|
||
∇f = compute_gradient(S_current, f)
|
||
|
||
// Transport previous velocity to current tangent space
|
||
if v_prev is not null:
|
||
v_transport = P_{S_prev → S_current}(v_prev) // (PT)
|
||
else:
|
||
v_transport = 0
|
||
|
||
// Update velocity: v = μ · v_transport + ∇f
|
||
v = μ · v_transport + ∇f // in T_{S_current} S^7
|
||
|
||
// Riemannian gradient step with momentum
|
||
S_next = exp_{S_current}(η · v)
|
||
= cos(η·||v||)·S_current + sin(η·||v||)·(v/||v||)
|
||
|
||
S_next = project_to_simplex_sphere(S_next)
|
||
|
||
return (S_next, v)
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Core Algorithm: `sample_directions`
|
||
|
||
### 6.1 Uniform Sampling on T_{S_0} S^7
|
||
|
||
```
|
||
function sample_directions(
|
||
S_0: S^7,
|
||
N: int,
|
||
distribution: str = "uniform" // "uniform", "golden", "gradient_biased"
|
||
) → List[Direction]:
|
||
|
||
if distribution == "uniform":
|
||
return sample_uniform_directions(S_0, N)
|
||
|
||
elif distribution == "golden":
|
||
return sample_golden_directions(S_0, N)
|
||
|
||
elif distribution == "gradient_biased":
|
||
∇f = compute_gradient(S_0, f)
|
||
return sample_gradient_biased(S_0, N, ∇f)
|
||
```
|
||
|
||
### 6.2 Uniform Random Directions
|
||
|
||
```
|
||
function sample_uniform_directions(S_0: S^7, N: int) → List[Direction]:
|
||
"""
|
||
Sample N i.i.d. uniformly distributed directions on the
|
||
unit sphere S^6 ⊂ T_{S_0} S^7.
|
||
|
||
Algorithm: Sample standard Gaussian in R^8, project to tangent
|
||
space, normalize. This gives uniform distribution on S^6.
|
||
"""
|
||
directions = []
|
||
for _ = 1 to N:
|
||
v = randn(8) // N(0, I_8)
|
||
v_tangent = v - ⟨v, S_0⟩ · S_0
|
||
d = v_tangent / ||v_tangent||
|
||
directions.append(Direction{d})
|
||
return directions
|
||
```
|
||
|
||
### 6.3 Golden-Angle Directions (Φ-Quasi-Monte Carlo)
|
||
|
||
```
|
||
function sample_golden_directions(S_0: S^7, N: int) → List[Direction]:
|
||
"""
|
||
Generate N directions using the generalized golden angle on S^6.
|
||
Provides low-discrepancy coverage of the direction sphere.
|
||
|
||
Uses the Fibonacci lattice generalized to 7 dimensions with
|
||
the golden ratio φ = (1+√5)/2.
|
||
"""
|
||
φ = (1 + √5) / 2
|
||
|
||
// Build tangent basis
|
||
B = build_tangent_basis(S_0) // {e_1, ..., e_7}
|
||
|
||
directions = []
|
||
for n = 1 to N:
|
||
// Generalized Fibonacci angles in 7D
|
||
// Use the first 7 powers of φ modulo 1
|
||
angles = []
|
||
for k = 1 to 7:
|
||
α_k = 2π · fractional_part(n · φ^{-k})
|
||
angles.append(α_k)
|
||
|
||
// Convert angles to direction in the 7D tangent space
|
||
// Use hyperspherical coordinates
|
||
d_local = angles_to_unit_vector_7d(angles)
|
||
|
||
// Map from local 7D coordinates to R^8 via basis
|
||
d = Σ_{k=1}^7 d_local,k · e_k
|
||
|
||
directions.append(Direction{d})
|
||
|
||
return directions
|
||
```
|
||
|
||
**Hyperspherical coordinate mapping (7D → unit vector)**:
|
||
|
||
```
|
||
function angles_to_unit_vector_7d(angles: [θ_1,...,θ_7]) → R^7:
|
||
"""
|
||
Convert 7 angles to unit vector in R^7.
|
||
|
||
x_1 = cos(θ_1)
|
||
x_2 = sin(θ_1)·cos(θ_2)
|
||
x_3 = sin(θ_1)·sin(θ_2)·cos(θ_3)
|
||
...
|
||
x_7 = sin(θ_1)·...·sin(θ_6)·cos(θ_7)
|
||
x_8 = sin(θ_1)·...·sin(θ_6)·sin(θ_7)
|
||
|
||
(We use 7 angles for S^6, embedded in R^7 ~ T_{S_0} S^7)
|
||
"""
|
||
x = zeros(7)
|
||
sin_prod = 1.0
|
||
for k = 1 to 6:
|
||
x[k] = sin_prod · cos(angles[k])
|
||
sin_prod = sin_prod · sin(angles[k])
|
||
x[7] = sin_prod · cos(angles[7])
|
||
// Note: for S^6 in R^7, we need 6 angles, not 7
|
||
// The above gives 7D; for S^6 we use 6 angles
|
||
```
|
||
|
||
*Correction*: S^6 requires 6 angles in the hyperspherical coordinate system.
|
||
The generalized Fibonacci sequence on S^d uses d angles.
|
||
|
||
```
|
||
function sample_golden_directions_v2(S_0: S^7, N: int) → List[Direction]:
|
||
φ = (1 + √5) / 2
|
||
B = build_tangent_basis(S_0)
|
||
|
||
directions = []
|
||
for n = 1 to N:
|
||
// 6D generalized Fibonacci point
|
||
t = n / N
|
||
// Use 6 angular coordinates
|
||
coords = zeros(7)
|
||
for k = 1 to 7:
|
||
// Coordinate k = fractional part of n * φ^k, mapped to [-1, 1]
|
||
coords[k] = 2 · fractional_part(n · φ^{(k-1)/7}) - 1
|
||
|
||
// Project to unit sphere in the tangent space
|
||
d_local = coords / ||coords||
|
||
d = Σ_k d_local,k · B[k]
|
||
|
||
directions.append(Direction{d})
|
||
return directions
|
||
```
|
||
|
||
### 6.4 Gradient-Biased Direction Sampling
|
||
|
||
```
|
||
function sample_gradient_biased(
|
||
S_0: S^7,
|
||
N: int,
|
||
∇f: T_{S_0} S^7,
|
||
concentration: float = 5.0
|
||
) → List[Direction]:
|
||
"""
|
||
Sample directions biased toward the gradient direction.
|
||
Uses a von Mises-Fisher distribution on S^6 with mean
|
||
direction ∇f/||∇f|| and concentration parameter κ.
|
||
"""
|
||
μ = ∇f / ||∇f|| // Mean direction
|
||
κ = concentration // Concentration
|
||
|
||
directions = []
|
||
for _ = 1 to N:
|
||
// Rejection sampling for von Mises-Fisher
|
||
// or: sample from N(κ·μ, I), project to tangent space, normalize
|
||
v = randn(8) + κ · μ
|
||
v_tangent = v - ⟨v, S_0⟩ · S_0
|
||
d = v_tangent / ||v_tangent||
|
||
directions.append(Direction{d})
|
||
|
||
return directions
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Complete Self-Finding Loop Integration
|
||
|
||
### 7.1 Main Loop (from experiment spec)
|
||
|
||
```
|
||
function self_finding_loop(
|
||
S_0: S^7, // Initial state
|
||
max_iter: int = 100, // Maximum iterations
|
||
N_directions: int = 32, // Directions per search
|
||
T_steps: int = 16, // Steps per geodesic
|
||
η: float = 0.05, // Learning rate
|
||
ε_converge: float = 1e-6 // Convergence threshold
|
||
) → (S_opt, history):
|
||
|
||
S = S_0
|
||
history = []
|
||
|
||
for iter = 1 to max_iter:
|
||
// ---- Phase 1: Direction Search ----
|
||
(d*, t*, S_candidate, C*) = geodesic_search(
|
||
S, N_directions, T_steps
|
||
)
|
||
|
||
C_current = compression_ratio(spiral_index(S))
|
||
|
||
// ---- Phase 2: Gradient Ascent Step ----
|
||
if C* > C_current:
|
||
// Move toward candidate
|
||
f(x) = compression_ratio(spiral_index(x))
|
||
S = gradient_ascent_step(S, f, η, grad_method="fd")
|
||
else:
|
||
// Local maximum reached
|
||
break
|
||
|
||
// ---- Phase 3: Self-Reference (Strange Loop) ----
|
||
// Encode the search trajectory itself
|
||
trajectory = history + [(d*, t*, C*)]
|
||
n_exp = encode_trajectory(trajectory)
|
||
|
||
// ---- Phase 4: Meta-Update ----
|
||
// Optionally: use the experiment encoding as next starting point
|
||
// S_meta = spiral_to_sphere_point(n_exp)
|
||
// This closes the strange loop
|
||
|
||
history.append({
|
||
'iteration': iter,
|
||
'S': S,
|
||
'C': C_current,
|
||
'd_best': d*,
|
||
't_best': t*,
|
||
'n_exp': n_exp
|
||
})
|
||
|
||
// Convergence check
|
||
if len(history) > 1:
|
||
C_prev = history[-2]['C']
|
||
if |C_current - C_prev| / C_prev < ε_converge:
|
||
break
|
||
|
||
return (S, history)
|
||
```
|
||
|
||
### 7.2 Encoding the Trajectory
|
||
|
||
```
|
||
function encode_trajectory(trajectory: List[(d, t, C)]) → int:
|
||
"""
|
||
Encode the search trajectory as a spiral index.
|
||
This creates the 'strange loop' — the search encodes itself.
|
||
|
||
The trajectory is a sequence of (direction, step, compression) tuples.
|
||
We serialize this and encode as a DNA sequence via the Φ-corkscrew.
|
||
"""
|
||
// Serialize trajectory to a bit string
|
||
bits = serialize(trajectory) // e.g., using IEEE 754 floats
|
||
|
||
// Convert bit string to integer
|
||
n_trajectory = bit_string_to_int(bits)
|
||
|
||
// Map to spiral index
|
||
n_exp = spiral_index_from_int(n_trajectory)
|
||
|
||
return n_exp
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Convergence Analysis
|
||
|
||
### 8.1 Convergence of Geodesic Search
|
||
|
||
**Theorem** (Local convergence). Let C: S^7 → R be the compression
|
||
ratio function. If C is L-smooth on S^7 (Riemannian gradient is
|
||
L-Lipschitz) and bounded above, then gradient ascent with step size
|
||
η ∈ (0, 2/L) converges to a stationary point.
|
||
|
||
**Proof sketch**:
|
||
1. The exponential map exp_x is the standard geodesic flow on S^7
|
||
2. The sectional curvature of S^7 is constant K = 1 > 0
|
||
3. For positively curved manifolds, gradient ascent with appropriate
|
||
step size decreases the objective gradient norm to zero
|
||
4. By compactness of S^7 and continuity (of the smooth relaxation),
|
||
the sequence has a convergent subsequence
|
||
5. The limit point satisfies ∇C = 0 (stationary point)
|
||
|
||
### 8.2 Rate of Convergence
|
||
|
||
For gradient ascent on S^7 with constant step size η:
|
||
|
||
```
|
||
C(S_{k+1}) - C(S*) ≤ (1 - η·m) · (C(S_k) - C(S*)) [if m-strongly convex]
|
||
```
|
||
|
||
where m is the strong convexity parameter (lower bound on Hessian
|
||
eigenvalues in the tangent space).
|
||
|
||
For non-convex C (the general case):
|
||
```
|
||
min_{0≤k≤K} ||∇C(S_k)||² ≤ (C(S_0) - C(S*)) / (η·K)
|
||
```
|
||
|
||
O(1/√K) rate for gradient norm, O(1/K) for strongly convex regions.
|
||
|
||
### 8.3 Effect of Self-Reference
|
||
|
||
When the trajectory encoding is used as the next starting point:
|
||
|
||
```
|
||
S_{k+1} = f(S_k, trajectory(S_0, ..., S_k))
|
||
```
|
||
|
||
This creates a **non-Markovian** dynamical system. The convergence
|
||
properties depend on the encoding map. Empirically, self-reference
|
||
acts as a form of momentum: the encoded trajectory contains
|
||
information about the "shape" of the compression landscape, which
|
||
guides future searches.
|
||
|
||
---
|
||
|
||
## 9. Computational Complexity
|
||
|
||
| Operation | Complexity | Notes |
|
||
|-----------|-----------|-------|
|
||
| `sample_directions` | O(N · d) | d=8, N directions |
|
||
| `γ_d(t)` (geodesic) | O(d) | One evaluation |
|
||
| `geodesic_search` | O(N · T · (d + T_spiral)) | T_spiral = spiral_index cost |
|
||
| `compute_gradient` | O(2d · T_spiral) | 2·7 = 14 function evals |
|
||
| `gradient_ascent_step` | O(2d · T_spiral) | Same as gradient |
|
||
| `parallel_transport` | O(d) | Negligible |
|
||
| Full iteration | O(N·T·T_spiral) | Dominated by spiral_index |
|
||
|
||
Where `T_spiral` = cost of `spiral_index(x)` = O(N_spiral) for a
|
||
search over N_spiral spiral points (can be accelerated with KD-trees
|
||
to O(log N_spiral)).
|
||
|
||
---
|
||
|
||
## 10. Summary of Key Formulas
|
||
|
||
| Formula | Equation | Description |
|
||
|---------|----------|-------------|
|
||
| Geodesic | γ_d(t) = cos(t)·x + sin(t)·d | (G1) Great circle on S^7 |
|
||
| Exponential Map | exp_x(v) = cos(||v||)·x + sin(||v||)·(v/||v||) | (EM) Geodesic flow |
|
||
| Logarithm Map | log_x(y) = arccos(⟨x,y⟩)·(y-⟨x,y⟩x)/||...|| | (LM) Inverse exponential |
|
||
| Parallel Transport | P_{x→y}(v) = v - (⟨v,y⟩/(1+⟨x,y⟩))·(x+y) | (PT) Along geodesic |
|
||
| Tangent Projection | Proj_{T_x}(v) = v - ⟨v,x⟩·x | Project to tangent space |
|
||
| Boundary Limit | t_max = min_i arctan(-x_i/d_i) for d_i < 0 | (G2) Simplex boundary |
|
||
| Gradient (FD) | ∇f = Σ_k [f(exp(ε·e_k)) - f(exp(-ε·e_k))]/(2ε) · e_k | Central differences |
|
||
| Gradient Step | S_{next} = exp_S(η·∇f) | Riemannian ascent |
|
||
|
||
---
|
||
|
||
## 11. Interface Specification
|
||
|
||
### 11.1 Function Signatures
|
||
|
||
```python
|
||
def geodesic_search(
|
||
S_0: np.ndarray, # shape (8,), unit vector, S_0 >= 0
|
||
N_directions: int, # number of directions to sample
|
||
T_steps: int, # number of steps per geodesic
|
||
t_max: float = np.pi/2, # maximum geodesic distance
|
||
step_pattern: str = "geometric",
|
||
f: Callable = compression_ratio_at_point # f: S^7 -> R
|
||
) -> Tuple[np.ndarray, float, np.ndarray, float]:
|
||
"""Returns (d_best, t_best, S_best, C_best)"""
|
||
|
||
|
||
def gradient_ascent_step(
|
||
S_current: np.ndarray, # shape (8,), current point
|
||
f: Callable, # objective function f: S^7 -> R
|
||
learning_rate: float, # step size η
|
||
grad_method: str = "fd", # "fd" or "smooth"
|
||
ε: float = 1e-4 # finite difference step
|
||
) -> np.ndarray:
|
||
"""Returns S_next (shape (8,))"""
|
||
|
||
|
||
def sample_directions(
|
||
S_0: np.ndarray, # shape (8,), anchor point
|
||
N: int, # number of directions
|
||
distribution: str = "uniform" # "uniform", "golden", "gradient_biased"
|
||
) -> np.ndarray:
|
||
"""Returns directions (shape (N, 8)), each row is a unit tangent vector"""
|
||
|
||
|
||
def compute_gradient(
|
||
S: np.ndarray, # shape (8,), evaluation point
|
||
f: Callable, # f: S^7 -> R
|
||
ε: float = 1e-4, # FD step size
|
||
method: str = "central" # "central", "forward"
|
||
) -> np.ndarray:
|
||
"""Returns gradient (shape (8,)), in T_S S^7"""
|
||
|
||
|
||
def parallel_transport(
|
||
v: np.ndarray, # shape (8,), tangent vector at x
|
||
x: np.ndarray, # shape (8,), source point
|
||
y: np.ndarray # shape (8,), target point
|
||
) -> np.ndarray:
|
||
"""Returns transported vector (shape (8,)), in T_y S^7"""
|
||
```
|
||
|
||
### 11.2 Type Definitions
|
||
|
||
```python
|
||
S7Point = np.ndarray # shape (8,), ||x|| = 1, x_i >= 0
|
||
Direction = np.ndarray # shape (8,), ||d|| = 1, <d, x> = 0
|
||
TangentV = np.ndarray # shape (8,), <v, x> = 0
|
||
ScalarFn = Callable[[S7Point], float]
|
||
```
|
||
|
||
---
|
||
|
||
## 12. Testing Strategy
|
||
|
||
### 12.1 Unit Tests
|
||
|
||
1. **Geodesic stays on sphere**: For random x, d, t: verify ||γ_d(t)|| = 1
|
||
2. **Tangent constraint**: Verify ⟨d, S_0⟩ = 0 for all sampled directions
|
||
3. **Unit norm**: Verify ||d|| = 1 for all directions
|
||
4. **Gradient is tangent**: Verify ⟨∇f, S⟩ = 0
|
||
5. **Gradient ascent increases f**: For a known function, verify f(S_next) > f(S)
|
||
6. **Parallel transport is isometric**: Verify ||P(v)|| = ||v||
|
||
7. **Exponential and log are inverses**: Verify log_x(exp_x(v)) ≈ v
|
||
|
||
### 12.2 Integration Tests
|
||
|
||
1. **Known optimum**: Test on a function with known maximum on S^7
|
||
2. **Symmetry**: Verify gradient is zero at symmetric points for symmetric functions
|
||
3. **Convergence**: Verify ||∇f|| → 0 as iterations increase
|
||
4. **Boundary handling**: Verify geodesics don't leave the simplex
|
||
|
||
### 12.3 End-to-End Test
|
||
|
||
```
|
||
S_0 = uniform point on S^7 ∩ {x_i >= 0}
|
||
(d*, t*, S*, C*) = geodesic_search(S_0, N=64, T=32)
|
||
assert C* >= compression_ratio(spiral_index(S_0))
|
||
assert ||S*|| ≈ 1
|
||
assert all(S* >= 0)
|
||
```
|
||
|
||
---
|
||
|
||
## 13. References
|
||
|
||
1. Amari, S.-I. (2016). *Information Geometry and Its Applications*. Springer.
|
||
2. Chentsov, N.N. (1982). *Statistical Decision Rules and Optimal Inference*.
|
||
3. Absil, P.-A., Mahony, R., & Sepulchre, R. (2008). *Optimization Algorithms
|
||
on Matrix Manifolds*. Princeton University Press.
|
||
4. Boumal, N. (2023). *An Introduction to Optimization on Smooth Manifolds*.
|
||
Cambridge University Press.
|
||
5. Audet, C. & Dennis, J.E. (2006). "Mesh Adaptive Direct Search Algorithms
|
||
for Constrained Optimization*. SIAM Journal on Optimization.
|
||
|
||
---
|
||
|
||
*End of Geodesic Search Algorithm Specification*
|