"""Does the canonical Alefeld-Potra-Shi set carry the same scoring artefact as fun7? On the wide-bracket set five problems are scored unsolved for every method although every method returns a point where f(x) = 0 exactly (diag_rescore_cha.py). Every method also reports 153 of 154 on the canonical set, so exactly one problem there is unsolved by everyone — this asks whether that is the same artefact, a different one, or a real failure. Both criteria are applied to the SAME runs: strict : |x - declared_root| <= ACC (the harness rule) honest : strict OR f(x) == 0 (a root is a root) and every problem that the two criteria disagree about is printed with its diagnosis. python -u diag_rescore_aps.py """ from __future__ import annotations import math from simroot.baselines import BRENT_BASELINE, CHANDRUPATLA_BASELINE from simroot.baselines import (best_of, bisection, brent, brent_scipy, chandrupatla, chandrupatla_scipy, itp, toms748) from simroot.pure import pure_root from sweep_full import ACC, MAXFEV, XTOL, load_problems METHODS = { "ours (shape)": lambda f, a, b: pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3", guard="safe", prestep="slope", points="shape"), "ours (dissimilar)": lambda f, a, b: pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3", guard="safe", prestep="slope", direction="dissimilar"), "ours (published proj)": lambda f, a, b: pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3", guard="project"), "chandrupatla": lambda f, a, b: CHANDRUPATLA_BASELINE(f, a, b, XTOL, MAXFEV), "toms748": lambda f, a, b: toms748(f, a, b, XTOL, MAXFEV), "brent": lambda f, a, b: BRENT_BASELINE(f, a, b, XTOL, MAXFEV), "itp": lambda f, a, b: itp(f, a, b, XTOL, MAXFEV), "bisection": lambda f, a, b: bisection(f, a, b, XTOL, MAXFEV), } TINY = 2.2250738585072014e-308 # smallest normal double, for reporting only def main(): probs = [p for p in load_problems() if p[0] == "APS"] print(f"APS problems: {len(probs)}") print(f"\n{'method':<22} {'strict solved/total':>22} {'honest solved/total':>22} " f"{'disagreements':>14}") disagree = {} never_strict = {pid: 0 for _s, pid, *_ in probs} for name, run in METHODS.items(): s_solved = s_total = h_solved = h_total = 0 diffs = [] for _s, pid, f, a, b, root in probs: try: x, n, conv = run(f, a, b) except Exception: x, n, conv = float("nan"), MAXFEV, False x = float(x) n = int(n) fin = conv and math.isfinite(x) strict = bool(fin and abs(x - root) <= ACC) honest = bool(strict or (fin and f(x) == 0.0)) s_total += n if strict else MAXFEV h_total += n if honest else MAXFEV s_solved += int(strict) h_solved += int(honest) never_strict[pid] += int(strict) if honest != strict: diffs.append((pid, x, root, f(x), n)) disagree[name] = diffs print(f"{name:<22} {s_solved:8d}/154 {s_total:8d} {h_solved:8d}/154 {h_total:8d} " f"{len(diffs):14d}") print("\nproblems where the two criteria disagree (a root found, scored a failure):") any_diff = False for name, diffs in disagree.items(): for pid, x, root, fx, n in diffs: any_diff = True print(f" {name:<22} {pid:<12} x={x:+.10g} root={root:+.10g} " f"f(x)={fx:+.3e} after {n} evals") if not any_diff: print(" none — the canonical set does NOT carry the fun7 artefact") print("\nproblems no method solved under the strict rule:") for pid, cnt in sorted(never_strict.items(), key=lambda kv: kv[1])[:6]: print(f" {pid:<12} solved by {cnt} of {len(METHODS)} methods") # inspect the hardest one in the same way fun7 was inspected worst = min(never_strict, key=lambda k: never_strict[k]) for _s, pid, f, a, b, root in probs: if pid != worst: continue print(f"\ndiagnosis of {pid}: bracket [{a:.6g}, {b:.6g}] declared root {root:.10g}") print(f" f(a)={f(a):+.6e} f(b)={f(b):+.6e} f(root)={f(root):+.6e}") for t in (1e-12, 1e-9, 1e-6, 1e-3): print(f" f(root+{t:g}) = {f(root + t):+.6e} f(root-{t:g}) = {f(root - t):+.6e}") x, n, conv = METHODS["ours (dissimilar)"](f, a, b) print(f" ours returns x={float(x):+.12g} after {n} evals, f(x)={f(float(x)):+.3e}, " f"|x-root|={abs(float(x) - root):.3g}") print(f" |f(x)| below smallest normal? {abs(f(float(x))) < TINY}") if __name__ == "__main__": main()