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}