code wiki / _hdl_build / nx_evolve_gap.nx
nx_evolve_gap.nx source
↩ module page · 229 lines · 11058 B
1// nx_evolve_gap.nx -- the EVOLUTIONARY-COMPUTATION team member, wired into team-solve as TIER-2: when
2// tier-1 mechanistic-search can't solve a gap (it needs PARAMETERS a bare capability can't supply),
3// EVOLUTION searches the parameter (GENE) space. Concretely: the team has a PARAMETERIZED capability
4// reduce_op <op> <init> (op in {add,mul,max,min}, init); this organ EVOLVES the (op,init) genes with
5// the EC operators from the taxonomy (evo_params.tsv): a POPULATION of genes, TOURNAMENT selection,
6// per-gene MUTATION, ELITISM, FIXED-seed reproducibility -- and the FITNESS is the EXTERNAL ALE HARNESS
7// SCORE (the designed "swap fitness_id for a gate permil"). It evolves until a gene scores 1000 -> the
8// gap is SOLVED by the evolutionary member, NO LLM. HONEST: for this small/binary gap evolution is a
9// guided search; nx_evolve validates GP's gradient-climbing on smooth/multimodal landscapes
10// (sphere/rastrigin) -- together they are the team's evolutionary search across landscapes. (DRY note:
11// the shared GP loop wants extraction to a lib once a 3rd consumer appears, per rule 15.)
12// args mode: nx_evolve_gap <gap_task> -> evolve genes; print the solving (op,init) or UNSOLVED.
13// no-arg: SELF-GATE on the product gap task_reduce -> evolution MUST discover (mul,1) -> GREEN.
14// license_tier: ORIGINAL
15//
16// module: nishi-core.team.evolve_gap
17// depends: nishi-core.sys.syscalls
18// capability: EVOLUTIONARY_GAP_SOLVE
19import "nx_syscalls.nx"
20const EG_MAGIC_262144: i64 = 262144
21
22const EG_POP: i64 = 16
23const EG_GENS: i64 = 4
24const EG_TOURK: i64 = 3
25
26func eg_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
27func eg_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 }
28func eg_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; 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 }
29func eg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
30func eg_unlink(path: *u8) -> i64 { return __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) }
31
32func eg_read(path: *u8, buf: *u8, cap: i64) -> i64 {
33 let fd: i64 = sys_openat_rd(path)
34 if fd < 0 { return 0 }
35 var n: i64 = 0
36 var go: i64 = 1
37 while go == 1 {
38 let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - 1 - n)
39 if r <= 0 { go = 0 } else { n = n + r }
40 if n >= cap - 1 { go = 0 }
41 }
42 sys_close(fd)
43 return n
44}
45
46func eg_score_of(path: *u8) -> i64 {
47 let sb: *u8 = sys_mmap(64)
48 let n: i64 = eg_read(path, sb, 64)
49 if n <= 0 { return 0 - 1 }
50 var v: i64 = 0
51 var i: i64 = 0
52 while i < n { if sb[i] >= (48 as u8) { if sb[i] <= (57 as u8) { v = v * 10 + (sb[i] - 48) } } i = i + 1 }
53 return v
54}
55
56// xorshift64 RNG (FIXED seed -> reproducible run, the EC law).
57func eg_rand(s: *i64) -> i64 {
58 var x: i64 = s[0]
59 x = x ^ (x << 13)
60 x = x ^ ((x >> 7) & 0x1ffffffffffffff)
61 x = x ^ (x << 17)
62 s[0] = x
63 if x < 0 { return 0 - x }
64 return x
65}
66
67func eg_modn(v: i64, n: i64) -> i64 { var r: i64 = v % n; if r < 0 { r = r + n } return r }
68
69// write a variant of the gap task with instruction "reduce_op <op> <init>" (op from a 0..3 gene).
70func eg_variant(taskbuf: *u8, tn: i64, op: i64, init: i64, outpath: *u8) -> i64 {
71 let ob: *u8 = sys_mmap(EG_MAGIC_262144)
72 var o: i64 = 0
73 var ls: i64 = 0
74 var i: i64 = 0
75 while i <= tn {
76 var eol: i64 = 0
77 if i == tn { eol = 1 } else { if taskbuf[i] == (10 as u8) { eol = 1 } }
78 if eol == 1 {
79 var isinstr: i64 = 0
80 let key: *u8 = "task|instruction|" as *u8
81 if ls + 16 <= i { var k: i64 = 0; var m2: i64 = 1; while k < 16 { if taskbuf[ls+k] != key[k] { m2 = 0; k = 16 } else { k = k + 1 } } if m2 == 1 { isinstr = 1 } }
82 if isinstr == 1 {
83 let pre: *u8 = "task|instruction|reduce_op " as *u8
84 var j: i64 = 0
85 while pre[j] != (0 as u8) { ob[o] = pre[j]; o = o + 1; j = j + 1 }
86 if op == 0 { ob[o] = 97; ob[o+1] = 100; ob[o+2] = 100 }
87 if op == 1 { ob[o] = 109; ob[o+1] = 117; ob[o+2] = 108 }
88 if op == 2 { ob[o] = 109; ob[o+1] = 97; ob[o+2] = 120 }
89 if op == 3 { ob[o] = 109; ob[o+1] = 105; ob[o+2] = 110 }
90 o = o + 3
91 ob[o] = 32; o = o + 1
92 var m: i64 = init
93 let t: *u8 = sys_mmap(28); var kk: i64 = 0
94 if m == 0 { t[0] = 48; kk = 1 }
95 while m > 0 { t[kk] = (48 + (m % 10)) as u8; m = m / 10; kk = kk + 1 }
96 var q: i64 = 0
97 while q < kk { ob[o] = t[kk - 1 - q]; o = o + 1; q = q + 1 }
98 ob[o] = 10; o = o + 1
99 } else {
100 var p: i64 = ls
101 while p < i { ob[o] = taskbuf[p]; o = o + 1; p = p + 1 }
102 if i < tn { ob[o] = 10; o = o + 1 }
103 }
104 ls = i + 1
105 }
106 i = i + 1
107 }
108 eg_unlink(outpath)
109 let fd: i64 = sys_openat_wr(outpath, 0x1a4)
110 if fd < 0 { return 0 }
111 sys_write(fd, ob, o)
112 sys_close(fd)
113 return o
114}
115
116// FITNESS = external ALE harness score of the (op,init)-configured reduce on the gap task.
117func eg_fitness(taskbuf: *u8, tn: i64, op: i64, init: i64) -> i64 {
118 eg_variant(taskbuf, tn, op, init, "/tmp/_eg_variant.txt" as *u8)
119 sys_mkdir("/tmp/_eg_sb" as *u8, 0x1ed); sys_mkdir("/tmp/_eg_out" as *u8, 0x1ed)
120 eg_unlink("/tmp/_eg_sc" as *u8)
121 let pid: i64 = sys_fork()
122 if pid == 0 {
123 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4)
124 if dn >= 0 { sys_dup3(dn, 1, 0); sys_dup3(dn, 2, 0) }
125 let argv: *i64 = sys_mmap(48) as *i64
126 argv[0] = "_offc/nx_ale_harness.elf" as *u8 as i64
127 argv[1] = "/tmp/_eg_variant.txt" as *u8 as i64
128 argv[2] = "/tmp/_eg_sb" as *u8 as i64
129 argv[3] = "/tmp/_eg_out" as *u8 as i64
130 argv[4] = "/tmp/_eg_sc" as *u8 as i64
131 argv[5] = 0
132 let envp: *i64 = sys_mmap(16) as *i64
133 envp[0] = 0
134 sys_execve("_offc/nx_ale_harness.elf" as *u8, argv, envp)
135 sys_exit(127)
136 }
137 let st: *i64 = sys_mmap(16) as *i64
138 sys_wait4(pid, st, 0)
139 let sc: i64 = eg_score_of("/tmp/_eg_sc" as *u8)
140 if sc < 0 { return 0 }
141 return sc
142}
143
144// evolve (op,init) genes to maximize the harness score on the gap task. on success fills *bop/*binit
145// and returns the generation it converged; -1 if UNSOLVED within EG_GENS.
146func eg_evolve(taskpath: *u8, bop: *i64, binit: *i64) -> i64 {
147 let taskbuf: *u8 = sys_mmap(EG_MAGIC_262144)
148 let tn: i64 = eg_read(taskpath, taskbuf, EG_MAGIC_262144)
149 if tn <= 0 { return 0 - 1 }
150 let seed: *i64 = sys_mmap(16) as *i64
151 seed[0] = 0x2545f4914f6cdd1d
152 let pop_op: *i64 = sys_mmap(8 * EG_POP) as *i64
153 let pop_in: *i64 = sys_mmap(8 * EG_POP) as *i64
154 // seed the initial population to COVER the (op,init) gene space (op=i%4, init=i/4) so a small
155 // run converges fast on this tiny binary landscape; tournament+mutation refine across gens.
156 var i: i64 = 0
157 while i < EG_POP { pop_op[i] = eg_modn(i, 4); pop_in[i] = i / 4; i = i + 1 }
158 var gen: i64 = 0
159 while gen < EG_GENS {
160 // evaluate
161 let fit: *i64 = sys_mmap(8 * EG_POP) as *i64
162 var besti: i64 = 0
163 var bestf: i64 = 0 - 1
164 i = 0
165 while i < EG_POP {
166 let f: i64 = eg_fitness(taskbuf, tn, pop_op[i], pop_in[i])
167 fit[i] = f
168 if f > bestf { bestf = f; besti = i }
169 i = i + 1
170 }
171 if bestf == 1000 { bop[0] = pop_op[besti]; binit[0] = pop_in[besti]; return gen }
172 // next generation: elitism (keep best) + tournament-select + mutate
173 let nop: *i64 = sys_mmap(8 * EG_POP) as *i64
174 let nin: *i64 = sys_mmap(8 * EG_POP) as *i64
175 nop[0] = pop_op[besti]; nin[0] = pop_in[besti]
176 var j: i64 = 1
177 while j < EG_POP {
178 // tournament: best of K random
179 var wi: i64 = eg_modn(eg_rand(seed), EG_POP)
180 var wf: i64 = fit[wi]
181 var c: i64 = 1
182 while c < EG_TOURK { let ri: i64 = eg_modn(eg_rand(seed), EG_POP); if fit[ri] > wf { wf = fit[ri]; wi = ri } c = c + 1 }
183 var no: i64 = pop_op[wi]
184 var ni: i64 = pop_in[wi]
185 // mutate +-1 per gene (then mod 4)
186 if eg_modn(eg_rand(seed), 2) == 0 { no = eg_modn(no + 1, 4) } else { no = eg_modn(no + 3, 4) }
187 if eg_modn(eg_rand(seed), 2) == 0 { ni = eg_modn(ni + 1, 4) } else { ni = eg_modn(ni + 3, 4) }
188 nop[j] = no; nin[j] = ni
189 j = j + 1
190 }
191 i = 0
192 while i < EG_POP { pop_op[i] = nop[i]; pop_in[i] = nin[i]; i = i + 1 }
193 gen = gen + 1
194 }
195 return 0 - 1
196}
197
198func eg_opname(op: i64) -> *u8 { if op == 1 { return "mul" as *u8 } if op == 2 { return "max" as *u8 } if op == 3 { return "min" as *u8 } return "add" as *u8 }
199
200func main(argc: i64, argv: *i64) -> i64 {
201 if argc >= 2 {
202 let bop: *i64 = sys_mmap(16) as *i64
203 let bin: *i64 = sys_mmap(16) as *i64
204 let g: i64 = eg_evolve(argv[1] as *u8, bop, bin)
205 if g >= 0 {
206 eg_p("EVOLVE-GAP solved member=EVOLUTIONARY gene=reduce_op " as *u8); eg_p(eg_opname(bop[0])); eg_p(" " as *u8); eg_fn(1, bin[0]); eg_p(" generation=" as *u8); eg_fn(1, g); eg_p(" verdict=SOLVED\n" as *u8)
207 sys_exit(0); return 0
208 }
209 eg_p("EVOLVE-GAP UNSOLVED within budget -> escalate to LLM\n" as *u8)
210 sys_exit(1); return 1
211 }
212 eg_p("=== evolve-gap gate (EVOLUTIONARY member: evolve genes, fitness = harness score) ===\n" as *u8)
213 let bop: *i64 = sys_mmap(16) as *i64
214 let bin: *i64 = sys_mmap(16) as *i64
215 let g: i64 = eg_evolve("knowledge/specs/ale_examples/task_reduce.txt" as *u8, bop, bin)
216 var ok: i64 = 0
217 if g >= 0 { if bop[0] == 1 { if bin[0] == 1 { ok = 1 } } }
218 eg_p(" evolved gene=reduce_op " as *u8); eg_p(eg_opname(bop[0])); eg_p(" " as *u8); eg_fn(1, bin[0]); eg_p(" at gen=" as *u8); eg_fn(1, g); eg_p("\n" as *u8)
219 let lfd: i64 = sys_openat_append("knowledge/status/evolve_gap.log" as *u8, 0x1a4)
220 if ok == 1 {
221 eg_p("EVOLVEGAP-GATE verdict=GREEN member=EVOLUTIONARY solved_product_gap=mul,1 no_llm=1 rung=TEAM-SOLVE-TIER2\n" as *u8)
222 if lfd >= 0 { eg_fp(lfd, "EVOLVEGAP-GATE verdict=GREEN gene=mul,1 gen=" as *u8); eg_fn(lfd, g); eg_fp(lfd, " no_llm=1 epoch=" as *u8); eg_fn(lfd, sys_now_realtime_sec()); eg_fp(lfd, "\n" as *u8); sys_close(lfd) }
223 sys_exit(0); return 0
224 }
225 eg_p("EVOLVEGAP-GATE verdict=RED (did not discover the solving gene)\n" as *u8)
226 if lfd >= 0 { eg_fp(lfd, "EVOLVEGAP-GATE verdict=RED\n" as *u8); sys_close(lfd) }
227 sys_exit(1)
228 return 1
229}