code wiki / _hdl_build / nx_evolve.nx

nx_evolve.nx source

↩ module page · 167 lines · 7763 B

1// nx_evolve.nx -- X-EVO-001: the EVOLUTION HARNESS (operator self-sufficiency arc; 2// configured from the EC taxonomy evo_params.tsv, not invention). Rung 1 validates 3// the MACHINERY on a fitness with a KNOWN optimum (you cannot trust an optimizer you 4// cannot verify) -- then rung 2 swaps fitness_id for a GATE permil (the exceed: we 5// grow evaluators). Every EC operator from the taxonomy, wired: 6// population = candidate integer vectors selection = TOURNAMENT (best-of-k) 7// mutation = per-gene +-1 at mutation_rate elitism = best carried unchanged 8// generation = one loop; best logged (lineage) termination = convergence streak 9// seeding = xorshift64 from cfg seed (FIXED-PER-RUN reproducibility law) 10// diversity = tournament_k tunes greed<->variety (the niching knob) 11// fitness 0 = -sphere(target) (unimodal, optimum known = target vector, fitness 0) 12// fitness 1 = -rastrigin-ish (multimodal: -(sum (g-t)^2 + 8*(g!=t)) -- many basins) 13// cfg ints: pop gens mut_rate_inv tour_k dims seed fitness_id target (mut_rate = 14// 1/mut_rate_inv per gene per gen). Durable: EVOLVE-GEN + EVOLVE rows -> 15// knowledge/status/evolve.log. Exit 0 = converged to optimum; 1 = did not. 16// argv[1..]=cfg override ints (gates drive scratch configs deterministically). 17// license_tier: ORIGINAL 18import "nx_syscalls.nx" 19const K_MAGIC_1000000: i64 = 1000000 20const K_MAGIC_2463534242: i64 = 2463534242 21func _p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 22func _fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 23func _fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m; sys_write(fd,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 24func ev_atoi(s: *u8) -> i64 { 25 var i: i64 = 0 26 var neg: i64 = 0 27 if s[0] == (45 as u8) { neg = 1; i = 1 } 28 var v: i64 = 0 29 while s[i] >= (48 as u8) { if s[i] > (57 as u8) { i = i + K_MAGIC_1000000 } else { v = v * 10 + ((s[i] as i64) - 48); i = i + 1 } } 30 if neg == 1 { return 0 - v } 31 return v 32} 33// xorshift64* deterministic PRNG (state in s[0]); reproducibility law -- no clock 34func ev_rand(s: *i64) -> i64 { 35 var x: i64 = s[0] 36 x = x ^ (x << 13) 37 x = x ^ ((x >> 7) & 0x01FFFFFFFFFFFFFF) 38 x = x ^ (x << 17) 39 s[0] = x 40 var r: i64 = x 41 if r < 0 { r = 0 - r } 42 return r 43} 44// fitness: higher = better; optimum = 0 at g == target for both kinds 45func ev_fit(g: *i64, dims: i64, target: i64, kind: i64) -> i64 { 46 var f: i64 = 0 47 var i: i64 = 0 48 while i < dims { 49 let d: i64 = g[i] - target 50 f = f - d * d 51 if kind == 1 { if d != 0 { f = f - 8 } } 52 i = i + 1 53 } 54 return f 55} 56func main(argc: i64, argv: *i64) -> i64 { 57 // defaults (overridable by argv for the gate's deterministic scratch runs) 58 var pop: i64 = 24 59 var gens: i64 = 120 60 var mut_inv: i64 = 4 61 var tour_k: i64 = 3 62 var dims: i64 = 6 63 var seed: i64 = K_MAGIC_2463534242 64 var kind: i64 = 1 65 var target: i64 = 7 66 if argc >= 2 { pop = ev_atoi(argv[1] as *u8) } 67 if argc >= 3 { gens = ev_atoi(argv[2] as *u8) } 68 if argc >= 4 { mut_inv = ev_atoi(argv[3] as *u8) } 69 if argc >= 5 { tour_k = ev_atoi(argv[4] as *u8) } 70 if argc >= 6 { dims = ev_atoi(argv[5] as *u8) } 71 if argc >= 7 { seed = ev_atoi(argv[6] as *u8) } 72 if argc >= 8 { kind = ev_atoi(argv[7] as *u8) } 73 if argc >= 9 { target = ev_atoi(argv[8] as *u8) } 74 if pop < 2 { pop = 2 } 75 if mut_inv < 1 { mut_inv = 1 } 76 if tour_k < 1 { tour_k = 1 } 77 _p("=== EVOLVE: EC machinery on a known-optimum fitness (validate, then gate-fit) ===\n" as *u8) 78 let s: *i64 = sys_mmap(16) as *i64 79 s[0] = seed 80 // population: pop x dims integers, init in [-20,20] 81 let g: *i64 = sys_mmap(8 * pop * dims) as *i64 82 let fit: *i64 = sys_mmap(8 * pop) as *i64 83 var p: i64 = 0 84 while p < pop { 85 var d: i64 = 0 86 while d < dims { 87 g[p * dims + d] = (ev_rand(s) % 41) - 20 88 d = d + 1 89 } 90 fit[p] = ev_fit((g as i64 + p * dims * 8) as *i64, dims, target, kind) 91 p = p + 1 92 } 93 let lfd: i64 = sys_openat_append("knowledge/status/evolve.log" as *u8, 0x1a4) 94 if lfd < 0 { _p(" evolve log open failed\n" as *u8); sys_exit(1); return 1 } 95 _fp(lfd, "EVOLVE-RUN epoch=" as *u8); _fn(lfd, sys_now_realtime_sec()) 96 _fp(lfd, " pop=" as *u8); _fn(lfd, pop); _fp(lfd, " mut_inv=" as *u8); _fn(lfd, mut_inv) 97 _fp(lfd, " tour_k=" as *u8); _fn(lfd, tour_k); _fp(lfd, " seed=" as *u8); _fn(lfd, seed) 98 _fp(lfd, " kind=" as *u8); _fn(lfd, kind); _fp(lfd, "\n" as *u8) 99 // gen-0 best (baseline for the improvement gate) 100 var best: i64 = fit[0] 101 var bi: i64 = 0 102 var q: i64 = 1 103 while q < pop { if fit[q] > best { best = fit[q]; bi = q } q = q + 1 } 104 let gen0best: i64 = best 105 let child: *i64 = sys_mmap(8 * pop * dims) as *i64 106 var stale: i64 = 0 107 var converged: i64 = 0 108 var gen: i64 = 0 109 while gen < gens { 110 // ELITISM: child slot 0 = current best, unchanged 111 var d0: i64 = 0 112 while d0 < dims { child[d0] = g[bi * dims + d0]; d0 = d0 + 1 } 113 // fill the rest by TOURNAMENT selection + MUTATION 114 var c: i64 = 1 115 while c < pop { 116 // tournament: best of tour_k random parents 117 var winner: i64 = ev_rand(s) % pop 118 var tk: i64 = 1 119 while tk < tour_k { 120 let challenger: i64 = ev_rand(s) % pop 121 if fit[challenger] > fit[winner] { winner = challenger } 122 tk = tk + 1 123 } 124 var d: i64 = 0 125 while d < dims { 126 var gv: i64 = g[winner * dims + d] 127 // MUTATION: at rate 1/mut_inv, perturb by +-1 128 if (ev_rand(s) % mut_inv) == 0 { 129 if (ev_rand(s) & 1) == 0 { gv = gv + 1 } else { gv = gv - 1 } 130 } 131 child[c * dims + d] = gv 132 d = d + 1 133 } 134 c = c + 1 135 } 136 // generational replace + re-evaluate 137 var x: i64 = 0 138 while x < pop * dims { g[x] = child[x]; x = x + 1 } 139 var nb: i64 = fit[0] 140 p = 0 141 while p < pop { 142 fit[p] = ev_fit((g as i64 + p * dims * 8) as *i64, dims, target, kind) 143 p = p + 1 144 } 145 nb = fit[0]; bi = 0 146 q = 1 147 while q < pop { if fit[q] > nb { nb = fit[q]; bi = q } q = q + 1 } 148 // CONVERGENCE: best unchanged for a streak 149 if nb <= best { stale = stale + 1 } else { stale = 0 } 150 best = nb 151 if (gen % 20) == 0 { _fp(lfd, "EVOLVE-GEN gen=" as *u8); _fn(lfd, gen); _fp(lfd, " best=" as *u8); _fn(lfd, best); _fp(lfd, "\n" as *u8) } 152 if best == 0 { converged = 1; gen = gens } 153 if stale >= 25 { gen = gens } 154 gen = gen + 1 155 } 156 _fp(lfd, "EVOLVE epoch=" as *u8); _fn(lfd, sys_now_realtime_sec()) 157 _fp(lfd, " gen0_best=" as *u8); _fn(lfd, gen0best) 158 _fp(lfd, " final_best=" as *u8); _fn(lfd, best) 159 _fp(lfd, " optimum_found=" as *u8); _fn(lfd, converged) 160 if converged == 1 { _fp(lfd, " verdict=CONVERGED\n" as *u8) } else { _fp(lfd, " verdict=PARTIAL\n" as *u8) } 161 sys_close(lfd) 162 _p(" final_best=" as *u8); _fn(1, best); _p(" (0 = global optimum)\n" as *u8) 163 if converged == 1 { _p(" EVOLVE: CONVERGED to the known optimum (machinery validated)\n" as *u8); sys_exit(0); return 0 } 164 _p(" EVOLVE: PARTIAL (improved but not at optimum -- raise gens or tune knobs)\n" as *u8) 165 sys_exit(1) 166 return 1 167}