PREREG before code and run: repair the two base-step gaps - close (Dekker/Brent's tolerance step, named as borrowed) and sub (the second branch of |1 - 1/m| > 1/2: enter the regime for m <= 2/3 on an overshooting unkept promise) - and test A' = A + close + sub once on a FOURTH corpus (corpus_fourth.py, seed 20260922, 240 problems in six new families, two of them targeted), committed now; development only on the seen corpora. F1-F3 transfer, F4 the repairs earned.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
"""The FOURTH out-of-sample corpus for PREREG_close_sub_2026-09-21 - written and committed before
|
||||
the two repairs are implemented and before any method is run on it. Seed 20260922; the
|
||||
function families are NEW (none of corpus_new's closed forms is reused). 40 per class:
|
||||
|
||||
D1 random polynomial, one simple root in the bracket (others outside) - neutral
|
||||
D2 random polynomial with one MULTIPLE root of odd multiplicity 3..9 - flat side
|
||||
D3 fractional power |x - r|^p sign(x - r) * g(x), p ~ U(0.15, 0.95) - TARGETED (repair 2)
|
||||
D4 sums of exponentials and sines with one root in the bracket - neutral
|
||||
D5 compositions tanh(q(x)), atan(q(x)), log1p(q(x)^2) - c with a cubic q - neutral
|
||||
D6 odd around the root: s(x - r) with s in {sin(k.), (.)+a(.)^3, arcsinh(k.)} - TARGETED (repair 1)
|
||||
|
||||
Roots are known by construction for D1-D3 and D6; for D4-D5 success is judged by a sign
|
||||
change within 1e-6 (corpus_roots_jl.solved), which is used for every class for uniformity.
|
||||
Brackets: width log-uniform on [0.1, 100], the root at a fraction U(0.02, 0.98). A problem
|
||||
without finite values of opposite sign at the ends is redrawn (redraws reported).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
|
||||
import numpy as np
|
||||
|
||||
SEED = 20260922
|
||||
PER_CLASS = 40
|
||||
|
||||
|
||||
def _bracket(rng, r, lo=0.1, hi=100.0):
|
||||
L = math.exp(rng.uniform(math.log(lo), math.log(hi)))
|
||||
u = rng.uniform(0.02, 0.98)
|
||||
return r - u * L, r + (1.0 - u) * L
|
||||
|
||||
|
||||
def _ok(f, a, b):
|
||||
try:
|
||||
fa, fb = f(a), f(b)
|
||||
except (OverflowError, ValueError, ZeroDivisionError):
|
||||
return False
|
||||
return (math.isfinite(fa) and math.isfinite(fb) and fa != 0.0 and fb != 0.0
|
||||
and (fa < 0.0) != (fb < 0.0))
|
||||
|
||||
|
||||
def _poly_from_roots(roots, scale):
|
||||
def f(x, roots=tuple(roots), scale=scale):
|
||||
v = scale
|
||||
for q in roots:
|
||||
v *= (x - q)
|
||||
return v
|
||||
return f
|
||||
|
||||
|
||||
def _d1(rng):
|
||||
r = rng.uniform(-1, 1)
|
||||
a, b = _bracket(rng, r)
|
||||
deg = int(rng.integers(3, 10))
|
||||
others = []
|
||||
while len(others) < deg - 1: # the other roots outside the bracket, or complex pairs
|
||||
if rng.uniform() < 0.5 and len(others) <= deg - 3:
|
||||
c, d = rng.uniform(-3, 3), rng.uniform(0.1, 3)
|
||||
others.append(("c", c, d))
|
||||
others.append(None)
|
||||
else:
|
||||
side = a - rng.uniform(0.1, 5) if rng.uniform() < 0.5 else b + rng.uniform(0.1, 5)
|
||||
others.append(("r", side))
|
||||
others = [o for o in others if o is not None][: deg - 1]
|
||||
|
||||
def f(x, r=r, others=tuple(others)):
|
||||
v = x - r
|
||||
for o in others:
|
||||
v *= (x - o[1]) if o[0] == "r" else ((x - o[1]) ** 2 + o[2] ** 2)
|
||||
return v
|
||||
return f, r, (a, b)
|
||||
|
||||
|
||||
def _d2(rng):
|
||||
r = rng.uniform(-1, 1)
|
||||
m = int(rng.choice([3, 5, 7, 9]))
|
||||
a, b = _bracket(rng, r, hi=10.0)
|
||||
c = rng.uniform(0.5, 3)
|
||||
return (lambda x, r=r, m=m, c=c: (x - r) ** m * (1 + c * x * x)), r, (a, b)
|
||||
|
||||
|
||||
def _d3(rng):
|
||||
r = rng.uniform(-1, 1)
|
||||
p = rng.uniform(0.15, 0.95)
|
||||
a0, c = rng.uniform(0, 1), rng.uniform(0.5, 5)
|
||||
a, b = _bracket(rng, r)
|
||||
return (lambda x, r=r, p=p, a0=a0, c=c:
|
||||
math.copysign(abs(x - r) ** p, x - r) * math.exp(a0 * math.sin(c * x))), r, (a, b)
|
||||
|
||||
|
||||
def _d4(rng):
|
||||
r = rng.uniform(-1, 1)
|
||||
k1, k2 = rng.uniform(-2, 2), rng.uniform(-2, 2)
|
||||
w, ph = rng.uniform(0.5, 4), rng.uniform(0, 2 * math.pi)
|
||||
a, b = _bracket(rng, r, hi=20.0)
|
||||
|
||||
def g(x, k1=k1, k2=k2, w=w, ph=ph):
|
||||
return math.exp(k1 * x) + 0.5 * math.exp(k2 * x) + math.sin(w * x + ph)
|
||||
gr = g(r)
|
||||
slope = abs(k1) + abs(k2) + w + 1.0
|
||||
return (lambda x, g=g, gr=gr, r=r, s=slope: g(x) - gr + 1.5 * s * (x - r)), r, (a, b)
|
||||
|
||||
|
||||
def _d5(rng):
|
||||
r = rng.uniform(-1, 1)
|
||||
c1, c2 = rng.uniform(0.5, 3), rng.uniform(-1, 1)
|
||||
kind = int(rng.integers(3))
|
||||
a, b = _bracket(rng, r, hi=10.0)
|
||||
q = lambda x, r=r, c1=c1, c2=c2: c1 * (x - r) + c2 * (x - r) ** 2 + (x - r) ** 3
|
||||
if kind == 0:
|
||||
return (lambda x, q=q: math.tanh(q(x))), r, (a, b)
|
||||
if kind == 1:
|
||||
return (lambda x, q=q: math.atan(q(x))), r, (a, b)
|
||||
return (lambda x, q=q: math.copysign(math.log1p(q(x) ** 2), q(x))), r, (a, b)
|
||||
|
||||
|
||||
def _d6(rng):
|
||||
r = rng.uniform(-1, 1)
|
||||
k = math.exp(rng.uniform(math.log(0.3), math.log(3)))
|
||||
kind = int(rng.integers(3))
|
||||
a, b = _bracket(rng, r, hi=3.0 / k if kind == 0 else 100.0) # sin: a single root
|
||||
if kind == 0:
|
||||
return (lambda x, r=r, k=k: math.sin(k * (x - r))), r, (a, b)
|
||||
if kind == 1:
|
||||
aa = rng.uniform(0.1, 2)
|
||||
return (lambda x, r=r, aa=aa: (x - r) + aa * (x - r) ** 3), r, (a, b)
|
||||
return (lambda x, r=r, k=k: math.asinh(k * (x - r))), r, (a, b)
|
||||
|
||||
|
||||
def build():
|
||||
out, redraws = [], {}
|
||||
rng = np.random.default_rng(SEED)
|
||||
for cls, gen in (("D1", _d1), ("D2", _d2), ("D3", _d3), ("D4", _d4), ("D5", _d5), ("D6", _d6)):
|
||||
n = red = 0
|
||||
while n < PER_CLASS:
|
||||
f, r, (a, b) = gen(rng)
|
||||
if _ok(f, a, b) and min(a, b) < r < max(a, b):
|
||||
out.append((cls, f"{cls}.{n:02d}", f, float(a), float(b), float(r)))
|
||||
n += 1
|
||||
else:
|
||||
red += 1
|
||||
redraws[cls] = red
|
||||
return out, redraws
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from collections import Counter
|
||||
probs, red = build()
|
||||
print(len(probs), dict(Counter(p[0] for p in probs)), "redraws", red)
|
||||
Reference in New Issue
Block a user