(2) Valeri: 'similarity should solve the flat-family problem'. The similarity of two successive contraction ratios, min/max(rho_n, rho_n-1), was pre-declared as the detector; it FAILS and is inverted - AUC 0.28-0.42 flat against the rest, and 'the contraction did not speed up' fires more on APS (37.6%) than on the flat families (28.2%). The rho sequence shows why: on x^m the method runs a period-4 cycle - two Newton undershoots at exactly (1-1/m)^m (0.328 for m=5, 0.346 for m=9), one crossing, one nearly empty step (rho ~ 1) - so successive ratios are dissimilar, not constant. The safeguard is not the cause: the steps are as proposed. Candidate detectors suggested by the cycle are new hypotheses, not built. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
63 lines
2.3 KiB
Python
63 lines
2.3 KiB
Python
"""Why the contraction-ratio similarity came out inverted: the rho sequence itself.
|
|
|
|
diag_contraction_similarity.py falsified "successive contraction ratios are similar on
|
|
the flat families": they are LESS similar there than on the canonical set. The picture
|
|
behind the hypothesis - rho constant at about (1 - 1/m)^m - holds for pure Newton steps on
|
|
x^m. The explanation to check is that our safeguarded run is not pure: the projection
|
|
interleaves forced moves, so rho alternates. Printed per step for one flat problem and
|
|
one canonical problem: rho_n, and whether the step was the similarity step as proposed or
|
|
was changed by the safeguard (x_new != x + raw).
|
|
|
|
python -u diag_contraction_sequence.py
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from scipy.optimize._tstutils import _APS_TESTS_DICTS, _CHANDRUPATLA_TESTS_DICTS
|
|
|
|
from simroot.pure import pure_root
|
|
|
|
CFG = dict(similarity="ratio", scale="derived3", guard="project")
|
|
|
|
|
|
def show(name, f, a, b):
|
|
evals = []
|
|
|
|
def g(t):
|
|
v = f(t)
|
|
evals.append((t, v))
|
|
return v
|
|
st = {"trace": []}
|
|
pure_root(g, a, b, 1e-12, 200, stats=st, **CFG)
|
|
# map each traced state to the evaluation that followed it
|
|
order = [e[0] for e in evals]
|
|
print(f"\n== {name}: {len(evals)} evaluations")
|
|
print(f" {'k':>3} {'rho_n=|f_n/f_(n-1)|':>22} {'step as proposed?':>18}")
|
|
for k, s in enumerate(st["trace"][:40]):
|
|
proposed = s["x"] + s["raw"]
|
|
try:
|
|
i = order.index(s["x"])
|
|
except ValueError:
|
|
continue
|
|
if i + 1 >= len(evals):
|
|
break
|
|
x_next, f_next = evals[i + 1]
|
|
rho = abs(f_next / s["fx"]) if s["fx"] != 0.0 else float("nan")
|
|
kept = "yes" if x_next == proposed else "CHANGED"
|
|
print(f" {k:3d} {rho:22.3e} {kept:>18}")
|
|
|
|
|
|
def main():
|
|
cha = {str(d["ID"]): d for d in _CHANDRUPATLA_TESTS_DICTS}
|
|
d = cha["fun5.1"]
|
|
show("fun5.1 = x^9 (flat)", d["f"], *(float(v) for v in d["bracket"]))
|
|
d = cha["fun4.3"]
|
|
show("fun4.3 = 6(x-2)^5 on a wide bracket (flat)", d["f"],
|
|
*(float(v) for v in d["bracket"]))
|
|
d = _APS_TESTS_DICTS[10]
|
|
f = (lambda ff, aa: lambda t: ff(t, *aa))(d["f"], d.get("args", ()))
|
|
show(f"{d['ID']} (canonical)", f, *(float(v) for v in d["bracket"]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|