Impact, every sweep regenerated: the paper's key configurations are unchanged to the evaluation (proposed 2806/3220, credit 3568/3020, Chandrupatla, TOMS 748, Brent, bisection); 46 stated numbers move (ITP CHA 2857 -> 2896, ITP oracle 2611 -> 2647, record CHA figures by 14-18, the grid means by ~1%) and one finding weakens: the measured-order exponent of section 7.1 was cheaper in 29 of 60 far cells and 7 of 7 safeguards; with the fix 12 of 61 and 6 of 7, and on the wide-bracket set it now loses in every safeguard and drops 5 problems. PREREG G1-G3 outcome on the fixed code: G2 (repeating step pattern, period from the data) PASSES Y1-Y4 and is ACCEPTED by the stop rule - proposed rule APS 2806 -> 2782 (below Chandrupatla's 2787), CHA 3220 -> 3169, both 6026 -> 5951, per problem vs Chandrupatla on APS 95/20/38 p = 8e-7. G1 fails Y1/Y2 (its Y3 miss was the sign bug), G3 fails Y2, A fails Y2. Regression 887 pass; the two red tests are the paper-number check (awaiting the paper update) and test_blend (fixed since, copy in stage16). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
160 lines
6.6 KiB
Python
160 lines
6.6 KiB
Python
"""Stage 10 - checking the technical claims independently.
|
|
|
|
Five of them change the content of the paper rather than its wording, so none
|
|
is accepted on authority. Each is recomputed here from scratch.
|
|
|
|
A. The proposed similarity IS the one Table 1's last row calls degenerate,
|
|
and the degeneracy is specific to the CHOSEN scale.
|
|
B. Proposition 1 is true for the ratio form only, not for similarity rules
|
|
in general.
|
|
C. The bracket-endpoint divided difference plus the tent similarity is
|
|
regula falsi exactly - so the words "most recent" in the definition of
|
|
f-hat are load-bearing.
|
|
D. Table 1's c = 0 rows report a window artefact; the true behaviour is
|
|
sublinear, e_n ~ sigma^2 / (c2 f'(r)^2 |D| n).
|
|
E. The order of a Newton step with an O(h^2) derivative estimate is 2, not
|
|
the 1.84 the paper claims.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
|
|
|
import math
|
|
|
|
r2 = math.sqrt(2.0)
|
|
f = lambda x: x * x - 2.0
|
|
|
|
TENT = lambda z: max(0.0, 1.0 - abs(z))
|
|
RATIO = lambda z: 1.0 / (1.0 + abs(z))
|
|
RAT_SQ = lambda z: 1.0 / (1.0 + z * z)
|
|
EXP_SQ = lambda z: math.exp(-z * z)
|
|
COSINE = lambda z: 1.0 / math.sqrt(1.0 + z * z)
|
|
|
|
|
|
def iterate(S, n, sigma=2.0, x0=0.0, xfar=2.0):
|
|
x, errs = x0, []
|
|
for _ in range(n):
|
|
x = x + (1.0 - S(f(x) / sigma)) * (xfar - x)
|
|
errs.append(abs(x - r2))
|
|
return errs
|
|
|
|
|
|
def main():
|
|
print("=" * 76)
|
|
print("A. the tent similarity under the CHOSEN scale")
|
|
print("=" * 76)
|
|
e = iterate(TENT, 200)
|
|
print(f" z at x=0 is {f(0.0) / 2.0:+.1f}, so S = {TENT(f(0.0) / 2.0):.1f} "
|
|
f"and the step is the whole bracket")
|
|
print(f" |e| after 1 step: {e[0]:.4f} after 200: {e[-1]:.4f} "
|
|
f"{'CAPTURED at the far end' if abs(e[0] - e[-1]) < 1e-15 else 'moves'}")
|
|
print(" => the paper proposes, in section 3, the function its own")
|
|
print(" Table 1 calls degenerate. CONFIRMED.")
|
|
|
|
print("\n but under the DERIVED scale the clip never engages:")
|
|
# replay the proposed configuration and record how often |f|/sigma >= 1
|
|
from simroot.pure import _slope3
|
|
clipped = total = 0
|
|
a, b = 0.0, 2.0
|
|
fa, fb = f(a), f(b)
|
|
A, FA, B = a, fa, b
|
|
x, fx, xp, fp = a, fa, b, fb
|
|
xp2 = fp2 = None
|
|
for _ in range(40):
|
|
if abs(B - A) <= 1e-12:
|
|
break
|
|
far = B if abs(B - x) >= abs(A - x) else A
|
|
slope = _slope3(x, fx, xp, fp, xp2, fp2)
|
|
sc = abs(slope) * abs(far - x)
|
|
if sc == 0.0:
|
|
break
|
|
z = abs(fx) / sc
|
|
total += 1
|
|
clipped += z >= 1.0
|
|
xn = x + min(1.0, z) * (far - x)
|
|
lo, hi = min(A, B), max(A, B)
|
|
if not (lo < xn < hi):
|
|
xn = 0.5 * (A + B)
|
|
fn = f(xn)
|
|
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, xn, fn
|
|
if _opposite(FA, fn):
|
|
B = xn
|
|
else:
|
|
A, FA = xn, fn
|
|
print(f" steps {total}, of which clipped at z>=1: {clipped}")
|
|
|
|
print("\n" + "=" * 76)
|
|
print("B/C. Proposition 1: which similarity reproduces regula falsi?")
|
|
print("=" * 76)
|
|
a, b = 1.0, 4.0
|
|
fa, fb = f(a), f(b)
|
|
falsi = (a * fb - b * fa) / (fb - fa)
|
|
print(f" regula falsi point on [1,4]: {falsi:.6f}\n")
|
|
print(f" {'similarity':14s}{'scale = |f(x_far)|':>22s}{'match':>8s}")
|
|
print(" " + "-" * 44)
|
|
for name, S in (("1/(1+|z|)", RATIO), ("exp(-|z|)", lambda z: math.exp(-abs(z))),
|
|
("1/(1+z^2)", RAT_SQ), ("1/sqrt(1+z^2)", COSINE),
|
|
("tent", TENT)):
|
|
pt = a + (1.0 - S(f(a) / abs(fb))) * (b - a)
|
|
print(f" {name:14s}{pt:>22.6f}{'YES' if abs(pt - falsi) < 1e-12 else 'no':>8s}")
|
|
print("\n => the identity holds for the ratio form only. The paper's")
|
|
print(" conclusion 'a similarity rule whose scale is taken from the")
|
|
print(" bracket is not a new method' is too broad. CONFIRMED.")
|
|
|
|
sigma = abs((fb - fa) / (b - a)) * abs(b - a)
|
|
pt = a + min(1.0, abs(fa) / sigma) * (b - a)
|
|
print(f"\n tent + divided difference over the BRACKET ENDS: {pt!r}")
|
|
print(f" equals regula falsi exactly: {pt == falsi}")
|
|
print(" => 'most recent' in the definition of f-hat is load-bearing:")
|
|
print(" ends give regula falsi, recent iterates give the secant.")
|
|
|
|
print("\n" + "=" * 76)
|
|
print("D. Table 1, the c = 0 rows")
|
|
print("=" * 76)
|
|
print(f" {'n':>6s}" + "".join(f"{s:>14s}" for s in
|
|
("1/(1+z^2)", "exp(-z^2)", "1/sqrt(1+z^2)")))
|
|
print(" " + "-" * 48)
|
|
seqs = {n: iterate(S, 4001) for n, S in
|
|
(("1/(1+z^2)", RAT_SQ), ("exp(-z^2)", EXP_SQ),
|
|
("1/sqrt(1+z^2)", COSINE))}
|
|
for n in (5, 10, 15, 40, 100, 1000, 4000):
|
|
row = "".join(f"{seqs[k][n] / seqs[k][n - 1]:>14.4f}" for k in seqs)
|
|
print(f" {n:>6d}{row}")
|
|
print("\n the ratio creeps to 1 - there is no rate to measure, and the")
|
|
print(" paper's 0.9357 / 0.9444 / 0.9327 are the value at n ~ 10-15.")
|
|
print("\n the real law: 1 - S = c2 z^2 + O(z^4) gives")
|
|
print(" e_{n+1} = e_n - c2 f'(r)^2 |D| e_n^2 / sigma^2 + ...")
|
|
print(" => e_n ~ sigma^2 / (c2 f'(r)^2 |D|) . 1/n")
|
|
fp, D, sig = 2.0 * r2, 2.0 - r2, 2.0
|
|
# c2 is measured, not transcribed from a Taylor expansion done by hand:
|
|
# a verification script carrying my own derived constant would be checking
|
|
# my arithmetic against itself.
|
|
for name, S in (("1/(1+z^2)", RAT_SQ), ("exp(-z^2)", EXP_SQ),
|
|
("1/sqrt(1+z^2)", COSINE)):
|
|
h = 1e-4
|
|
c2 = (1.0 - S(h)) / (h * h)
|
|
pred = sig * sig / (c2 * fp * fp * D)
|
|
meas = 4000 * seqs[name][4000]
|
|
print(f" {name:14s} predicted n.e_n -> {pred:7.4f} "
|
|
f"measured at n=4000: {meas:7.4f}")
|
|
|
|
print("\n" + "=" * 76)
|
|
print("E. the order of the three-point rule")
|
|
print("=" * 76)
|
|
print(" Newton with a derivative estimate of error O(h^2):")
|
|
print(" e' = e - f/f-hat = e - (e - c e^2 + ...)(1 + O(e^2)) = c e^2")
|
|
print(" so the order is 2, not the 1.84 of Muller's method, which uses")
|
|
print(" the quadratic's ROOT rather than its DERIVATIVE.")
|
|
from simroot.pure import pure_root
|
|
from stage5_three_point import PROBLEMS, order_of
|
|
ps = [order_of(lambda f_, a_, b_, xt, mx: pure_root(
|
|
f_, a_, b_, 1e-12, 200, scale="derived3", guard="project"),
|
|
fn, aa, bb, rr) for _n, fn, aa, bb, rr in PROBLEMS]
|
|
ps = [p for p in ps if math.isfinite(p) and 0.5 < p < 5.0]
|
|
print(f" measured median over the eight problems: "
|
|
f"{sorted(ps)[len(ps) // 2]:.3f} predicted: 2")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|