alstrup commited on
Commit
c1fcf09
·
verified ·
1 Parent(s): 25ff745

cleanup submission: composed_encoding.py

Browse files
Files changed (1) hide show
  1. composed_encoding.py +46 -6
composed_encoding.py CHANGED
@@ -37,11 +37,14 @@ AMARK, BMARK, DIVMARK, EQ, ACC, NMARK, REVMARK, NL = "A", "B", "M", "=", "a", "N
37
  PLSB = "m"
38
 
39
 
40
- def prompt_str(x: int, y: int, p: int, W: int, base: int, subpad: bool = False) -> str:
 
41
  """subpad adds p LSB-first to the prompt: the MSB field serves quotient
42
  estimation, the LSB field aligns with the LSB-emitted qd*p / remainder
43
  chains (per-step diagnostic: subtraction digits need REVERSED access into
44
  the MSB-only field — the aligned acc stage learned, the division didn't)."""
 
 
45
  s = (AMARK + limb_str(x, W, base) + BMARK + limb_str(y, W, base)
46
  + DIVMARK + limb_str(p, W, base, msb_first=True))
47
  if subpad:
@@ -52,7 +55,8 @@ def prompt_str(x: int, y: int, p: int, W: int, base: int, subpad: bool = False)
52
  def gen_len(W: int, scratch: bool = False, cursor: bool = False,
53
  subpad: bool = False, stepidx: bool = False,
54
  skiptriv: bool = False, subnum: bool = False,
55
- bemit: bool = False, srt: bool = False) -> int:
 
56
  """Tokens generated after '=': W acc blocks, N restage, quotient, answer.
57
  scratch=True: each quotient limb is followed by the running remainder
58
  (W limbs, LSB-first) — externalizes the division state, which the model
@@ -100,6 +104,8 @@ def gen_len(W: int, scratch: bool = False, cursor: bool = False,
100
  rem errors were 58% unstructured noise, 0.54 even at b=0 -- the
101
  install-only borrow supervision never built a circuit; emit the chain
102
  (the scratch lesson, applied to the borrow state)."""
 
 
103
  restage = 1 + (3 if stepidx else 1) * 2 * W
104
  pcopy = (1 + W) if skiptriv else 0
105
  if srt:
@@ -144,8 +150,9 @@ def _srt_qd(num: int, p: int, base: int) -> int:
144
  def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = False,
145
  cursor: bool = False, subpad: bool = False, stepidx: bool = False,
146
  skiptriv: bool = False, subnum: bool = False,
147
- bemit: bool = False, srt: bool = False):
148
- """Return (text, ann). x,y < p < base**W."""
 
149
  assert not subnum or subpad, "subnum requires subpad"
150
  assert not bemit or subnum, "bemit requires subnum"
151
  assert not srt or (skiptriv and bemit), "srt requires skiptriv+bemit"
@@ -178,6 +185,22 @@ def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = Fal
178
  pos += 2 * W
179
  assert acc == N
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  n_msb = to_limbs(N, 2 * W, base, msb_first=True)
182
  if stepidx: # restage as (index, limb) pairs
