Sign tests by product underflowed: FIXED everywhere (branch, not master - the paper is not yet updated). FA * fnew < 0.0 with FA ~ -1e-200, fnew ~ 1e-150 is -0.0 and '-0.0 < 0.0' is False, so on flat functions (x^19) the bracket update moved the wrong end, the root left the bracket and the run still reported convergence - the proposed rule returned 4.9e-9, bisection 3.5e-9, ITP 1.6e-8 with a claimed 1e-12 bracket; the 1e-6 harness scored them solved. Same defect in our bisection, false-position family, Ridders, Brent, ITP and twelve copies in stage scripts, simroot/sim.py and one test; all replaced by _opposite / _same_sign, pinned by test_sign_underflow.
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>
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
"""Verdicts Y1-Y6 of PREREG_extrapolation_gates_2026-09-21.md from sweep_extrap2.json,
|
||||||
|
plus the check that mode 'steps' (A) reproduces sweep_extrap.json bit for bit.
|
||||||
|
|
||||||
|
python -u analyze_extrap2.py
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
|
||||||
|
from analyze_extrap import FAMILY, FLAT, fam_sum, h2h, load, sign_p
|
||||||
|
|
||||||
|
MODES = ("none", "steps", "confirmed", "pattern", "steps+results")
|
||||||
|
NAME = {"none": "no lengthening", "steps": "A", "confirmed": "G1 confirmed",
|
||||||
|
"pattern": "G2 pattern", "steps+results": "G3 steps+results"}
|
||||||
|
|
||||||
|
|
||||||
|
def key(r):
|
||||||
|
s = r["spec"]
|
||||||
|
return (s[1], s[2], s[3], s[5], s[6], s[7])
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
rows = load("sweep_extrap2.json")
|
||||||
|
old = {r["label"]: r for r in load("sweep_extrap.json")}
|
||||||
|
cha = {r["label"]: r for r in load("sweep_full.json")}["chandrupatla"]
|
||||||
|
cells = {}
|
||||||
|
for r in rows:
|
||||||
|
cells.setdefault(key(r), {})[r["spec"][9]] = r
|
||||||
|
# A reproduces its own earlier sweep?
|
||||||
|
same = diff = 0
|
||||||
|
for r in rows:
|
||||||
|
if r["spec"][9] in ("none", "steps") and r["label"] in old:
|
||||||
|
o = old[r["label"]]
|
||||||
|
if o["APS"]["per"] == r["APS"]["per"] and o["CHA"]["per"] == r["CHA"]["per"]:
|
||||||
|
same += 1
|
||||||
|
else:
|
||||||
|
diff += 1
|
||||||
|
print(f"A and no-lengthening cells identical to sweep_extrap.json: {same} same, {diff} differ\n")
|
||||||
|
|
||||||
|
prop = cells[("ratio", "derived3", "project", "none", "recent", "distance")]
|
||||||
|
base = prop["none"]
|
||||||
|
print("PROPOSED RULE (tent, 3-point, projection), by mode:")
|
||||||
|
print(f" {'mode':<18} {'APS':>5} {'CHA':>5} {'both':>5} {'flat':>5} Y1 Y2 Y3 Y4 "
|
||||||
|
f"vs Chandrupatla APS (w/t/l, p)")
|
||||||
|
for m in MODES:
|
||||||
|
r = prop[m]
|
||||||
|
fam = [c[m] for k, c in cells.items() if k[2] in FAMILY]
|
||||||
|
viol = sum(x["APS"]["over"] + x["CHA"]["over"] for x in fam)
|
||||||
|
low = sum(1 for x in fam if x["APS"]["solved"] + x["CHA"]["solved"] < 193)
|
||||||
|
y1 = r["CHA"]["total"] < 3220
|
||||||
|
y2 = r["APS"]["total"] <= 2806
|
||||||
|
y3 = viol == 0 and low == 0
|
||||||
|
y4 = fam_sum(r, FLAT) < fam_sum(base, FLAT)
|
||||||
|
w, t, l = h2h(r, cha, "APS")
|
||||||
|
mark = lambda b: "✓" if b else "✗" # noqa: E731
|
||||||
|
print(f" {NAME[m]:<18} {r['APS']['total']:5d} {r['CHA']['total']:5d} "
|
||||||
|
f"{r['APS']['total'] + r['CHA']['total']:5d} {fam_sum(r, FLAT):5d} "
|
||||||
|
f"{mark(y1) if m != 'none' else '-':>2} {mark(y2) if m != 'none' else '-':>2} "
|
||||||
|
f"{mark(y3):>2} {mark(y4) if m != 'none' else '-':>2} {w}/{t}/{l} p={sign_p(w, l):.2g}"
|
||||||
|
+ (" ACCEPTED" if m != "none" and y1 and y2 and y3 else ""))
|
||||||
|
print("\nY6 best cell over both sets, per mode (guarantee family, >= 193 solved):")
|
||||||
|
for m in MODES:
|
||||||
|
cand = [c[m] for k, c in cells.items() if k[2] in FAMILY
|
||||||
|
and c[m]["APS"]["solved"] + c[m]["CHA"]["solved"] >= 193]
|
||||||
|
b = min(cand, key=lambda x: x["APS"]["total"] + x["CHA"]["total"])
|
||||||
|
print(f" {NAME[m]:<18} {b['label']:<52} {b['APS']['total']}+{b['CHA']['total']}="
|
||||||
|
f"{b['APS']['total'] + b['CHA']['total']}")
|
||||||
|
print("\nreadings under the projection, APS/CHA by mode:")
|
||||||
|
for rd, k in (("slope", ("slope", "recent", "distance")),
|
||||||
|
("shape+slope", ("slope", "shape", "distance")),
|
||||||
|
("dissim+slope", ("slope", "recent", "dissimilar")),
|
||||||
|
("defect", ("defect", "recent", "distance"))):
|
||||||
|
c = cells[("ratio", "derived3", "project") + k]
|
||||||
|
print(f" {rd:<13} " + " ".join(f"{NAME[m].split()[0]} {c[m]['APS']['total']}/"
|
||||||
|
f"{c[m]['CHA']['total']}" for m in MODES))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
A and no-lengthening cells identical to sweep_extrap.json: 182 same, 0 differ
|
||||||
|
|
||||||
|
PROPOSED RULE (tent, 3-point, projection), by mode:
|
||||||
|
mode APS CHA both flat Y1 Y2 Y3 Y4 vs Chandrupatla APS (w/t/l, p)
|
||||||
|
no lengthening 2806 3220 6026 1823 - - ✓ - 87/24/42 p=9.2e-05
|
||||||
|
A 2967 2926 5893 1525 ✓ ✗ ✓ ✓ 42/62/49 p=0.53
|
||||||
|
G1 confirmed 2933 3281 6214 1859 ✗ ✗ ✓ ✗ 81/28/44 p=0.0012
|
||||||
|
G2 pattern 2782 3169 5951 1780 ✓ ✓ ✓ ✓ 95/20/38 p=8.2e-07 ACCEPTED
|
||||||
|
G3 steps+results 2953 3205 6158 1804 ✓ ✗ ✓ ✓ 79/28/46 p=0.004
|
||||||
|
|
||||||
|
Y6 best cell over both sets, per mode (guarantee family, >= 193 solved):
|
||||||
|
no lengthening pure+dissim+slope.ratio.derived3.project 2726+2799=5525
|
||||||
|
A pure+dissim+ext+slope.ratio.derived3.project 2859+2553=5412
|
||||||
|
G1 confirmed pure+dissim+extC+slope.ratio.derived3.project 2882+2757=5639
|
||||||
|
G2 pattern pure+dissim+extP+slope.ratio.derived3.project 2759+2789=5548
|
||||||
|
G3 steps+results pure+dissim+extR+slope.ratio.derived3.project 2808+2785=5593
|
||||||
|
|
||||||
|
readings under the projection, APS/CHA by mode:
|
||||||
|
slope no 2848/3114 A 2971/2763 G1 3004/2993 G2 2809/3033 G3 2934/3043
|
||||||
|
shape+slope no 2675/3498 A 2930/3506 G1 2800/3511 G2 2894/3483 G3 2944/3477
|
||||||
|
dissim+slope no 2726/2799 A 2859/2553 G1 2882/2757 G2 2759/2789 G3 2808/2785
|
||||||
|
defect no 2523/3210 A 3180/2955 G1 2667/3260 G2 2580/3183 G3 2684/3210
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
CHANGED pure.ratio.derived3.step CHA: total 3460 -> 3524, solved 40 -> 40, over2x 10 -> 15
|
||||||
|
CHANGED pure.ratio.start.both CHA: total 3631 -> 3626, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio.start.project CHA: total 5029 -> 5024, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.bracket.both CHA: total 3315 -> 3335, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.bracket.bracket CHA: total 3321 -> 3341, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.bracket.credit CHA: total 3130 -> 3129, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.bracket.project CHA: total 4763 -> 4763, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.bracket.safe CHA: total 3998 -> 4059, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.bracket.step CHA: total 4004 -> 4065, solved 40 -> 40, over2x 2 -> 2
|
||||||
|
CHANGED pure.ratio_soft.derived.both CHA: total 3308 -> 3358, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.derived.bracket CHA: total 3167 -> 3235, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.derived.credit CHA: total 3094 -> 3094, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.derived.safe CHA: total 3643 -> 3695, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.derived.step CHA: total 3704 -> 3756, solved 40 -> 40, over2x 8 -> 8
|
||||||
|
CHANGED pure.ratio_soft.derived3.both CHA: total 3370 -> 3435, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.derived3.bracket CHA: total 3513 -> 3581, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.derived3.none CHA: total 4285 -> 4248, solved 35 -> 35, over2x 5 -> 5
|
||||||
|
CHANGED pure.ratio_soft.derived3.safe CHA: total 3681 -> 3741, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.derived3.step CHA: total 3724 -> 3819, solved 40 -> 40, over2x 5 -> 10
|
||||||
|
CHANGED pure.ratio_soft.start.both CHA: total 3508 -> 3508, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.ratio_soft.start.project CHA: total 4954 -> 4949, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.bracket.both CHA: total 3314 -> 3323, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.bracket.bracket CHA: total 3433 -> 3440, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.bracket.credit CHA: total 3040 -> 3039, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.bracket.project CHA: total 4676 -> 4671, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.bracket.safe CHA: total 3835 -> 3829, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.bracket.step CHA: total 3841 -> 3835, solved 40 -> 40, over2x 3 -> 3
|
||||||
|
CHANGED pure.rational.derived.both CHA: total 3674 -> 3715, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.derived.bracket CHA: total 3766 -> 3821, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.derived.safe CHA: total 3557 -> 3637, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.derived.step CHA: total 3618 -> 3698, solved 40 -> 40, over2x 10 -> 10
|
||||||
|
CHANGED pure.rational.derived3.both CHA: total 3815 -> 3873, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.derived3.bracket CHA: total 3994 -> 4052, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.derived3.safe CHA: total 3505 -> 3538, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.rational.derived3.step CHA: total 3618 -> 3698, solved 40 -> 40, over2x 9 -> 13
|
||||||
|
CHANGED pure.rational.start.project CHA: total 4762 -> 4758, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.bracket.both CHA: total 3391 -> 3431, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.bracket.bracket CHA: total 3387 -> 3443, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.bracket.safe CHA: total 3989 -> 4038, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.bracket.step CHA: total 4017 -> 4066, solved 40 -> 40, over2x 1 -> 1
|
||||||
|
CHANGED pure.sqrt.derived.both CHA: total 3870 -> 3908, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived.bracket CHA: total 4102 -> 4162, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived.none CHA: total 3511 -> 3538, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived.project CHA: total 3511 -> 3538, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived.safe CHA: total 3493 -> 3520, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived.step CHA: total 3493 -> 3525, solved 40 -> 40, over2x 0 -> 1
|
||||||
|
CHANGED pure.sqrt.derived3.both CHA: total 3737 -> 3781, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived3.bracket CHA: total 3859 -> 3904, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived3.credit CHA: total 3130 -> 3130, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived3.none CHA: total 3852 -> 3883, solved 40 -> 40, over2x 4 -> 4
|
||||||
|
CHANGED pure.sqrt.derived3.project CHA: total 3642 -> 3649, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived3.safe CHA: total 3891 -> 3928, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.derived3.step CHA: total 3924 -> 4039, solved 40 -> 40, over2x 5 -> 10
|
||||||
|
CHANGED pure.sqrt.start.both CHA: total 3829 -> 3829, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.start.credit CHA: total 3130 -> 3130, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.start.project CHA: total 5120 -> 5115, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.start.safe CHA: total 4395 -> 4395, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED pure.sqrt.start.step CHA: total 4396 -> 4396, solved 40 -> 40, over2x 0 -> 0
|
||||||
|
CHANGED ridders CHA: total 4216 -> 3768, solved 36 -> 40, over2x 0 -> 0
|
||||||
|
unexpected changes: 168
|
||||||
|
rows changed: APS 5 of 264, CHA 163 of 264
|
||||||
|
label APS old->new CHA old->new solved
|
||||||
|
pure.ratio.derived3.project 2806->2806 3220->3220 193->193
|
||||||
|
pure.ratio.derived3.credit 3568->3568 3020->3020 193->193
|
||||||
|
pure.ratio.derived3.none 2806->2806 4104->4104 188->188
|
||||||
|
pure.ratio.derived3.safe 3036->3036 3363->3390 193->193
|
||||||
|
chandrupatla 2787->2787 2441->2441 193->193
|
||||||
|
toms748 2820->2820 4000->4000 193->193
|
||||||
|
brent 2889->2889 4115->4115 191->191
|
||||||
|
bisection 7530->7530 3090->3090 193->193
|
||||||
|
itp 3957->3957 2857->2896 193->193
|
||||||
|
itp_oracle 3260->3260 2611->2647 193->193
|
||||||
|
ridders 3313->3313 4216->3768 189->193
|
||||||
|
illinois 7045->7045 6234->6234 176->176
|
||||||
|
regula_falsi 10560->10560 8239->8239 133->133
|
||||||
|
pure.sqrt.bracket.project 7796->7796 4516->4516 194->194
|
||||||
|
pure.exp_abs.bracket.both 3461->3461 2733->2736 193->193
|
||||||
|
proposed rule, CHA problems changed: {}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
OK number of configurations got 264 want 264
|
||||||
|
|
||||||
|
The proposed method (projection, multiplier declared):
|
||||||
|
OK APS place got 3 want 3
|
||||||
|
OK APS total got 2806 want 2806
|
||||||
|
OK APS solved got 153 want 153
|
||||||
|
BAD CHA place got 45 want 47
|
||||||
|
OK CHA total got 3220 want 3220
|
||||||
|
OK CHA solved got 40 want 40
|
||||||
|
OK both sets got 6026 want 6026
|
||||||
|
|
||||||
|
Head to head of the proposed method:
|
||||||
|
OK APS vs chandrupatla got (87, 24, 42) want (87, 24, 42)
|
||||||
|
OK APS vs toms748 got (86, 16, 51) want (86, 16, 51)
|
||||||
|
OK APS vs brent got (102, 11, 40) want (102, 11, 40)
|
||||||
|
OK APS vs itp got (132, 3, 18) want (132, 3, 18)
|
||||||
|
OK APS vs itp_oracle got (121, 4, 28) want (121, 4, 28)
|
||||||
|
OK APS vs bisection got (152, 1, 0) want (152, 1, 0)
|
||||||
|
OK CHA vs chandrupatla got (9, 5, 26) want (9, 5, 26)
|
||||||
|
OK CHA vs toms748 got (31, 1, 8) want (31, 1, 8)
|
||||||
|
OK CHA vs brent got (30, 4, 4) want (30, 4, 4)
|
||||||
|
OK CHA vs itp got (17, 0, 23) want (17, 0, 23)
|
||||||
|
OK CHA vs itp_oracle got (16, 0, 24) want (16, 0, 24)
|
||||||
|
OK APS vs Chandrupatla sign test p < 1e-4 got True want True
|
||||||
|
OK CHA vs Chandrupatla sign test p (rounded) got 0.006 want 0.006
|
||||||
|
|
||||||
|
The constant-free variant (earned projection):
|
||||||
|
OK credit APS place got 29 want 29
|
||||||
|
OK credit APS total got 3568 want 3568
|
||||||
|
OK credit CHA place got 10 want 10
|
||||||
|
OK credit CHA total got 3020 want 3020
|
||||||
|
OK credit both sets got 6588 want 6588
|
||||||
|
OK credit costs 762 more on the canonical set got 762 want 762
|
||||||
|
OK credit APS vs chandrupatla got (79, 3, 71) want (79, 3, 71)
|
||||||
|
OK credit APS vs toms748 got (77, 9, 67) want (77, 9, 67)
|
||||||
|
OK credit APS vs brent got (78, 5, 70) want (78, 5, 70)
|
||||||
|
OK credit APS vs Chandrupatla sign test p (rounded) got 0.57 want 0.57
|
||||||
|
|
||||||
|
The guards that replace the step instead of projecting it:
|
||||||
|
OK APS unguarded got 2806 want 2806
|
||||||
|
OK CHA unguarded total got 4104 want 4104
|
||||||
|
OK CHA unguarded solved got 35 want 35
|
||||||
|
OK CHA unguarded bound violations got 10 want 10
|
||||||
|
OK APS bracket-guard got 7260 want 7260
|
||||||
|
OK APS both-guard got 7239 want 7239
|
||||||
|
|
||||||
|
Alefeld-Potra-Shi:
|
||||||
|
OK APS winner got 'chandrupatla' want 'chandrupatla'
|
||||||
|
OK APS chandrupatla place got 1 want 1
|
||||||
|
OK APS chandrupatla total got 2787 want 2787
|
||||||
|
OK APS toms748 place got 4 want 4
|
||||||
|
OK APS toms748 total got 2820 want 2820
|
||||||
|
OK APS brent place got 5 want 5
|
||||||
|
OK APS brent total got 2889 want 2889
|
||||||
|
OK APS dekker place got 12 want 12
|
||||||
|
OK APS dekker total got 3158 want 3158
|
||||||
|
OK APS itp_oracle place got 13 want 13
|
||||||
|
OK APS itp_oracle total got 3260 want 3260
|
||||||
|
OK APS ridders place got 20 want 20
|
||||||
|
OK APS ridders total got 3313 want 3313
|
||||||
|
OK APS itp place got 34 want 34
|
||||||
|
OK APS itp total got 3957 want 3957
|
||||||
|
OK APS illinois place got 73 want 73
|
||||||
|
OK APS illinois total got 7045 want 7045
|
||||||
|
OK APS bisection place got 79 want 79
|
||||||
|
OK APS bisection total got 7530 want 7530
|
||||||
|
OK APS regula_falsi place got 244 want 244
|
||||||
|
OK APS regula_falsi total got 10560 want 10560
|
||||||
|
OK APS regula falsi solved got 127 want 127
|
||||||
|
|
||||||
|
Chandrupatla:
|
||||||
|
OK CHA rank 1 label got 'pure.sqrt.bracket.project' want 'pure.sqrt.bracket.project'
|
||||||
|
OK CHA rank 1 solves one more than anyone else got 41 want 41
|
||||||
|
OK CHA chandrupatla place got 2 want 2
|
||||||
|
OK CHA chandrupatla total got 2441 want 2441
|
||||||
|
OK CHA itp_oracle place got 3 want 3
|
||||||
|
BAD CHA itp_oracle total got 2647 want 2611
|
||||||
|
OK CHA itp place got 6 want 6
|
||||||
|
BAD CHA itp total got 2896 want 2857
|
||||||
|
OK CHA bisection place got 16 want 16
|
||||||
|
OK CHA bisection total got 3090 want 3090
|
||||||
|
BAD CHA toms748 place got 159 want 164
|
||||||
|
OK CHA toms748 total got 4000 want 4000
|
||||||
|
BAD CHA brent place got 227 want 226
|
||||||
|
OK CHA brent total got 4115 want 4115
|
||||||
|
OK CHA brent solved got 38 want 38
|
||||||
|
OK chandrupatla, both sets got 5228 want 5228
|
||||||
|
OK Chandrupatla beats us on both sets got True want True
|
||||||
|
|
||||||
|
Negative results, the regime claims:
|
||||||
|
BAD CHA cbrt over the whole set got 4109 want 4099
|
||||||
|
OK single fixed choice, both sets got 6026 want 6026
|
||||||
|
BAD switch by benchmark set, both sets got 6915 want 6905
|
||||||
|
OK switching is worse than not switching got True want True
|
||||||
|
OK fun4.1 projection variant got 89 want 89
|
||||||
|
OK fun4.1 cbrt got 32 want 32
|
||||||
|
OK fun4.2 projection variant got 93 want 93
|
||||||
|
OK fun4.2 cbrt got 32 want 32
|
||||||
|
OK fun4.3 projection variant got 113 want 113
|
||||||
|
OK fun4.3 cbrt got 40 want 40
|
||||||
|
OK fun4.4 projection variant got 125 want 125
|
||||||
|
OK fun4.4 cbrt got 47 want 47
|
||||||
|
OK fun4.5 projection variant got 153 want 153
|
||||||
|
OK fun4.5 cbrt got 59 want 59
|
||||||
|
|
||||||
|
The law across the grid:
|
||||||
|
BAD mean total, scale=derived3, lin got 6893 want 6809
|
||||||
|
BAD mean total, scale=derived3, quad got 22315 want 22294
|
||||||
|
BAD mean total, scale=derived, lin got 6981 want 6906
|
||||||
|
BAD mean total, scale=derived, quad got 22206 want 22167
|
||||||
|
BAD mean total, scale=bracket, lin got 10279 want 10263
|
||||||
|
BAD mean total, scale=bracket, quad got 19127 want 19137
|
||||||
|
OK mean total, scale=start, lin got 16102 want 16102
|
||||||
|
OK mean total, scale=start, quad got 15345 want 15345
|
||||||
|
OK every c=1 similarity beats every c=0 similarity got True want True
|
||||||
|
OK similarity ranking got ['ratio', 'exp_abs', 'rational', 'ratio_soft', 'sqrt', 'cbrt', 'exp_sq', 'rat_sq', 'cosine'] want ['ratio', 'exp_abs', 'rational', 'ratio_soft', 'sqrt', 'cbrt', 'exp_sq', 'rat_sq', 'cosine']
|
||||||
|
BAD similarity ratio best got 6560 want 6496
|
||||||
|
BAD similarity exp_abs best got 6895 want 6822
|
||||||
|
BAD similarity rational best got 7118 want 7038
|
||||||
|
BAD similarity ratio_soft best got 9578 want 9502
|
||||||
|
BAD similarity sqrt best got 10546 want 10497
|
||||||
|
BAD similarity cbrt best got 12002 want 11941
|
||||||
|
BAD similarity exp_sq best got 14307 want 14314
|
||||||
|
OK similarity rat_sq best got 15102 want 15102
|
||||||
|
OK similarity cosine best got 16394 want 16394
|
||||||
|
OK scale ranking got ['derived3', 'derived', 'bracket', 'start'] want ['derived3', 'derived', 'bracket', 'start']
|
||||||
|
BAD scale derived3 best got 6560 want 6496
|
||||||
|
BAD scale derived best got 6702 want 6628
|
||||||
|
BAD scale bracket best got 9107 want 9081
|
||||||
|
OK scale start best got 14540 want 14540
|
||||||
|
|
||||||
|
The placement modes (each in its own sweep file):
|
||||||
|
OK slope.ratio.derived3.project APS got 2848 want 2848
|
||||||
|
BAD slope.ratio.derived3.project CHA got 3114 want 3074
|
||||||
|
OK slope.ratio.derived3.project solved got 193 want 193
|
||||||
|
OK slope.ratio.derived3.project guarantee (over 2x) got 0 want 0
|
||||||
|
OK pure+shape+slope.ratio.derived3.safe APS got 2527 want 2527
|
||||||
|
BAD pure+shape+slope.ratio.derived3.safe CHA got 3126 want 3108
|
||||||
|
OK pure+shape+slope.ratio.derived3.safe solved got 193 want 193
|
||||||
|
OK pure+shape+slope.ratio.derived3.safe guarantee (over 2x) got 0 want 0
|
||||||
|
OK pure+dissim+slope.ratio.derived3.project APS got 2726 want 2726
|
||||||
|
BAD pure+dissim+slope.ratio.derived3.project CHA got 2799 want 2785
|
||||||
|
OK pure+dissim+slope.ratio.derived3.project solved got 193 want 193
|
||||||
|
OK pure+dissim+slope.ratio.derived3.project guarantee (over 2x) got 0 want 0
|
||||||
|
OK pure+shape+dissim+slope.ratio.derived3.safe APS got 2884 want 2884
|
||||||
|
BAD pure+shape+dissim+slope.ratio.derived3.safe CHA got 2871 want 2859
|
||||||
|
OK pure+shape+dissim+slope.ratio.derived3.safe solved got 193 want 193
|
||||||
|
OK pure+shape+dissim+slope.ratio.derived3.safe guarantee (over 2x) got 0 want 0
|
||||||
|
!! gate.ratio.derived.project not in sweep_gate.json — stale sweep
|
||||||
|
OK log.ratio_soft.derived.safe APS got 6940 want 6940
|
||||||
|
BAD log.ratio_soft.derived.safe CHA got 3541 want 3474
|
||||||
|
OK log.ratio_soft.derived.safe solved got 193 want 193
|
||||||
|
OK log.ratio_soft.derived.safe guarantee (over 2x) got 0 want 0
|
||||||
|
BAD pure+dissim+slope.ratio.derived3.safe CHA per-set got 2695 want 2683
|
||||||
|
|
||||||
|
The per-place reading (sweep_order.json):
|
||||||
|
OK far+rational both APS m=1 got 4522 want 4522
|
||||||
|
OK far+rational both APS order got 3675 want 3675
|
||||||
|
BAD far+rational both CHA m=1 got 3406 want 3387
|
||||||
|
BAD far+rational both CHA order got 3906 want 3216
|
||||||
|
OK far+rational bracket APS m=1 got 4606 want 4606
|
||||||
|
OK far+rational bracket APS order got 3542 want 3542
|
||||||
|
BAD far+rational bracket CHA m=1 got 3602 want 3571
|
||||||
|
BAD far+rational bracket CHA order got 3950 want 3303
|
||||||
|
OK far+rational credit APS m=1 got 5190 want 5190
|
||||||
|
OK far+rational credit APS order got 4686 want 4686
|
||||||
|
OK far+rational credit CHA m=1 got 3013 want 3013
|
||||||
|
BAD far+rational credit CHA order got 3646 want 2884
|
||||||
|
OK far+rational project APS m=1 got 6932 want 6932
|
||||||
|
OK far+rational project APS order got 6364 want 6364
|
||||||
|
BAD far+rational project CHA m=1 got 4789 want 4794
|
||||||
|
BAD far+rational project CHA order got 5098 want 4559
|
||||||
|
OK far+rational safe APS m=1 got 5987 want 5987
|
||||||
|
OK far+rational safe APS order got 5229 want 5229
|
||||||
|
BAD far+rational safe CHA m=1 got 4134 want 4108
|
||||||
|
BAD far+rational safe CHA order got 4503 want 3923
|
||||||
|
OK far+rational step APS m=1 got 6435 want 6435
|
||||||
|
OK far+rational step APS order got 5551 want 5551
|
||||||
|
BAD far+rational step CHA m=1 got 4287 want 4257
|
||||||
|
BAD far+rational step CHA order got 4602 want 4022
|
||||||
|
OK far+rational none APS m=1 got 10676 want 10676
|
||||||
|
OK far+rational none APS order got 10043 want 10043
|
||||||
|
OK far+rational none CHA m=1 got 8265 want 8265
|
||||||
|
OK far+rational none CHA order got 7794 want 7794
|
||||||
|
BAD cheaper in 7 of 7 safeguards got 6 want 7
|
||||||
|
OK false position none solved got 127 want 127
|
||||||
|
OK false position none APS got 10676 want 10676
|
||||||
|
OK false position order solved got 128 want 128
|
||||||
|
OK false position order APS got 10043 want 10043
|
||||||
|
OK slope reading none APS got 2806 want 2806
|
||||||
|
OK slope reading order APS got 2854 want 2854
|
||||||
|
OK guarantee family violations got 0 want 0
|
||||||
|
|
||||||
|
The decision place (sweep_decision.json):
|
||||||
|
OK ratio.band.project APS got 5432 want 5432
|
||||||
|
BAD ratio.band.project CHA got 3059 want 3066
|
||||||
|
BAD ratio.band.credit CHA got 2892 want 2899
|
||||||
|
OK ratio.none.project APS got 2806 want 2806
|
||||||
|
OK ratio.defect.project APS got 2523 want 2523
|
||||||
|
OK ratio.defect.project CHA got 3210 want 3210
|
||||||
|
BAD ratio_soft.simpair.project CHA got 2897 want 2868
|
||||||
|
OK defect APS solved got 153 want 153
|
||||||
|
OK defect both sets got 5733 want 5733
|
||||||
|
OK defect is the new canonical best (< 2527) got True want True
|
||||||
|
OK decision grid guarantee violations got 0 want 0
|
||||||
|
BAD band refusal rate % got 63.5 want 63.6
|
||||||
|
BAD defect refusal rate % got 6.6 want 7.0
|
||||||
|
|
||||||
|
The gap decomposition (fresh runs of the diagnosis scripts):
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/valeri/sim-numerics/verify_article.py", line 558, in <module>
|
||||||
|
main()
|
||||||
|
File "/home/valeri/sim-numerics/verify_article.py", line 220, in main
|
||||||
|
verify_gap_decomposition()
|
||||||
|
File "/home/valeri/sim-numerics/verify_article.py", line 388, in verify_gap_decomposition
|
||||||
|
fl = diag_flat_detectable.main()
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/valeri/sim-numerics/diag_flat_detectable.py", line 54, in main
|
||||||
|
groups[key] += states(d["f"], a, b, float(d["root"]))
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/valeri/sim-numerics/diag_flat_detectable.py", line 40, in states
|
||||||
|
out.append(_local_order(s["x"], s["fx"], s["xp"], s["fp"], s["xp2"], s["fp2"]))
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/valeri/sim-numerics/simroot/pure.py", line 592, in _local_order
|
||||||
|
theta = f2 * fpp / (fp * fp)
|
||||||
|
~~~~~~~~~^~~~~~~~~~~
|
||||||
|
ZeroDivisionError: float division by zero
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Regenerate EVERY sweep file after a change to the method or the baselines
|
||||||
|
# (2026-09-21: sign tests by product underflowed; fixed in pure.py and baselines.py).
|
||||||
|
# Frozen runner: detached, logged, explicit end marker.
|
||||||
|
export OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 MKL_NUM_THREADS=1
|
||||||
|
cd "$HOME/sim-numerics" || exit 1
|
||||||
|
for flag in "" --log --gate --slope --cap --combo --points --direction --order \
|
||||||
|
--decision --extrap --extrap2; do
|
||||||
|
echo "=== sweep ${flag:-(full)} ==="
|
||||||
|
~/torchenv/bin/python -u sweep_full.py $flag 2>&1 | grep -E "^sweep:|wrote|Traceback|Error|FAILED"
|
||||||
|
done
|
||||||
|
echo "=== SWEEPS DONE ==="
|
||||||
+21
-6
@@ -47,6 +47,21 @@ class _Budget(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _opposite(u, v):
|
||||||
|
"""True when u and v have strictly opposite signs. NOT u * v < 0: for the tiny
|
||||||
|
values of a flat function near its root (x^19 there is ~1e-200) the product
|
||||||
|
underflows to -0.0, '-0.0 < 0.0' is False, and a bracket update then moves the
|
||||||
|
wrong end and loses the root while still reporting convergence (found 2026-09-21
|
||||||
|
on fun6.5, x^19 over [-10, 100])."""
|
||||||
|
return (u < 0.0 < v) or (v < 0.0 < u)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_sign(u, v):
|
||||||
|
"""True when u and v are both strictly positive or both strictly negative; see
|
||||||
|
_opposite for why this is not u * v > 0."""
|
||||||
|
return (u > 0.0 and v > 0.0) or (u < 0.0 and v < 0.0)
|
||||||
|
|
||||||
|
|
||||||
def _converged(a, b, xtol):
|
def _converged(a, b, xtol):
|
||||||
return abs(b - a) <= xtol
|
return abs(b - a) <= xtol
|
||||||
|
|
||||||
@@ -68,7 +83,7 @@ def bisection(f, a, b, xtol, maxfev):
|
|||||||
fx = g(x)
|
fx = g(x)
|
||||||
if fx == 0.0:
|
if fx == 0.0:
|
||||||
return x, g.n, True
|
return x, g.n, True
|
||||||
if fa * fx < 0.0:
|
if _opposite(fa, fx):
|
||||||
b, fb = x, fx
|
b, fb = x, fx
|
||||||
else:
|
else:
|
||||||
a, fa = x, fx
|
a, fa = x, fx
|
||||||
@@ -104,7 +119,7 @@ def _false_position_family(f, a, b, xtol, maxfev, correction):
|
|||||||
fx = g(x)
|
fx = g(x)
|
||||||
if fx == 0.0:
|
if fx == 0.0:
|
||||||
return x, g.n, True
|
return x, g.n, True
|
||||||
if fa * fx < 0.0:
|
if _opposite(fa, fx):
|
||||||
# b replaced; a became stale -> correct fa
|
# b replaced; a became stale -> correct fa
|
||||||
fa = correction(fa, fb, fx)
|
fa = correction(fa, fb, fx)
|
||||||
b, fb = x, fx
|
b, fb = x, fx
|
||||||
@@ -170,9 +185,9 @@ def ridders(f, a, b, xtol, maxfev):
|
|||||||
if fx == 0.0:
|
if fx == 0.0:
|
||||||
return x, g.n, True
|
return x, g.n, True
|
||||||
# rebuild the tightest bracket among a, c, x, b
|
# rebuild the tightest bracket among a, c, x, b
|
||||||
if fc * fx < 0.0:
|
if _opposite(fc, fx):
|
||||||
a, fa, b, fb = (c, fc, x, fx) if c < x else (x, fx, c, fc)
|
a, fa, b, fb = (c, fc, x, fx) if c < x else (x, fx, c, fc)
|
||||||
elif fa * fx < 0.0:
|
elif _opposite(fa, fx):
|
||||||
b, fb = x, fx
|
b, fb = x, fx
|
||||||
else:
|
else:
|
||||||
a, fa = x, fx
|
a, fa = x, fx
|
||||||
@@ -202,7 +217,7 @@ def brent(f, a, b, xtol, maxfev, stats=None):
|
|||||||
c, fc = a, fa
|
c, fc = a, fa
|
||||||
d = e = b - a
|
d = e = b - a
|
||||||
while True:
|
while True:
|
||||||
if fb * fc > 0.0:
|
if _same_sign(fb, fc):
|
||||||
c, fc = a, fa
|
c, fc = a, fa
|
||||||
d = e = b - a
|
d = e = b - a
|
||||||
if abs(fc) < abs(fb):
|
if abs(fc) < abs(fb):
|
||||||
@@ -305,7 +320,7 @@ def itp(f, a, b, xtol, maxfev, kappa1=None, kappa2=2.0, n0=1):
|
|||||||
fx = g(x)
|
fx = g(x)
|
||||||
if fx == 0.0:
|
if fx == 0.0:
|
||||||
return x, g.n, True
|
return x, g.n, True
|
||||||
if fx * fa < 0.0:
|
if _opposite(fx, fa):
|
||||||
b, fb = x, fx
|
b, fb = x, fx
|
||||||
else:
|
else:
|
||||||
a, fa = x, fx
|
a, fa = x, fx
|
||||||
|
|||||||
+76
-21
@@ -93,7 +93,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from .baselines import Counter, _Budget
|
from .baselines import Counter, _Budget, _opposite, _same_sign
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# [0,1] similarity functions of a normalised residual z: S(0) = 1 (identical
|
# [0,1] similarity functions of a normalised residual z: S(0) = 1 (identical
|
||||||
@@ -126,6 +126,63 @@ DIRECTIONS = ("distance", "dissimilar")
|
|||||||
|
|
||||||
EXPONENTS = ("none", "order")
|
EXPONENTS = ("none", "order")
|
||||||
|
|
||||||
|
EXTRAPOLATE_MODES = ("none", "steps", "confirmed", "pattern", "steps+results")
|
||||||
|
|
||||||
|
|
||||||
|
def _ratio_sim(a, b):
|
||||||
|
"""The SIM ratio form for two magnitudes: min/max, 1 when they are equal."""
|
||||||
|
hi = max(a, b)
|
||||||
|
return min(a, b) / hi if hi > 0.0 else 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def _extrapolation_s(mode, step, x, x_prev, x_prev2, fx, f_prev, f_prev2, moves):
|
||||||
|
"""How much of the geometric-series lengthening the history CONFIRMS: returns s in
|
||||||
|
[0, 1); the step becomes step/(1 - s). 0 means leave the step alone.
|
||||||
|
|
||||||
|
"steps" A: similarity of this step to the previous displacement.
|
||||||
|
"confirmed" G1: three moves the same way, both length ratios q1, q2 < 1; the
|
||||||
|
latest ratio q2, scaled by how similar q1 and q2 are.
|
||||||
|
"pattern" G2: A's s, applied only when the pattern of successive length ratios
|
||||||
|
repeats itself - period = the lag (2 .. half the history, so that two
|
||||||
|
repeats fit) of highest mean ratio similarity; applied iff that
|
||||||
|
similarity exceeds 1/2, the bisection constant.
|
||||||
|
"steps+results" G3: the smaller of A's s and the similarity of the last two RESULTS
|
||||||
|
f_n/f_(n-1) and f_(n-1)/f_(n-2); a result of either sign change
|
||||||
|
(a crossing) makes it 0.
|
||||||
|
No constant beyond bisection's 1/2 appears in any of them (PREREG 2026-09-21)."""
|
||||||
|
d1 = x - x_prev
|
||||||
|
if step == 0.0 or d1 == 0.0 or (step > 0.0) != (d1 > 0.0):
|
||||||
|
return 0.0
|
||||||
|
s_step = _ratio_sim(abs(step), abs(d1))
|
||||||
|
if mode == "steps":
|
||||||
|
return s_step
|
||||||
|
if mode == "confirmed":
|
||||||
|
if x_prev2 is None:
|
||||||
|
return 0.0
|
||||||
|
d2 = x_prev - x_prev2
|
||||||
|
if d2 == 0.0 or (d2 > 0.0) != (d1 > 0.0):
|
||||||
|
return 0.0
|
||||||
|
q1, q2 = abs(d1) / abs(d2), abs(step) / abs(d1)
|
||||||
|
if not (q1 < 1.0 and q2 < 1.0):
|
||||||
|
return 0.0
|
||||||
|
return q2 * _ratio_sim(q1, q2)
|
||||||
|
if mode == "pattern":
|
||||||
|
qs = [abs(moves[j]) / abs(moves[j - 1]) for j in range(1, len(moves))
|
||||||
|
if moves[j - 1] != 0.0 and moves[j] != 0.0]
|
||||||
|
k, best = len(qs), 0.0
|
||||||
|
for p in range(2, k // 2 + 1):
|
||||||
|
sims = [_ratio_sim(qs[j], qs[j - p]) for j in range(p, k)]
|
||||||
|
best = max(best, sum(sims) / len(sims))
|
||||||
|
return s_step if best > 0.5 else 0.0
|
||||||
|
if mode == "steps+results":
|
||||||
|
if f_prev2 is None or f_prev == 0.0 or f_prev2 == 0.0:
|
||||||
|
return 0.0
|
||||||
|
r_n, r_p = fx / f_prev, f_prev / f_prev2
|
||||||
|
if not (r_n > 0.0 and r_p > 0.0):
|
||||||
|
return 0.0
|
||||||
|
return min(s_step, _ratio_sim(r_n, r_p))
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
|
||||||
def _read_z(resid, sc, exponent, m):
|
def _read_z(resid, sc, exponent, m):
|
||||||
"""The normalised residual the similarity function is applied to.
|
"""The normalised residual the similarity function is applied to.
|
||||||
@@ -595,8 +652,9 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
|||||||
if scale not in ("derived", "derived3", "derived_rho", "derived3_rho",
|
if scale not in ("derived", "derived3", "derived_rho", "derived3_rho",
|
||||||
"derived3_m", "derived3_cap", "start", "bracket", "far"):
|
"derived3_m", "derived3_cap", "start", "bracket", "far"):
|
||||||
raise ValueError(f"unknown scale {scale!r}")
|
raise ValueError(f"unknown scale {scale!r}")
|
||||||
if extrapolate not in ("none", "steps"):
|
if extrapolate not in EXTRAPOLATE_MODES:
|
||||||
raise ValueError(f"unknown extrapolate {extrapolate!r}")
|
raise ValueError(f"unknown extrapolate {extrapolate!r}")
|
||||||
|
moves = [] # displacement history, kept only for extrapolate="pattern"
|
||||||
if exponent not in EXPONENTS:
|
if exponent not in EXPONENTS:
|
||||||
raise ValueError(f"unknown exponent {exponent!r}")
|
raise ValueError(f"unknown exponent {exponent!r}")
|
||||||
if exponent == "order" and scale not in ("derived3", "derived3_cap", "bracket", "far"):
|
if exponent == "order" and scale not in ("derived3", "derived3_cap", "bracket", "far"):
|
||||||
@@ -641,7 +699,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
|||||||
return a, g.n, True
|
return a, g.n, True
|
||||||
if fb == 0.0:
|
if fb == 0.0:
|
||||||
return b, g.n, True
|
return b, g.n, True
|
||||||
if fa * fb > 0.0:
|
if _same_sign(fa, fb):
|
||||||
raise ValueError("f(a) and f(b) must straddle zero")
|
raise ValueError("f(a) and f(b) must straddle zero")
|
||||||
|
|
||||||
A, FA, B, FB = a, fa, b, fb # the proven bracket
|
A, FA, B, FB = a, fa, b, fb # the proven bracket
|
||||||
@@ -866,23 +924,20 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
|||||||
step = _log_space_step(S, x, fx, far, slope, c_near, xtol)
|
step = _log_space_step(S, x, fx, far, slope, c_near, xtol)
|
||||||
if step is None:
|
if step is None:
|
||||||
step = (1.0 - S(z_now)) * (far - x)
|
step = (1.0 - S(z_now)) * (far - x)
|
||||||
if extrapolate == "steps":
|
if extrapolate != "none":
|
||||||
# PREREG 2026-09-21 (A in the method). The similarity of THIS
|
# PREREG 2026-09-21 (A in the method) and PREREG 2026-09-21
|
||||||
# step to the previous displacement: two successive moves the
|
# (gates G1-G3). Two successive moves the same way, of similar
|
||||||
# same way, of similar length, mean the iterate creeps along a
|
# length, mean the iterate creeps along a geometric series
|
||||||
# geometric series whose remainder is step*S/(1-S) - so the
|
# whose remainder is step*S/(1-S): the step is lengthened by
|
||||||
# step is lengthened by 1/(1-S). On x^m under a Newton step
|
# 1/(1-S). The modes differ only in how much of S the history
|
||||||
# S = 1 - 1/m and the factor is m, which lands on the root.
|
# CONFIRMS - see _extrapolation_s. Capped at the far end, the
|
||||||
# At a simple root successive steps shrink superlinearly, S ->
|
# same bound the step itself has; no constant.
|
||||||
# 0 and the step is untouched. Capped at the far end, the same
|
if extrapolate == "pattern":
|
||||||
# bound the step itself has; no constant.
|
moves.append(x - x_prev)
|
||||||
d_prev = x - x_prev
|
s_eff = _extrapolation_s(extrapolate, step, x, x_prev,
|
||||||
if (step != 0.0 and d_prev != 0.0
|
x_prev2, fx, f_prev, f_prev2, moves)
|
||||||
and (step > 0.0) == (d_prev > 0.0)):
|
if 0.0 < s_eff < 1.0:
|
||||||
s_steps = (min(abs(step), abs(d_prev))
|
longer = step / (1.0 - s_eff)
|
||||||
/ max(abs(step), abs(d_prev)))
|
|
||||||
if s_steps < 1.0:
|
|
||||||
longer = step / (1.0 - s_steps)
|
|
||||||
reach = abs(far - x)
|
reach = abs(far - x)
|
||||||
step = (longer if abs(longer) <= reach
|
step = (longer if abs(longer) <= reach
|
||||||
else math.copysign(reach, step))
|
else math.copysign(reach, step))
|
||||||
@@ -934,7 +989,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
|||||||
if stats is not None:
|
if stats is not None:
|
||||||
stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed
|
stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed
|
||||||
return x_new, g.n, True
|
return x_new, g.n, True
|
||||||
if FA * fnew < 0.0:
|
if _opposite(FA, fnew):
|
||||||
B, FB = x_new, fnew
|
B, FB = x_new, fnew
|
||||||
else:
|
else:
|
||||||
A, FA = x_new, fnew
|
A, FA = x_new, fnew
|
||||||
|
|||||||
+4
-2
@@ -40,6 +40,8 @@ no sigma, no temperature, no threshold, no tuned coefficient anywhere below.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from .baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from .baselines import Counter, _Budget
|
from .baselines import Counter, _Budget
|
||||||
@@ -155,7 +157,7 @@ def sim_root(f, a, b, xtol, maxfev, similarity="neg_sq", prototypes="pair",
|
|||||||
pending = False
|
pending = False
|
||||||
if fx == 0.0:
|
if fx == 0.0:
|
||||||
return x, g.n, True
|
return x, g.n, True
|
||||||
if fa * fx < 0.0:
|
if _opposite(fa, fx):
|
||||||
b, fb = x, fx
|
b, fb = x, fx
|
||||||
else:
|
else:
|
||||||
a, fa = x, fx
|
a, fa = x, fx
|
||||||
@@ -228,7 +230,7 @@ def sim_root(f, a, b, xtol, maxfev, similarity="neg_sq", prototypes="pair",
|
|||||||
mem.append((x, fx))
|
mem.append((x, fx))
|
||||||
if fx == 0.0:
|
if fx == 0.0:
|
||||||
return x, g.n, True
|
return x, g.n, True
|
||||||
if fa * fx < 0.0:
|
if _opposite(fa, fx):
|
||||||
b, fb = x, fx
|
b, fb = x, fx
|
||||||
else:
|
else:
|
||||||
a, fa = x, fx
|
a, fa = x, fx
|
||||||
|
|||||||
+4
-2
@@ -30,6 +30,8 @@ anything; every problem is shown.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
@@ -85,7 +87,7 @@ def bisection(f, a, b, tol=TOL, maxfev=MAXFEV):
|
|||||||
fx = g(x)
|
fx = g(x)
|
||||||
if fx == 0.0 or (b - a) <= tol:
|
if fx == 0.0 or (b - a) <= tol:
|
||||||
return x, st["n"]
|
return x, st["n"]
|
||||||
if fa * fx < 0.0:
|
if _opposite(fa, fx):
|
||||||
b, fb = x, fx
|
b, fb = x, fx
|
||||||
else:
|
else:
|
||||||
a, fa = x, fx
|
a, fa = x, fx
|
||||||
@@ -118,7 +120,7 @@ def sim_step(f, a, b, tol=TOL, maxfev=MAXFEV):
|
|||||||
fx = g(x)
|
fx = g(x)
|
||||||
if fx == 0.0 or abs(b - a) <= tol:
|
if fx == 0.0 or abs(b - a) <= tol:
|
||||||
return x, st["n"]
|
return x, st["n"]
|
||||||
if fa * fx < 0.0:
|
if _opposite(fa, fx):
|
||||||
b, fb = x, fx
|
b, fb = x, fx
|
||||||
else:
|
else:
|
||||||
a, fa = x, fx
|
a, fa = x, fx
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ linear S, which is exactly the collapse this stage is meant to expose.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from simroot.baselines import Counter, _Budget, bisection, brent
|
from simroot.baselines import Counter, _Budget, bisection, brent
|
||||||
@@ -106,7 +108,7 @@ def pure_similarity_step(f, a, b, xtol, maxfev, sim="rational", scale="s0"):
|
|||||||
if fnew == 0.0:
|
if fnew == 0.0:
|
||||||
return x_new, g.n, True
|
return x_new, g.n, True
|
||||||
smax = max(smax, abs(fnew))
|
smax = max(smax, abs(fnew))
|
||||||
if fx * fnew < 0.0:
|
if _opposite(fx, fnew):
|
||||||
# the root is between the old point and the new one
|
# the root is between the old point and the new one
|
||||||
far, ffar = x, fx
|
far, ffar = x, fx
|
||||||
x, fx = x_new, fnew
|
x, fx = x_new, fnew
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ is accepted on authority. Each is recomputed here from scratch.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
r2 = math.sqrt(2.0)
|
r2 = math.sqrt(2.0)
|
||||||
@@ -75,7 +77,7 @@ def main():
|
|||||||
xn = 0.5 * (A + B)
|
xn = 0.5 * (A + B)
|
||||||
fn = f(xn)
|
fn = f(xn)
|
||||||
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, xn, fn
|
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, xn, fn
|
||||||
if FA * fn < 0.0:
|
if _opposite(FA, fn):
|
||||||
B = xn
|
B = xn
|
||||||
else:
|
else:
|
||||||
A, FA = xn, fn
|
A, FA = xn, fn
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ Each is run raw and credit-guarded, on the same 199 problems.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
||||||
@@ -84,7 +86,7 @@ def solve(f, a, b, xtol, maxfev, rule, guarded):
|
|||||||
return a, g.n, True
|
return a, g.n, True
|
||||||
if fb == 0.0:
|
if fb == 0.0:
|
||||||
return b, g.n, True
|
return b, g.n, True
|
||||||
if fa * fb > 0.0:
|
if _same_sign(fa, fb):
|
||||||
raise ValueError("no sign change")
|
raise ValueError("no sign change")
|
||||||
A, FA, B, FB = a, fa, b, fb
|
A, FA, B, FB = a, fa, b, fb
|
||||||
hist = [(a, fa), (b, fb)]
|
hist = [(a, fa), (b, fb)]
|
||||||
@@ -108,7 +110,7 @@ def solve(f, a, b, xtol, maxfev, rule, guarded):
|
|||||||
x = x_new
|
x = x_new
|
||||||
if fn == 0.0:
|
if fn == 0.0:
|
||||||
return x_new, g.n, True
|
return x_new, g.n, True
|
||||||
if FA * fn < 0.0:
|
if _opposite(FA, fn):
|
||||||
B, FB = x_new, fn
|
B, FB = x_new, fn
|
||||||
else:
|
else:
|
||||||
A, FA = x_new, fn
|
A, FA = x_new, fn
|
||||||
|
|||||||
+3
-1
@@ -33,6 +33,8 @@ validated against scipy.optimize.brentq to 0.2% of evaluations.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
||||||
@@ -63,7 +65,7 @@ def brent_blend(f, a, b, xtol, maxfev, mode="blend"):
|
|||||||
c, fc = a, fa
|
c, fc = a, fa
|
||||||
d = e = b - a
|
d = e = b - a
|
||||||
while True:
|
while True:
|
||||||
if fb * fc > 0.0:
|
if _same_sign(fb, fc):
|
||||||
c, fc = a, fa
|
c, fc = a, fa
|
||||||
d = e = b - a
|
d = e = b - a
|
||||||
if abs(fc) < abs(fb):
|
if abs(fc) < abs(fb):
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ by 7 dB.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@@ -63,7 +65,7 @@ def falsi_driver(f, a, b, xtol, maxfev, repair):
|
|||||||
return a, g.n, True
|
return a, g.n, True
|
||||||
if fb == 0.0:
|
if fb == 0.0:
|
||||||
return b, g.n, True
|
return b, g.n, True
|
||||||
if fa * fb > 0.0:
|
if _same_sign(fa, fb):
|
||||||
raise ValueError("no sign change")
|
raise ValueError("no sign change")
|
||||||
sg = _Safeguard("credit", abs(b - a), xtol)
|
sg = _Safeguard("credit", abs(b - a), xtol)
|
||||||
while abs(b - a) > xtol:
|
while abs(b - a) > xtol:
|
||||||
@@ -82,7 +84,7 @@ def falsi_driver(f, a, b, xtol, maxfev, repair):
|
|||||||
fx = g(x_new)
|
fx = g(x_new)
|
||||||
if fx == 0.0:
|
if fx == 0.0:
|
||||||
return x_new, g.n, True
|
return x_new, g.n, True
|
||||||
if fa * fx < 0.0:
|
if _opposite(fa, fx):
|
||||||
if repair == "illinois":
|
if repair == "illinois":
|
||||||
fa *= 0.5
|
fa *= 0.5
|
||||||
elif repair == "pegasus":
|
elif repair == "pegasus":
|
||||||
|
|||||||
+4
-2
@@ -26,6 +26,8 @@ and Galdino's (2011).
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
||||||
@@ -133,7 +135,7 @@ def falsi_modern(f, a, b, xtol, maxfev, variant):
|
|||||||
return a, g.n, True
|
return a, g.n, True
|
||||||
if fb == 0.0:
|
if fb == 0.0:
|
||||||
return b, g.n, True
|
return b, g.n, True
|
||||||
if fa * fb > 0.0:
|
if _same_sign(fa, fb):
|
||||||
raise ValueError("no sign change")
|
raise ValueError("no sign change")
|
||||||
while abs(b - a) > xtol:
|
while abs(b - a) > xtol:
|
||||||
lo, hi = (a, b) if a < b else (b, a)
|
lo, hi = (a, b) if a < b else (b, a)
|
||||||
@@ -156,7 +158,7 @@ def falsi_modern(f, a, b, xtol, maxfev, variant):
|
|||||||
m = f_moved / (f_moved + fx) if (f_moved + fx) != 0.0 else 0.5
|
m = f_moved / (f_moved + fx) if (f_moved + fx) != 0.0 else 0.5
|
||||||
return m if 0.0 < m < 1.0 else 0.5
|
return m if 0.0 < m < 1.0 else 0.5
|
||||||
|
|
||||||
if fa * fx < 0.0:
|
if _opposite(fa, fx):
|
||||||
fa *= factor(fa, fb)
|
fa *= factor(fa, fb)
|
||||||
b, fb = x_new, fx
|
b, fb = x_new, fx
|
||||||
else:
|
else:
|
||||||
|
|||||||
+3
-1
@@ -30,6 +30,8 @@ explanation is wrong and must not go into the paper.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
||||||
@@ -157,7 +159,7 @@ def replay_bracket(f, a, b, xs):
|
|||||||
w0 = hi - lo
|
w0 = hi - lo
|
||||||
positions.append((xi - lo) / w0)
|
positions.append((xi - lo) / w0)
|
||||||
fi = f(xi)
|
fi = f(xi)
|
||||||
if flo * fi < 0.0:
|
if _opposite(flo, fi):
|
||||||
hi = xi
|
hi = xi
|
||||||
else:
|
else:
|
||||||
lo, flo = xi, fi
|
lo, flo = xi, fi
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ directly on the worst offenders.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from scipy.optimize._tstutils import _CHANDRUPATLA_TESTS_DICTS
|
from scipy.optimize._tstutils import _CHANDRUPATLA_TESTS_DICTS
|
||||||
@@ -78,7 +80,7 @@ def replay(f, a, b, similarity="ratio"):
|
|||||||
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, x_new, fn
|
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, x_new, fn
|
||||||
if fn == 0.0:
|
if fn == 0.0:
|
||||||
break
|
break
|
||||||
if FA * fn < 0.0:
|
if _opposite(FA, fn):
|
||||||
B, FB = x_new, fn
|
B, FB = x_new, fn
|
||||||
else:
|
else:
|
||||||
A, FA = x_new, fn
|
A, FA = x_new, fn
|
||||||
|
|||||||
+4
-2
@@ -27,6 +27,8 @@ brentq would not be comparable and is excluded.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@ def ours_inlined(f, a, b, xtol, maxfev):
|
|||||||
return a, n, True
|
return a, n, True
|
||||||
if fb == 0.0:
|
if fb == 0.0:
|
||||||
return b, n, True
|
return b, n, True
|
||||||
if fa * fb > 0.0:
|
if _same_sign(fa, fb):
|
||||||
raise ValueError("f(a) and f(b) must straddle zero")
|
raise ValueError("f(a) and f(b) must straddle zero")
|
||||||
A, FA, B = a, fa, b
|
A, FA, B = a, fa, b
|
||||||
if abs(fa) <= abs(fb):
|
if abs(fa) <= abs(fb):
|
||||||
@@ -132,7 +134,7 @@ def ours_inlined(f, a, b, xtol, maxfev):
|
|||||||
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, xn, fn
|
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, xn, fn
|
||||||
if fn == 0.0:
|
if fn == 0.0:
|
||||||
return xn, n, True
|
return xn, n, True
|
||||||
if FA * fn < 0.0:
|
if _opposite(FA, fn):
|
||||||
B = xn
|
B = xn
|
||||||
else:
|
else:
|
||||||
A, FA = xn, fn
|
A, FA = xn, fn
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+21
-5
@@ -136,8 +136,9 @@ def label(spec):
|
|||||||
if len(spec) > 7 and spec[7] != "distance":
|
if len(spec) > 7 and spec[7] != "distance":
|
||||||
tag = f"{tag}+dissim"
|
tag = f"{tag}+dissim"
|
||||||
if len(spec) > 9 and spec[9] != "none":
|
if len(spec) > 9 and spec[9] != "none":
|
||||||
# the pair (off, on) must be distinguishable in a results file
|
# every extrapolation mode must be distinguishable in a results file
|
||||||
tag = f"{tag}+ext"
|
tag = f"{tag}+" + {"steps": "ext", "confirmed": "extC", "pattern": "extP",
|
||||||
|
"steps+results": "extR"}[spec[9]]
|
||||||
if len(spec) > 8 and spec[8] != "none":
|
if len(spec) > 8 and spec[8] != "none":
|
||||||
# the exponent must be visible in the label: (far, none) is false position and
|
# the exponent must be visible in the label: (far, none) is false position and
|
||||||
# (far, order) is the hypothesis, and a results file that cannot tell them apart
|
# (far, order) is the hypothesis, and a results file that cannot tell them apart
|
||||||
@@ -218,6 +219,18 @@ def _preflight_extrap_mode():
|
|||||||
raise SystemExit("extrapolate preflight FAILED: refusing to report zeros")
|
raise SystemExit("extrapolate preflight FAILED: refusing to report zeros")
|
||||||
|
|
||||||
|
|
||||||
|
def build_grid_extrap2(smoke):
|
||||||
|
"""PREREG_extrapolation_gates_2026-09-21: the same cells as build_grid_extrap, every
|
||||||
|
one in all five modes (none, A, G1, G2, G3)."""
|
||||||
|
for mode in ("confirmed", "pattern", "steps+results"):
|
||||||
|
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100, similarity="ratio",
|
||||||
|
scale="derived3", guard="project", extrapolate=mode)
|
||||||
|
if not (ok and abs(x - 1.0) < 1e-8):
|
||||||
|
raise SystemExit(f"extrapolate={mode} preflight FAILED: refusing to report zeros")
|
||||||
|
modes = ("none", "steps", "confirmed", "pattern", "steps+results")
|
||||||
|
return [s[:9] + (m,) for s in build_grid_extrap(smoke) if s[9] == "none" for m in modes]
|
||||||
|
|
||||||
|
|
||||||
def build_grid_extrap(smoke):
|
def build_grid_extrap(smoke):
|
||||||
"""PREREG 2026-09-21: step extrapolation (A) inside the method, every cell as a pair
|
"""PREREG 2026-09-21: step extrapolation (A) inside the method, every cell as a pair
|
||||||
(none, steps). Tent with every reading and every guard; all nine functions without
|
(none, steps). Tent with every reading and every guard; all nine functions without
|
||||||
@@ -374,10 +387,12 @@ def main():
|
|||||||
ordermode = "--order" in sys.argv # slot 1: the similarity read BY PLACE
|
ordermode = "--order" in sys.argv # slot 1: the similarity read BY PLACE
|
||||||
decmode = "--decision" in sys.argv # slot 2: the reading in the DECISION place
|
decmode = "--decision" in sys.argv # slot 2: the reading in the DECISION place
|
||||||
extmode = "--extrap" in sys.argv # A in the method: step extrapolation
|
extmode = "--extrap" in sys.argv # A in the method: step extrapolation
|
||||||
|
ext2mode = "--extrap2" in sys.argv # gates G1-G3 on the lengthening
|
||||||
combomode = "--combo" in sys.argv # modes A and B together
|
combomode = "--combo" in sys.argv # modes A and B together
|
||||||
pointsmode = "--points" in sys.argv # mode A: triple by shape
|
pointsmode = "--points" in sys.argv # mode A: triple by shape
|
||||||
dirmode = "--direction" in sys.argv # mode B: far end by dissimilarity
|
dirmode = "--direction" in sys.argv # mode B: far end by dissimilarity
|
||||||
specs = (build_grid_extrap(smoke) if extmode else
|
specs = (build_grid_extrap2(smoke) if ext2mode else
|
||||||
|
build_grid_extrap(smoke) if extmode else
|
||||||
build_grid_decision(smoke) if decmode else
|
build_grid_decision(smoke) if decmode else
|
||||||
build_grid_order(smoke) if ordermode else
|
build_grid_order(smoke) if ordermode else
|
||||||
build_grid_cap(smoke) if capmode else
|
build_grid_cap(smoke) if capmode else
|
||||||
@@ -402,8 +417,9 @@ def main():
|
|||||||
|
|
||||||
# the published sweep_full.json is what verify_article.py checks the paper
|
# the published sweep_full.json is what verify_article.py checks the paper
|
||||||
# against, so the log grid never writes into it
|
# against, so the log grid never writes into it
|
||||||
if extmode or decmode or ordermode or capmode or combomode or pointsmode or dirmode:
|
if ext2mode or extmode or decmode or ordermode or capmode or combomode or pointsmode or dirmode:
|
||||||
base = ("sweep_extrap" if extmode else
|
base = ("sweep_extrap2" if ext2mode else
|
||||||
|
"sweep_extrap" if extmode else
|
||||||
"sweep_decision" if decmode else
|
"sweep_decision" if decmode else
|
||||||
"sweep_order" if ordermode else
|
"sweep_order" if ordermode else
|
||||||
"sweep_cap" if capmode else
|
"sweep_cap" if capmode else
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -73,6 +73,46 @@ def test_on_a_budget_bound_run_extrapolation_changes_the_path_not_the_count():
|
|||||||
assert ev["steps"][1] != ev["none"][1]
|
assert ev["steps"][1] != ev["none"][1]
|
||||||
|
|
||||||
|
|
||||||
|
GATES = ("confirmed", "pattern", "steps+results")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("mode", GATES)
|
||||||
|
@pytest.mark.parametrize("f,a,b", SMOOTH + FLAT)
|
||||||
|
@pytest.mark.parametrize("guard", ("project", "credit"))
|
||||||
|
def test_every_gate_keeps_the_guarantee(mode, f, a, b, guard):
|
||||||
|
x, n, ok = pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3",
|
||||||
|
guard=guard, extrapolate=mode)
|
||||||
|
assert ok and min(a, b) <= x <= max(a, b)
|
||||||
|
half = math.ceil(math.log2(abs(b - a) / XTOL))
|
||||||
|
assert n <= (2 * half + 3 if guard == "project" else half + 4), (mode, n)
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_gates_decline_without_history():
|
||||||
|
"""Each gate needs history to confirm anything; without it the step is untouched."""
|
||||||
|
from simroot.pure import _extrapolation_s
|
||||||
|
# opposite directions -> nothing to confirm, in every mode
|
||||||
|
for mode in ("steps",) + GATES:
|
||||||
|
assert _extrapolation_s(mode, 0.1, 1.0, 1.5, None, 1.0, 2.0, None, []) == 0.0
|
||||||
|
# same direction, but G1 has no third point, G3 no third value, G2 no history
|
||||||
|
assert _extrapolation_s("confirmed", 0.1, 1.0, 0.8, None, 1.0, 2.0, None, []) == 0.0
|
||||||
|
assert _extrapolation_s("steps+results", 0.1, 1.0, 0.8, None, 1.0, 2.0, None, []) == 0.0
|
||||||
|
assert _extrapolation_s("pattern", 0.1, 1.0, 0.8, None, 1.0, 2.0, None, [0.2]) == 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_results_after_a_crossing_confirm_nothing():
|
||||||
|
"""G3: a sign change of f between the last results is a crossing, not a creep."""
|
||||||
|
from simroot.pure import _extrapolation_s
|
||||||
|
assert _extrapolation_s("steps+results", 0.1, 1.0, 0.9, 0.8, 1.0, -2.0, 4.0, []) == 0.0
|
||||||
|
assert _extrapolation_s("steps+results", 0.1, 1.0, 0.9, 0.8, 1.0, 2.0, 4.0, []) > 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_a_confirmed_geometric_series_is_read_exactly():
|
||||||
|
"""G1 on three moves in ratio 0.5, 0.5: fully confirmed, s = q2 = 0.5."""
|
||||||
|
from simroot.pure import _extrapolation_s
|
||||||
|
s = _extrapolation_s("confirmed", 0.025, 1.0, 0.95, 0.85, 1.0, 2.0, 4.0, [])
|
||||||
|
assert s == pytest.approx(0.5)
|
||||||
|
|
||||||
|
|
||||||
def test_unknown_mode_is_refused():
|
def test_unknown_mode_is_refused():
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
pure_root(lambda t: t, -1.0, 1.0, XTOL, MAXFEV, extrapolate="aitken")
|
pure_root(lambda t: t, -1.0, 1.0, XTOL, MAXFEV, extrapolate="aitken")
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ They are asserted here so a later edit cannot quietly restore the old claim.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from simroot.baselines import _opposite, _same_sign # 2026-09-21 fix
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@@ -80,7 +82,7 @@ def test_the_tent_never_clips_under_the_derived_scale():
|
|||||||
xn = 0.5 * (A + B)
|
xn = 0.5 * (A + B)
|
||||||
fn = F(xn)
|
fn = F(xn)
|
||||||
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, xn, fn
|
xp2, fp2, xp, fp, x, fx = xp, fp, x, fx, xn, fn
|
||||||
if FA * fn < 0.0:
|
if _opposite(FA, fn):
|
||||||
B = xn
|
B = xn
|
||||||
else:
|
else:
|
||||||
A, FA = xn, fn
|
A, FA = xn, fn
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
"""REGRESSION, 2026-09-21: sign tests by product underflowed on flat functions.
|
||||||
|
|
||||||
|
`FA * fnew < 0.0` with FA ~ -1e-200 and fnew ~ 1e-150 is -0.0, and '-0.0 < 0.0' is
|
||||||
|
False: the bracket update moved the wrong end, the root left the bracket, and the run
|
||||||
|
still reported convergence - on fun6.5 (x^19 over [-10, 100]) the proposed rule returned
|
||||||
|
6.7e-9 and a lengthening mode 1.27e-6 with a claimed 1e-12 bracket. The same product
|
||||||
|
test sat in our bisection, false-position family, Ridders, Brent and ITP.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from simroot.baselines import (_opposite, _same_sign, bisection, illinois, itp,
|
||||||
|
regula_falsi, ridders)
|
||||||
|
from simroot.pure import pure_root
|
||||||
|
|
||||||
|
XTOL, MAXFEV = 1e-12, 200
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_product_underflows_and_the_sign_test_does_not():
|
||||||
|
u, v = -1e-200, 1e-150
|
||||||
|
assert u * v == 0.0 # the defect, pinned
|
||||||
|
assert _opposite(u, v) and not _same_sign(u, v)
|
||||||
|
assert _same_sign(-1e-200, -1e-150) and not _opposite(-1e-200, -1e-150)
|
||||||
|
assert not _opposite(0.0, 1.0) and not _same_sign(0.0, 1.0)
|
||||||
|
|
||||||
|
|
||||||
|
def power19(t):
|
||||||
|
return t ** 19
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("guard", ("project", "safe", "credit", "none"))
|
||||||
|
@pytest.mark.parametrize("extrapolate", ("none", "confirmed"))
|
||||||
|
def test_the_method_keeps_the_root_in_the_bracket_on_x19(guard, extrapolate):
|
||||||
|
for sim in ("ratio", "cbrt"):
|
||||||
|
x, n, ok = pure_root(power19, -10.0, 100.0, XTOL, MAXFEV, similarity=sim,
|
||||||
|
scale="derived3", guard=guard, extrapolate=extrapolate)
|
||||||
|
if ok:
|
||||||
|
assert abs(x) <= XTOL, (sim, guard, extrapolate, x)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("method", (bisection, regula_falsi, illinois, ridders, itp))
|
||||||
|
def test_the_classical_methods_keep_the_root_on_x19(method):
|
||||||
|
x, n, ok = method(power19, -10.0, 100.0, XTOL, MAXFEV)
|
||||||
|
if ok:
|
||||||
|
assert abs(x) <= XTOL, (method.__name__, x)
|
||||||
Reference in New Issue
Block a user