|
| 1 | +# Track 2 capstone: end-to-end ML pipeline composing every substrate |
| 2 | +# primitive the language now ships: |
| 3 | +# |
| 4 | +# 1. Feature engineering through substrate-typed arrays |
| 5 | +# (arr_scale + arr_add + arr_fold_all) |
| 6 | +# 2. Linear projection via arr_matmul (2D array op) |
| 7 | +# 3. Substrate-aware loss reading per-element resonance |
| 8 | +# 4. Forward-mode autograd via dual numbers training a parameter |
| 9 | +# with closed-form gradient descent |
| 10 | +# |
| 11 | +# Stops when the dual-number gradient has driven the loss below 0.01, |
| 12 | +# proving the autograd, matmul, and substrate-typed primitives all |
| 13 | +# co-operate end-to-end on a single workload. |
| 14 | + |
| 15 | +fn approx_eq(a, b, tol) { |
| 16 | + h d = a - b; |
| 17 | + if d < 0.0 { d = 0.0 - d; } |
| 18 | + return d <= tol; |
| 19 | +} |
| 20 | + |
| 21 | +# --- Part 1: substrate-aware feature pipeline ----------------------- |
| 22 | +# Take raw counts, scale by 2, bias by 1, then fold to the nearest |
| 23 | +# Fibonacci attractor. Output: substrate-aligned feature buckets. |
| 24 | + |
| 25 | +fn substrate_features(raw) { |
| 26 | + h scaled = arr_scale(raw, 2); |
| 27 | + h biased = arr_add(scaled, 1); |
| 28 | + return arr_fold_all(biased); |
| 29 | +} |
| 30 | + |
| 31 | +# --- Part 2: 2D matmul-based projection ----------------------------- |
| 32 | +# Project a 1xN row through an NxK weight matrix to get a 1xK output. |
| 33 | + |
| 34 | +fn project(row_features, W) { |
| 35 | + # Wrap features in 1xN matrix so arr_matmul shapes line up. |
| 36 | + h M = [row_features]; |
| 37 | + return arr_matmul(M, W); |
| 38 | +} |
| 39 | + |
| 40 | +# --- Part 3: substrate-coherence score ------------------------------ |
| 41 | +# Mean resonance over array elements. High = substrate-aligned. |
| 42 | + |
| 43 | +fn substrate_score(arr) { |
| 44 | + h r = arr_resonance_vec(arr); |
| 45 | + h s = 0.0; |
| 46 | + h i = 0; |
| 47 | + while i < arr_len(r) { |
| 48 | + s = s + arr_get(r, i); |
| 49 | + i = i + 1; |
| 50 | + } |
| 51 | + return s / arr_len(r); |
| 52 | +} |
| 53 | + |
| 54 | +# --- Part 4: dual-number gradient descent --------------------------- |
| 55 | +# Loss L(w) = sum_i (w*x_i - y_i)^2 on a small dataset. |
| 56 | +# Each step: lift w to dual(w, 1.0), evaluate L', read dL/dw, step. |
| 57 | + |
| 58 | +fn loss_and_grad(w_value, xs, ys) { |
| 59 | + h w = dual(w_value, 1.0); # seed for d/dw |
| 60 | + h L = dual(0.0, 0.0); |
| 61 | + h n = arr_len(xs); |
| 62 | + h i = 0; |
| 63 | + while i < n { |
| 64 | + h xi = arr_get(xs, i); |
| 65 | + h yi = arr_get(ys, i); |
| 66 | + h pred = dual_mul(w, xi); |
| 67 | + h err = dual_sub(pred, yi); |
| 68 | + L = dual_add(L, dual_mul(err, err)); |
| 69 | + i = i + 1; |
| 70 | + } |
| 71 | + return L; |
| 72 | +} |
| 73 | + |
| 74 | +fn main() { |
| 75 | + print("=== Track 2 capstone: harmonic ML pipeline ==="); |
| 76 | + print(""); |
| 77 | + |
| 78 | + # --- Substrate feature pipeline demo --- |
| 79 | + print("[1] Substrate-aware feature engineering"); |
| 80 | + h raw = [3, 5, 8, 13, 21]; # Fibonacci-shaped raw counts |
| 81 | + h features = substrate_features(raw); |
| 82 | + h score_before = substrate_score(raw); |
| 83 | + h score_after = substrate_score(features); |
| 84 | + print(" raw -> mean resonance: " + to_string(score_before)); |
| 85 | + print(" folded -> mean resonance: " + to_string(score_after)); |
| 86 | + |
| 87 | + # --- 2D matmul projection --- |
| 88 | + print(""); |
| 89 | + print("[2] Linear projection (1x5) * (5x2) -> (1x2)"); |
| 90 | + # Fibonacci-valued weight matrix (substrate-resonant). |
| 91 | + h W = [[1, 0], [1, 1], [2, 1], [3, 2], [5, 3]]; |
| 92 | + h projected = project(features, W); |
| 93 | + h row = arr_get(projected, 0); |
| 94 | + print(" projected = [" + to_string(arr_get(row, 0)) + ", " + |
| 95 | + to_string(arr_get(row, 1)) + "]"); |
| 96 | + |
| 97 | + # --- Gradient-descent training --- |
| 98 | + print(""); |
| 99 | + print("[3] Gradient descent training on y = 2x"); |
| 100 | + # Synthetic dataset: y = 2*x for x in [1..5]. |
| 101 | + h xs = [1.0, 2.0, 3.0, 4.0, 5.0]; |
| 102 | + h ys = [2.0, 4.0, 6.0, 8.0, 10.0]; |
| 103 | + h w = 0.1; # start far from the truth (2.0) |
| 104 | + h lr = 0.01; |
| 105 | + h step = 0; |
| 106 | + h max_steps = 200; |
| 107 | + h converged = 0; |
| 108 | + |
| 109 | + while step < max_steps { |
| 110 | + h L = loss_and_grad(w, xs, ys); |
| 111 | + h Lv = dual_v(L); |
| 112 | + h dLdw = dual_d(L); |
| 113 | + if Lv < 0.01 { |
| 114 | + converged = 1; |
| 115 | + print(" converged at step " + to_string(step) + |
| 116 | + ", w=" + to_string(w) + |
| 117 | + ", loss=" + to_string(Lv)); |
| 118 | + step = max_steps; |
| 119 | + } else { |
| 120 | + w = w - lr * dLdw; |
| 121 | + if step % 25 == 0 { |
| 122 | + print(" step " + to_string(step) + |
| 123 | + " w=" + to_string(w) + |
| 124 | + " loss=" + to_string(Lv) + |
| 125 | + " dL/dw=" + to_string(dLdw)); |
| 126 | + } |
| 127 | + step = step + 1; |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + if converged == 1 { |
| 132 | + print(""); |
| 133 | + print("[OK] autograd + matmul + substrate primitives composed end-to-end"); |
| 134 | + } else { |
| 135 | + print(""); |
| 136 | + print("[!] did not converge within " + to_string(max_steps) + " steps"); |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | +main(); |
0 commit comments