183
  parts.append(NMARK + "".join(f"{i:02d}" + limb_char(n_msb[i])
@@ -212,6 +235,18 @@ def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = Fal
212
  parts.append("".join(limb_char(v) for v in num_c))
213
  pos += K
214
  qd = _srt_qd(num, p, base)
 
 
 
 
 
 
 
 
 
 
 
 
215
  assert abs(num - qd * p) < p, (x, y, p, i, num, qd)
216
  ann_g.append((pos, "qhat", qd + base - 1)) # 19-class signed label
217
  parts.append(chr(0x90 + base - 1 + qd))
@@ -331,7 +366,9 @@ def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = Fal
331
 
332
 
333
  def var_specs(W: int, base: int, scratch: bool = False, subpad: bool = False,
334
- srt: bool = False):
 
 
335
  specs = [("ans", base), ("qhat", 2 * base - 1 if srt else base),
336
  ("acarry", base)]
337
  if subpad: # multiply-carry + subtract-borrow chains
@@ -345,7 +382,10 @@ def decode_answer(gen_chars: str, W: int, base: int, scratch: bool = False,
345
  cursor: bool = False, subpad: bool = False,
346
  stepidx: bool = False, skiptriv: bool = False,
347
  subnum: bool = False, bemit: bool = False,
348
- srt: bool = False) -> int:
 
 
 
349
  # the answer block after the R-mark is W plain limbs in every mode
350
  off = gen_len(W, scratch, cursor, subpad, stepidx, skiptriv, subnum, bemit,
351
  srt) - W
 
37
  PLSB = "m"
38
 
39
 
40
+ def prompt_str(x: int, y: int, p: int, W: int, base: int, subpad: bool = False,
41
+ mulonly: bool = False) -> str:
42
  """subpad adds p LSB-first to the prompt: the MSB field serves quotient
43
  estimation, the LSB field aligns with the LSB-emitted qd*p / remainder
44
  chains (per-step diagnostic: subtraction digits need REVERSED access into
45
  the MSB-only field — the aligned acc stage learned, the division didn't)."""
46
+ if mulonly: # tier 0: pure multiplication
47
+ return AMARK + limb_str(x, W, base) + BMARK + limb_str(y, W, base) + EQ
48
  s = (AMARK + limb_str(x, W, base) + BMARK + limb_str(y, W, base)
49
  + DIVMARK + limb_str(p, W, base, msb_first=True))
50
  if subpad:
 
55
  def gen_len(W: int, scratch: bool = False, cursor: bool = False,
56
  subpad: bool = False, stepidx: bool = False,
57
  skiptriv: bool = False, subnum: bool = False,
58
+ bemit: bool = False, srt: bool = False,
59
+ mulonly: bool = False) -> int:
60
  """Tokens generated after '=': W acc blocks, N restage, quotient, answer.
61
  scratch=True: each quotient limb is followed by the running remainder
62
  (W limbs, LSB-first) — externalizes the division state, which the model
 
104
  rem errors were 58% unstructured noise, 0.54 even at b=0 -- the
105
  install-only borrow supervision never built a circuit; emit the chain
106
  (the scratch lesson, applied to the borrow state)."""
107
+ if mulonly: # acc rows + answer copy
108
+ return W * (1 + 2 * W) + 1 + 2 * W
109
  restage = 1 + (3 if stepidx else 1) * 2 * W
110
  pcopy = (1 + W) if skiptriv else 0
111
  if srt:
 
150
  def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = False,
151
  cursor: bool = False, subpad: bool = False, stepidx: bool = False,
152
  skiptriv: bool = False, subnum: bool = False,
153
+ bemit: bool = False, srt: bool = False, mulonly: bool = False,
154
+ srt_dither: float = 0.0):
155
+ """Return (text, ann). x,y < p < base**W (mulonly: x,y < base**W)."""
156
  assert not subnum or subpad, "subnum requires subpad"
157
  assert not bemit or subnum, "bemit requires subnum"
158
  assert not srt or (skiptriv and bemit), "srt requires skiptriv+bemit"
 
185
  pos += 2 * W
186
  assert acc == N
187
 
188
+ if mulonly: # tier 0: answer = N itself
189
+ parts.append(NMARK)
190
+ pos += 1
191
+ n_l = to_limbs(N, 2 * W, base)
192
+ for k in range(2 * W):
193
+ ann_g.append((pos + k, "ans", n_l[k]))
194
+ parts.append(limb_str(N, 2 * W, base) + NL)
195
+ pos += 2 * W + 1
196
+ prompt = prompt_str(x, y, p, W, base, mulonly=True)
197
+ text = prompt + "".join(parts)
198
+ assert len(text) == len(prompt) + gen_len(W, mulonly=True) + 1
199
+ ann = [dict() for _ in range(len(text))]
200
+ for gi, var, val in ann_g:
201
+ ann[len(prompt) + gi - 1][var] = int(val)
202
+ return text, ann
203
+
204
  n_msb = to_limbs(N, 2 * W, base, msb_first=True)
205
  if stepidx: # restage as (index, limb) pairs
206
  parts.append(NMARK + "".join(f"{i:02d}" + limb_char(n_msb[i])
 
235
  parts.append("".join(limb_char(v) for v in num_c))
236
  pos += K
237
  qd = _srt_qd(num, p, base)
238
+ if srt_dither:
239
+ # Deterministic pseudo-random alternate-digit training: SRT's
240
+ # redundancy makes qd+-1 often equally valid, but the model
241
+ # only ever saw label-digit continuations -- free-running it
242
+ # sometimes picks the OTHER valid digit and must continue
243
+ # consistently from its own choice. Dithered traces teach
244
+ # exactly those continuations. (hash-derived: reproducible)
245
+ h = hash((x, y, p, i)) & 0xFFFF
246
+ if h < int(srt_dither * 0x10000):
247
+ alt = qd + (1 if h & 1 else -1)
248
+ if abs(alt) <= base - 1 and abs(num - alt * p) < p:
249
+ qd = alt
250
  assert abs(num - qd * p) < p, (x, y, p, i, num, qd)
251
  ann_g.append((pos, "qhat", qd + base - 1)) # 19-class signed label
252
  parts.append(chr(0x90 + base - 1 + qd))
 
366
 
367
 
368
  def var_specs(W: int, base: int, scratch: bool = False, subpad: bool = False,
369
+ srt: bool = False, mulonly: bool = False):
370
+ if mulonly: # tier 0: multiply only
371
+ return [("ans", base), ("acarry", base)]
372
  specs = [("ans", base), ("qhat", 2 * base - 1 if srt else base),
373
  ("acarry", base)]
374
  if subpad: # multiply-carry + subtract-borrow chains
 
382
  cursor: bool = False, subpad: bool = False,
383
  stepidx: bool = False, skiptriv: bool = False,
384
  subnum: bool = False, bemit: bool = False,
385
+ srt: bool = False, mulonly: bool = False) -> int:
386
+ if mulonly: # answer = 2W limbs after 'N'
387
+ off = gen_len(W, mulonly=True) - 2 * W
388
+ return parse_limbs(gen_chars[off:off + 2 * W], base)
389
  # the answer block after the R-mark is W plain limbs in every mode
390
  off = gen_len(W, scratch, cursor, subpad, stepidx, skiptriv, subnum, bemit,
391
  srt) - W