AgentSquares / bounds.py
DHDRL's picture
Upload 107 files
6cb442b verified
Raw History Blame Contribute Delete
3.61 kB
"""Compare claimed container sides against stored bounds. Deterministic, no LLM.
Metric per n: smaller container side s is better (see sources.md; relative score s/sqrt(n)-1 is monotone in s for fixed n)."""
from __future__ import annotations
from dataclasses import dataclass, asdict, field
import json
import math
@dataclass
class Bound:
n: int
s: float
source: str
date: str # ISO date the source was read
verified: bool
basis: str = "" # e.g. "listed", "trivial-grid rule", "proved"
exact: str = "" # closed form if the source gives one
def load_bounds(path):
with open(path) as f:
return {int(d["n"]): Bound(**d) for d in json.load(f)}
def save_bounds(bounds, path):
with open(path, "w") as f:
json.dump([asdict(b) for _, b in sorted(bounds.items())], f, indent=2)
def area_lower_bound(n):
return math.sqrt(n)
def trivial_upper_bound(n):
return math.ceil(math.sqrt(n))
def rel_score(n, s):
return s / math.sqrt(n) - 1.0
# Units: every side length here is the container side measured in unit-square edge lengths
# (the squares have side 1). Thresholds are ABSOLUTE differences in that unit.
VALIDATION_EPS = 1e-9 # geometry tolerance used by packing.validate (float mode)
IMPROVEMENT_MATERIAL = 1e-8 # a claim must beat the bound by MORE than this; strictly > VALIDATION_EPS
assert IMPROVEMENT_MATERIAL > VALIDATION_EPS
def float_near_bound_margin(n):
"""Float validation allows each pair to overlap by up to VALIDATION_EPS. Along a row of ~sqrt(n)..n
squares those slacks add up, so the true required side can be up to ~n*VALIDATION_EPS smaller than
the float check suggests. A float-validated (non-proof) claim is promoted to an improvement only if it
beats the bound by more than this; otherwise it stays a candidate until an exact/interval check."""
return IMPROVEMENT_MATERIAL + n * VALIDATION_EPS
def classify(claim_s, bound_s, validation=None, material=IMPROVEMENT_MATERIAL):
"""Return (status, delta), delta = claim - bound (negative is better).
partial: no side. impossible: s < sqrt(n) is ruled out by area (checked by caller).
invalid: coordinates failed validation. improvement: validated and better.
unverified: better than bound but no coordinates checked (a CANDIDATE, never an improvement).
unchanged: within +-material. worse. no_baseline: bound unknown."""
if claim_s is None:
return "partial", None
if bound_s is None:
if validation is not None and not validation["valid"]:
return "invalid", None
return "no_baseline", None
delta = claim_s - bound_s
if validation is not None and not validation["valid"]:
return "invalid", delta
if delta < -material:
return ("improvement", delta) if validation is not None else ("unverified", delta)
if delta > material:
return "worse", delta
return "unchanged", delta
def find_conflicts(claims, tol=1e-6):
"""claims: dicts with n, s, source_url. One entry per n whose sides differ by > tol
across distinct sources. s=None ignored."""
by_n = {}
for c in claims:
if c.get("s") is not None:
by_n.setdefault(c["n"], []).append(c)
out = []
for n, cs in sorted(by_n.items()):
vals = [c["s"] for c in cs]
if max(vals) - min(vals) > tol and len({c.get("source_url") for c in cs}) > 1:
out.append({"n": n, "spread": max(vals) - min(vals),
"claims": [{"s": c["s"], "source_url": c.get("source_url")} for c in cs]})
return out