76 lines
2.8 KiB
Python
76 lines
2.8 KiB
Python
"""The largest single item of the wide-bracket gap: fun1's endgame (+61 evaluations).
|
|
|
|
If it has a structural cause, a derived fix may exist; if it is simply the order of
|
|
convergence, the answer is "no" and the reason is worth stating. Reports, per fun1 problem:
|
|
the bracket, the multiplicity-like behaviour of f near the root, the observed order of both
|
|
methods, and the endgame split.
|
|
|
|
python -u diag_fun1_endgame.py
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
from scipy.optimize._tstutils import _CHANDRUPATLA_TESTS_DICTS
|
|
|
|
from simroot.baselines import chandrupatla, chandrupatla_scipy
|
|
from simroot.pure import pure_root
|
|
from stage4_why import observed_order
|
|
from sweep_full import ACC, MAXFEV, XTOL
|
|
|
|
|
|
def ours(f, a, b, xtol, maxfev):
|
|
return pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived3",
|
|
guard="safe", prestep="slope", direction="dissimilar")
|
|
|
|
|
|
def multiplicity_probe(f, root):
|
|
"""How does |f| grow away from the root? |f(root+t)| ~ C t^m gives m from two points;
|
|
m = 1 is a simple root, m >= 2 flattens the endgame for every interpolating method."""
|
|
t1, t2 = 1e-5, 1e-4
|
|
f1, f2 = abs(f(root + t1)), abs(f(root + t2))
|
|
if f1 == 0.0 or f2 == 0.0:
|
|
return float("nan")
|
|
return math.log(f2 / f1) / math.log(t2 / t1)
|
|
|
|
|
|
def main():
|
|
print(f"{'problem':<9} {'bracket':>26} {'root':>10} {'m':>6} "
|
|
f"{'ours n':>7} {'ord':>6} {'CH n':>6} {'ord':>6}")
|
|
for d in _CHANDRUPATLA_TESTS_DICTS:
|
|
pid = str(d["ID"])
|
|
if not pid.startswith("fun1."):
|
|
continue
|
|
f = d["f"]
|
|
a, b = (float(v) for v in d["bracket"])
|
|
root = float(d["root"])
|
|
m = multiplicity_probe(f, root)
|
|
x_o, n_o, ok_o = ours(f, a, b, XTOL, MAXFEV)
|
|
best = None
|
|
for impl in (chandrupatla, chandrupatla_scipy):
|
|
try:
|
|
x_c, n_c, ok_c = impl(f, a, b, XTOL, MAXFEV)
|
|
except Exception:
|
|
continue
|
|
if best is None or n_c < best[1]:
|
|
best = (float(x_c), int(n_c), bool(ok_c))
|
|
try:
|
|
ord_o = observed_order(ours, f, a, b, root)
|
|
except Exception:
|
|
ord_o = float("nan")
|
|
try:
|
|
ord_c = observed_order(chandrupatla, f, a, b, root)
|
|
except Exception:
|
|
ord_c = float("nan")
|
|
print(f"{pid:<9} [{a:10.4g}, {b:10.4g}] {root:10.5g} {m:6.2f} "
|
|
f"{n_o:7d} {ord_o if isinstance(ord_o, float) else float('nan'):6.2f} "
|
|
f"{best[1]:6d} {ord_c if isinstance(ord_c, float) else float('nan'):6.2f}")
|
|
print(f" |f| at root+1e-5 = {abs(f(root + 1e-5)):.3e}, "
|
|
f"root+1e-2 = {abs(f(root + 1e-2)):.3e}, "
|
|
f"ours x={x_o:+.10g} ok={ok_o}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|