Why the analogy entry is late on the flat families (diagnostics only, method unchanged). At flag moments before entry: unlike-past 118, no-memory 7, m<2 2 - the order is not the bottleneck. The period-4 cycle: the flag rises in the phases whose configuration does NOT recur (the undershoot whose relative step shrinks every cycle, and the crossing); the recurring phases have the flag down and read the true order (fun4 = 6(x-2)^5: m ~ 4.9). The entry demands both at the same state. Remembering the analogy until the next flag: flat entry state 12.9 -> 8.2; problems entered APS 3 -> 8, fun9 0 -> 1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
|||||||
|
"""Consequence check for diag_analogy_sequence.py: the flag rises in the phases of the
|
||||||
|
period-4 cycle whose configuration does NOT recur (the undershoot whose relative step
|
||||||
|
shrinks every cycle, the crossing), while the recurring phases are the ones with the flag
|
||||||
|
down. The entry demands both AT THE SAME STATE, so it waits until a flag state happens
|
||||||
|
to recur.
|
||||||
|
|
||||||
|
Candidate (not in the method): the analogy is a property of the RUN, the flag of the
|
||||||
|
MOMENT - once any state has been analogous to its past with m >= 2, enter at the next
|
||||||
|
flag. Per problem, on traces of the proposed rule with NO regime (so both rules see the
|
||||||
|
same states): the state of entry under 'same state' and under 'analogy remembered', and
|
||||||
|
how many problems would enter at all, per group. Nothing in the method changes.
|
||||||
|
|
||||||
|
python -u diag_analogy_decoupled.py
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
from simroot.pure import _analogous_and_steep, _config3, pure_root
|
||||||
|
from sweep_full import MAXFEV, XTOL, load_problems
|
||||||
|
|
||||||
|
FLAT = ("fun3", "fun4", "fun5", "fun6")
|
||||||
|
|
||||||
|
|
||||||
|
def entries(trace):
|
||||||
|
past, seen = [], False
|
||||||
|
same = remembered = None
|
||||||
|
for k, s in enumerate(trace):
|
||||||
|
cur = _config3(s["x"], s["fx"], s["xp"], s["fp"], s["xp2"], s["fp2"])
|
||||||
|
flag = s["fp"] != 0.0 and s["fx"] / s["fp"] >= 0.25
|
||||||
|
ana = _analogous_and_steep(cur, past)
|
||||||
|
if flag and ana and same is None:
|
||||||
|
same = k
|
||||||
|
if flag and (seen or ana) and remembered is None:
|
||||||
|
remembered = k
|
||||||
|
seen = seen or ana
|
||||||
|
if cur is not None:
|
||||||
|
past.append(cur)
|
||||||
|
return same, remembered
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
per = defaultdict(lambda: [0, 0, 0, 0, 0]) # problems, same, remembered, sum same, sum rem
|
||||||
|
for s, pid, f, a, b, _root in load_problems():
|
||||||
|
st = {"trace": []}
|
||||||
|
pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3",
|
||||||
|
guard="project", stats=st)
|
||||||
|
fam = pid.split(".")[0]
|
||||||
|
g = "APS" if s == "APS" else ("CHA-flat" if fam in FLAT else f"CHA-{fam}")
|
||||||
|
same, rem = entries(st["trace"])
|
||||||
|
p = per[g]
|
||||||
|
p[0] += 1
|
||||||
|
p[1] += same is not None
|
||||||
|
p[2] += rem is not None
|
||||||
|
if g == "CHA-flat" and same is not None and rem is not None:
|
||||||
|
p[3] += same
|
||||||
|
p[4] += rem
|
||||||
|
print(f"{'group':<10} {'problems':>8} {'enter: same state':>18} {'analogy remembered':>19}")
|
||||||
|
for g in sorted(per):
|
||||||
|
n, a_, b_, s1, s2 = per[g]
|
||||||
|
print(f"{g:<10} {n:8d} {a_:18d} {b_:19d}")
|
||||||
|
fl = per["CHA-flat"]
|
||||||
|
print(f"\nflat: mean entry state {fl[3] / fl[1]:.1f} (same state) -> "
|
||||||
|
f"{fl[4] / fl[1]:.1f} (analogy remembered)")
|
||||||
|
print("diag done")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
"""Why does the analogy entry come late on the flat families? (Valeri, 2026-09-21)
|
||||||
|
|
||||||
|
The entry is flag AND _analogous_and_steep(cur, memory). The method calls the second
|
||||||
|
only when the flag has risen on a model step (short-circuit `and`), so a spy on it sees
|
||||||
|
exactly the flag moments. At each one it records how many evaluations of f were spent
|
||||||
|
and which condition held back the entry:
|
||||||
|
no-config the last three points give no (xi, phi)
|
||||||
|
no-memory nothing to compare with yet
|
||||||
|
unlike-past the configuration is nearer to the line than to any past one
|
||||||
|
m<2 analogous, but the pair's similarity exponent is below 2 (value kept)
|
||||||
|
ENTER
|
||||||
|
Compared with flatstickexit, which enters at the first flag. Nothing in the method
|
||||||
|
changes; problems are the 20 flat CHA problems (fun3-6), proposed rule (projection).
|
||||||
|
|
||||||
|
python -u diag_analogy_late.py
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
from collections import Counter as Tally
|
||||||
|
|
||||||
|
import simroot.pure as P
|
||||||
|
from sweep_full import MAXFEV, XTOL, load_problems
|
||||||
|
|
||||||
|
FLAT = ("fun3", "fun4", "fun5", "fun6")
|
||||||
|
_orig = P._analogous_and_steep
|
||||||
|
LOG = []
|
||||||
|
CALLS = [0]
|
||||||
|
|
||||||
|
|
||||||
|
def reason(cur, past):
|
||||||
|
if cur is None:
|
||||||
|
return "no-config", None
|
||||||
|
if not past:
|
||||||
|
return "no-memory", None
|
||||||
|
xi, phi = cur[0], cur[1]
|
||||||
|
best = min(past, key=lambda q: math.hypot(xi - q[0], phi - q[1]))
|
||||||
|
d_past = math.hypot(xi - best[0], phi - best[1])
|
||||||
|
d_line = abs(phi - xi) / math.sqrt(2.0)
|
||||||
|
if not d_past < d_line:
|
||||||
|
return "unlike-past", (d_past, d_line)
|
||||||
|
lx, lf = cur[2] / best[2], cur[3] / best[3]
|
||||||
|
m = math.log(lf) / math.log(lx) if lx not in (0.0, 1.0) and lf > 0.0 else math.nan
|
||||||
|
return ("ENTER" if m >= 2.0 else "m<2"), m
|
||||||
|
|
||||||
|
|
||||||
|
def spy(cur, past):
|
||||||
|
ok = _orig(cur, past)
|
||||||
|
why, val = reason(cur, past)
|
||||||
|
LOG.append((CALLS[0], why, val, len(past), ok))
|
||||||
|
return ok
|
||||||
|
|
||||||
|
|
||||||
|
def counted(f):
|
||||||
|
def g(x):
|
||||||
|
CALLS[0] += 1
|
||||||
|
return f(x)
|
||||||
|
return g
|
||||||
|
|
||||||
|
|
||||||
|
def run(f, a, b, gate):
|
||||||
|
st = {}
|
||||||
|
CALLS[0] = 0
|
||||||
|
_x, n, _ok = P.pure_root(counted(f), a, b, XTOL, MAXFEV, similarity="ratio",
|
||||||
|
scale="derived3", guard="project", prestep=gate, stats=st)
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
P._analogous_and_steep = spy
|
||||||
|
tally = Tally()
|
||||||
|
ms_before = []
|
||||||
|
print(f"{'problem':<10} {'exit: n':>7} {'analog: n':>9} {'first flag @':>12} "
|
||||||
|
f"{'entry @':>8} reasons before entry")
|
||||||
|
for s, pid, f, a, b, _root in load_problems():
|
||||||
|
if s != "CHA" or pid.split(".")[0] not in FLAT:
|
||||||
|
continue
|
||||||
|
n_exit = run(f, a, b, "flatstickexit")
|
||||||
|
LOG.clear()
|
||||||
|
n_an = run(f, a, b, "flatanalog")
|
||||||
|
first = LOG[0][0] if LOG else None
|
||||||
|
entry = next((e for e, why, *_ in LOG if why == "ENTER"), None)
|
||||||
|
before = [(why, val) for e, why, val, _, _ in LOG if entry is None or e < entry]
|
||||||
|
for why, val in before:
|
||||||
|
tally[why] += 1
|
||||||
|
if why == "m<2" and val is not None and math.isfinite(val):
|
||||||
|
ms_before.append(val)
|
||||||
|
print(f"{pid:<10} {n_exit:7d} {n_an:9d} {str(first):>12} {str(entry):>8} "
|
||||||
|
+ " ".join(why for why, _ in before))
|
||||||
|
print("\nreasons at flag moments before entry, all 20 problems:", dict(tally))
|
||||||
|
if ms_before:
|
||||||
|
ms = sorted(ms_before)
|
||||||
|
print("m read at analogous-but-refused moments:",
|
||||||
|
" ".join(f"{m:.2f}" for m in ms))
|
||||||
|
print("diag done")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
"""The state-by-state picture behind diag_analogy_late.py, for a few flat problems.
|
||||||
|
|
||||||
|
Every state the gate sees (trace hook, flatanalog, projection), in order:
|
||||||
|
n evaluations spent (the trace does not carry it; states are numbered instead)
|
||||||
|
flag r = f/f_prev >= 1/4 (the promise failed, sign kept)
|
||||||
|
xi, phi the configuration
|
||||||
|
ratio d_past / d_line (< 1 means analogous to the nearest past configuration)
|
||||||
|
lag how many states back that nearest past configuration is
|
||||||
|
m the pair's similarity exponent
|
||||||
|
Nothing in the method changes.
|
||||||
|
|
||||||
|
python -u diag_analogy_sequence.py fun6.3 fun4.1 fun3.4
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from simroot.pure import _config3, pure_root
|
||||||
|
from sweep_full import MAXFEV, XTOL, load_problems
|
||||||
|
|
||||||
|
|
||||||
|
def show(pid, f, a, b):
|
||||||
|
st = {"trace": []}
|
||||||
|
pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3", guard="project",
|
||||||
|
prestep="flatanalog", stats=st)
|
||||||
|
print(f"\n== {pid} (state, flag, xi, phi, d_past/d_line, lag, m)")
|
||||||
|
past = []
|
||||||
|
for k, s in enumerate(st["trace"][:30]):
|
||||||
|
cur = _config3(s["x"], s["fx"], s["xp"], s["fp"], s["xp2"], s["fp2"])
|
||||||
|
flag = s["fp"] != 0.0 and s["fx"] / s["fp"] >= 0.25
|
||||||
|
if cur is None:
|
||||||
|
print(f" {k:3d} {'F' if flag else '.'} (no configuration)")
|
||||||
|
continue
|
||||||
|
line = abs(cur[1] - cur[0]) / math.sqrt(2.0)
|
||||||
|
if past:
|
||||||
|
j = min(range(len(past)), key=lambda i: math.hypot(cur[0] - past[i][0],
|
||||||
|
cur[1] - past[i][1]))
|
||||||
|
q = past[j]
|
||||||
|
ratio = math.hypot(cur[0] - q[0], cur[1] - q[1]) / line if line > 0 else math.inf
|
||||||
|
lx, lf = cur[2] / q[2], cur[3] / q[3]
|
||||||
|
m = (math.log(lf) / math.log(lx)) if lx not in (0.0, 1.0) and lf > 0 else math.nan
|
||||||
|
lag = len(past) - j
|
||||||
|
print(f" {k:3d} {'F' if flag else '.'} xi {cur[0]:+9.4f} phi {cur[1]:+10.4f} "
|
||||||
|
f"ratio {ratio:7.3f} lag {lag:2d} m {m:6.2f}")
|
||||||
|
else:
|
||||||
|
print(f" {k:3d} {'F' if flag else '.'} xi {cur[0]:+9.4f} phi {cur[1]:+10.4f} (no memory)")
|
||||||
|
past.append(cur)
|
||||||
|
|
||||||
|
|
||||||
|
def main(ids):
|
||||||
|
for s, pid, f, a, b, _root in load_problems():
|
||||||
|
if s == "CHA" and pid in ids:
|
||||||
|
show(pid, f, a, b)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(sys.argv[1:] or ["fun6.3", "fun4.1"])
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
problem exit: n analog: n first flag @ entry @ reasons before entry
|
||||||
|
fun3.1 46 49 4 11 unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun3.2 48 53 4 16 unlike-past unlike-past unlike-past
|
||||||
|
fun3.3 58 71 4 17 unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun3.4 64 82 4 22 unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun3.5 77 76 6 12 unlike-past unlike-past unlike-past
|
||||||
|
fun4.1 46 60 4 18 unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun4.2 48 62 4 18 unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun4.3 58 68 4 14 unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun4.4 65 68 6 13 m<2 unlike-past unlike-past
|
||||||
|
fun4.5 78 82 6 13 m<2 unlike-past unlike-past
|
||||||
|
fun5.1 46 49 3 9 no-memory unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun5.2 46 50 3 9 no-memory unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun5.3 47 50 3 9 no-memory unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun5.4 49 52 3 9 no-memory unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun5.5 50 53 3 9 no-memory unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun6.1 39 58 3 18 no-memory unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun6.2 46 59 3 16 no-memory unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun6.3 47 63 4 22 unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun6.4 49 66 4 22 unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
fun6.5 50 67 4 22 unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past unlike-past
|
||||||
|
|
||||||
|
reasons at flag moments before entry, all 20 problems: {'unlike-past': 118, 'm<2': 2, 'no-memory': 7}
|
||||||
|
m read at analogous-but-refused moments: 0.92 0.92
|
||||||
|
diag done
|
||||||
|
group problems enter: same state analogy remembered
|
||||||
|
APS 154 3 8
|
||||||
|
CHA-flat 20 20 20
|
||||||
|
CHA-fun1 5 1 1
|
||||||
|
CHA-fun2 5 0 0
|
||||||
|
CHA-fun7 5 3 3
|
||||||
|
CHA-fun8 5 0 0
|
||||||
|
CHA-fun9 5 0 1
|
||||||
|
|
||||||
|
flat: mean entry state 12.9 (same state) -> 8.2 (analogy remembered)
|
||||||
|
diag done
|
||||||
Reference in New Issue
Block a user