Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
|
| 2 |
"""
|
| 3 |
PRACTICALITY SYSTEM 24.1 β STRUCTURAL SKETCH, QUANTUM ENGINE & HOMOTOPY CONTINUATION
|
| 4 |
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -9,11 +9,10 @@ ARCHITECTURE:
|
|
| 9 |
β [WISDOM LAYER] β Sketch-weighted rays + Masked Deduction (with Homotopy)
|
| 10 |
β [GEMINI COLLAPSER] β Domain-language explanation
|
| 11 |
|
| 12 |
-
|
| 13 |
-
1.
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
2. Quantum Anchor Fix: Correctly verifies correlators to prevent infinite 0.0 CE loops.
|
| 17 |
"""
|
| 18 |
|
| 19 |
import os, time, random, math, threading, warnings, json, textwrap
|
|
@@ -43,13 +42,13 @@ except ImportError:
|
|
| 43 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 44 |
# AI CONFIGURATION
|
| 45 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 46 |
-
DEFAULT_GEMINI_API_KEY = os.environ.get("
|
| 47 |
-
GEMINI_MODEL = "gemini-
|
| 48 |
|
| 49 |
warnings.filterwarnings("ignore")
|
| 50 |
USE_GPU = torch.cuda.is_available()
|
| 51 |
DEVICE = torch.device("cuda" if USE_GPU else "cpu")
|
| 52 |
-
print(f"[SYSTEM 24.1] Compute: {DEVICE.type.upper()} | Homotopy Continuation
|
| 53 |
|
| 54 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 55 |
# SECTION 1: CONSTANTS
|
|
@@ -80,18 +79,28 @@ SYMPY_TIMEOUT_SECS = 4.0
|
|
| 80 |
STATE_LOCK = threading.Lock()
|
| 81 |
|
| 82 |
GLOBAL_SOLVE_STATE = {
|
| 83 |
-
"is_running": False,
|
| 84 |
-
"
|
| 85 |
-
"
|
| 86 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
}
|
| 88 |
|
| 89 |
def _update_state(**kwargs):
|
| 90 |
with STATE_LOCK:
|
| 91 |
-
for k, v in kwargs.items():
|
|
|
|
| 92 |
|
| 93 |
def _add_log(line: str):
|
| 94 |
-
with STATE_LOCK:
|
|
|
|
| 95 |
|
| 96 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 97 |
# SECTION 3: INTERVAL ARITHMETIC (HC4)
|
|
@@ -307,7 +316,8 @@ AXL_COMPILER=AXLtoPSLCompiler()
|
|
| 307 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 308 |
@dataclass
|
| 309 |
class Constraint:
|
| 310 |
-
kind:str; expr:str; direction:str; weight:float=1.0; scope:str="root"
|
|
|
|
| 311 |
|
| 312 |
@dataclass
|
| 313 |
class MathConstraint:
|
|
@@ -489,59 +499,80 @@ def build_base_problem(axl_def:AXLProblemDef) -> Problem:
|
|
| 489 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 490 |
@dataclass
|
| 491 |
class StructuralSketch:
|
| 492 |
-
axiom_affinities: Dict[str, float]
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 497 |
|
| 498 |
@dataclass
|
| 499 |
class HypothesisTemplate:
|
| 500 |
-
template_id: str
|
| 501 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 502 |
|
| 503 |
def _try_sympy_solve(problem: Problem) -> Tuple[List[Dict[str, float]], bool, List[str]]:
|
| 504 |
has_transcendental = any(
|
| 505 |
mc.parsed is not None and (mc.parsed.has(sp.sin) or mc.parsed.has(sp.cos) or mc.parsed.has(sp.exp) or mc.parsed.has(sp.log))
|
| 506 |
for mc in problem.compiled_constraints)
|
| 507 |
if has_transcendental: return [], False, []
|
|
|
|
| 508 |
eq_mcs = [mc for mc in problem.compiled_constraints if mc.kind == "equality" and mc.parsed is not None and mc.syms_used]
|
| 509 |
if len(eq_mcs) < len(problem.variables): return [], False, []
|
|
|
|
| 510 |
syms = [sp.Symbol(v) for v in problem.variables]
|
| 511 |
equations = [mc.parsed for mc in eq_mcs]
|
| 512 |
|
| 513 |
-
def _solve():
|
|
|
|
| 514 |
|
| 515 |
try:
|
| 516 |
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as ex:
|
| 517 |
future = ex.submit(_solve)
|
| 518 |
raw = future.result(timeout=SYMPY_TIMEOUT_SECS)
|
| 519 |
except Exception: return [], False, []
|
|
|
|
| 520 |
if not raw: return [], False, []
|
| 521 |
|
| 522 |
derivation = ["SYSTEM HANDED TO SYMPY:"]
|
| 523 |
for mc in eq_mcs: derivation.append(f" {mc.expr_str} = 0")
|
|
|
|
| 524 |
for sol_idx, sol in enumerate(raw[:2]):
|
| 525 |
derivation.append(f"\nSYMBOLIC SOLUTION #{sol_idx + 1}:")
|
| 526 |
sorted_sol = sorted(sol.items(), key=lambda kv: len(kv[1].free_symbols))
|
| 527 |
for sym, val in sorted_sol:
|
| 528 |
simplified = sp.simplify(val); free_s = sorted(simplified.free_symbols, key=str)
|
| 529 |
if not free_s:
|
| 530 |
-
try:
|
| 531 |
-
|
| 532 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
if len(sorted_sol) == 1:
|
| 534 |
sym, val = sorted_sol[0]
|
| 535 |
try:
|
| 536 |
poly = sp.Poly(equations[0], sp.Symbol(str(sym)))
|
| 537 |
-
|
| 538 |
-
derivation.append(f" Univariate polynomial: degree {poly.degree()}, roots selected by
|
| 539 |
except: pass
|
| 540 |
|
| 541 |
valid = []
|
| 542 |
b_mid = {v: (problem.bounds[v][0] + problem.bounds[v][1]) / 2 for v in problem.variables}
|
| 543 |
for sol in raw:
|
| 544 |
-
binding = dict(b_mid)
|
|
|
|
| 545 |
for sym, val in sol.items():
|
| 546 |
try:
|
| 547 |
num = float(val.evalf()); vn = str(sym)
|
|
@@ -553,18 +584,23 @@ def _try_sympy_solve(problem: Problem) -> Tuple[List[Dict[str, float]], bool, Li
|
|
| 553 |
if ok:
|
| 554 |
ce = problem.scalar_energy(binding)
|
| 555 |
if ce < 1.0: valid.append((binding, ce))
|
|
|
|
| 556 |
valid.sort(key=lambda x: x[1])
|
| 557 |
if valid: derivation.append(f"\nBOUND-FILTERED: {len(valid)} of {len(raw)} symbolic solutions fall within domains.")
|
| 558 |
else: derivation.append(f"\nBOUND CHECK: all {len(raw)} symbolic solutions lie outside variable domains.")
|
|
|
|
| 559 |
return [v[0] for v in valid], len(valid) > 0, derivation
|
| 560 |
|
| 561 |
def compute_sketch(problem: Problem) -> StructuralSketch:
|
| 562 |
-
affinities = {a: 1.0 for a in _ALL_AXIOMS_PLACEHOLDER}
|
| 563 |
-
|
|
|
|
|
|
|
| 564 |
|
| 565 |
has_conservation = any(mc.weight >= 5.0 for mc in problem.compiled_constraints if mc.kind == "equality")
|
| 566 |
if has_conservation:
|
| 567 |
-
affinities["CONSERVED"] += 3.0
|
|
|
|
| 568 |
notes.append("Conservation laws β CONSERVED/COMPOSITE boosted")
|
| 569 |
|
| 570 |
if problem.bilinear_pairs:
|
|
@@ -572,38 +608,55 @@ def compute_sketch(problem: Problem) -> StructuralSketch:
|
|
| 572 |
notes.append(f"{len(problem.bilinear_pairs)} bilinear pairs β BILINEAR boosted")
|
| 573 |
|
| 574 |
if problem.monotone_targets:
|
| 575 |
-
affinities["MONOTONE_PRODUCT"] += 5.0
|
|
|
|
| 576 |
notes.append(f"{len(problem.monotone_targets)} monotone targets β MPR strongly boosted")
|
| 577 |
|
| 578 |
if problem.ordering_pairs:
|
| 579 |
-
affinities["ORDERED"] += 2.0
|
|
|
|
| 580 |
notes.append(f"{len(problem.ordering_pairs)} ordering constraints β ORDERED boosted")
|
| 581 |
|
| 582 |
if any(problem.scope_vars.values()):
|
| 583 |
-
affinities["DISCRETE"] += 2.0
|
|
|
|
| 584 |
notes.append("Scope structure detected β DISCRETE boosted")
|
| 585 |
|
| 586 |
n_proj = sum(1 for mc in problem.compiled_constraints if mc.projections)
|
| 587 |
if n_proj > 0:
|
| 588 |
-
affinities["ATOMIC"] += 2.0 + n_proj * 0.3
|
|
|
|
|
|
|
| 589 |
notes.append(f"{n_proj} projectable constraints β ATOMIC/IMPLICATION boosted")
|
| 590 |
|
| 591 |
has_sos = any(mc.parsed is not None and mc.parsed.is_Add and any(t.is_Pow and t.args[1] == 2 for t in mc.parsed.args) for mc in problem.compiled_constraints if mc.kind == "equality")
|
| 592 |
if has_sos:
|
| 593 |
-
affinities["METRIC"] += 2.5
|
|
|
|
|
|
|
| 594 |
notes.append("Sum-of-squares β METRIC/QUADRATIC/CONTINUOUS boosted")
|
| 595 |
|
| 596 |
tight = sum(1 for v in problem.variables if abs(problem.bounds[v][1] - problem.bounds[v][0]) < 10)
|
| 597 |
-
if tight > n_vars // 2:
|
|
|
|
|
|
|
| 598 |
|
| 599 |
-
if n_vars >= 6:
|
|
|
|
|
|
|
|
|
|
| 600 |
|
| 601 |
bound_groups = defaultdict(list)
|
| 602 |
for v in problem.variables: bound_groups[problem.bounds[v]].append(v)
|
| 603 |
-
if any(len(g) >= 2 for g in bound_groups.values()):
|
|
|
|
|
|
|
| 604 |
|
| 605 |
has_transcendental = any(mc.parsed is not None and (mc.parsed.has(sp.sin) or mc.parsed.has(sp.cos) or mc.parsed.has(sp.exp)) for mc in problem.compiled_constraints)
|
| 606 |
-
if has_transcendental:
|
|
|
|
|
|
|
|
|
|
| 607 |
|
| 608 |
max_deg = 1
|
| 609 |
for mc in problem.compiled_constraints:
|
|
@@ -622,19 +675,32 @@ def compute_sketch(problem: Problem) -> StructuralSketch:
|
|
| 622 |
n_obs = sum(1 for v in problem.variables if problem.bounds[v][0] == problem.bounds[v][1])
|
| 623 |
n_free_dof = max(0, n_vars - n_obs - n_eq)
|
| 624 |
|
| 625 |
-
exact_solutions = []
|
|
|
|
|
|
|
| 626 |
if n_vars <= SYMPY_MAX_VARS and dom_type in ("linear", "quadratic") and not has_transcendental:
|
| 627 |
exact_solutions, solvable, sympy_derivation = _try_sympy_solve(problem)
|
| 628 |
-
if solvable:
|
| 629 |
-
|
| 630 |
-
|
| 631 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 632 |
|
| 633 |
def generate_templates(problem: Problem, sketch: StructuralSketch) -> List[HypothesisTemplate]:
|
| 634 |
-
templates = []
|
|
|
|
| 635 |
|
| 636 |
for i, sol in enumerate(sketch.exact_solutions):
|
| 637 |
-
templates.append(HypothesisTemplate(
|
|
|
|
|
|
|
|
|
|
| 638 |
|
| 639 |
for mc in problem.compiled_constraints:
|
| 640 |
if mc.kind != "equality" or mc.weight < 5.0 or not mc.projections: continue
|
|
@@ -644,27 +710,40 @@ def generate_templates(problem: Problem, sketch: StructuralSketch) -> List[Hypot
|
|
| 644 |
try:
|
| 645 |
val = float(proj["func"](*[b_mid.get(s, 0.0) for s in proj["syms"]]))
|
| 646 |
if math.isfinite(val) and lo <= val <= hi:
|
| 647 |
-
templates.append(HypothesisTemplate(
|
|
|
|
|
|
|
|
|
|
| 648 |
except: pass
|
| 649 |
|
| 650 |
tb = _global_hc4_tighten_bounds(problem)
|
| 651 |
for v_small, v_large, k in problem.monotone_targets:
|
| 652 |
-
lo_s, hi_s = problem.bounds.get(v_small, (-1e9, 1e9))
|
|
|
|
| 653 |
for ratio in [0.1, 0.25, 0.5, 0.707, 0.9]:
|
| 654 |
vs_sq = k * ratio
|
| 655 |
if vs_sq <= 0: continue
|
| 656 |
vs = math.sqrt(vs_sq); vl = k / vs
|
| 657 |
if not (lo_s <= vs <= hi_s and lo_l <= vl <= hi_l and vs <= vl): continue
|
| 658 |
-
|
|
|
|
|
|
|
|
|
|
| 659 |
box = {u: IV(*tb.get(u, problem.bounds.get(u, (-10, 10)))) for u in problem.variables}
|
| 660 |
-
box[v_small] = IV(vs - 1e-6, vs + 1e-6)
|
|
|
|
| 661 |
cont = _hc4(box, problem.compiled_constraints)
|
|
|
|
| 662 |
pinned = {v_small: vs, v_large: vl}
|
| 663 |
if cont:
|
| 664 |
for u, iv in cont.items():
|
| 665 |
if u in problem.bounds: nb[u] = iv.mid()
|
| 666 |
pinned = {u: nb[u] for u in problem.variables if cont[u].width() < 1e-2}
|
| 667 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 668 |
|
| 669 |
for mc in problem.compiled_constraints:
|
| 670 |
if mc.kind != "equality" or not mc.projections: continue
|
|
@@ -674,29 +753,42 @@ def generate_templates(problem: Problem, sketch: StructuralSketch) -> List[Hypot
|
|
| 674 |
try:
|
| 675 |
val = float(proj["func"](*[b_mid.get(s, 0.0) for s in proj["syms"]]))
|
| 676 |
if math.isfinite(val) and lo <= val <= hi:
|
| 677 |
-
templates.append(HypothesisTemplate(
|
|
|
|
|
|
|
|
|
|
| 678 |
except: pass
|
| 679 |
|
| 680 |
bound_groups = defaultdict(list)
|
| 681 |
for v in problem.variables: bound_groups[problem.bounds[v]].append(v)
|
| 682 |
for bnd, grp in bound_groups.items():
|
| 683 |
if len(grp) < 2: continue
|
| 684 |
-
avg = sum(b_mid[v] for v in grp) / len(grp)
|
|
|
|
| 685 |
if lo <= avg <= hi:
|
| 686 |
pinned = {v: avg for v in grp}
|
| 687 |
-
templates.append(HypothesisTemplate(
|
|
|
|
|
|
|
|
|
|
| 688 |
|
| 689 |
seen = set(); unique = []
|
| 690 |
for t in sorted(templates, key=lambda t: -t.confidence):
|
| 691 |
key = str(sorted(t.pinned_vars.items()))
|
| 692 |
-
if key not in seen:
|
|
|
|
|
|
|
|
|
|
| 693 |
return unique[:TEMPLATE_BATCH_SIZE]
|
| 694 |
|
| 695 |
def templates_to_hypotheses(templates, problem, init_binding):
|
| 696 |
hyps = []
|
| 697 |
for t in templates:
|
| 698 |
-
binding = dict(init_binding)
|
| 699 |
-
|
|
|
|
|
|
|
|
|
|
| 700 |
return hyps
|
| 701 |
|
| 702 |
_ALL_AXIOMS_PLACEHOLDER: List[str] = []
|
|
@@ -706,18 +798,36 @@ _ALL_AXIOMS_PLACEHOLDER: List[str] = []
|
|
| 706 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 707 |
@dataclass
|
| 708 |
class L9Certificate:
|
| 709 |
-
residual_ce: float
|
|
|
|
|
|
|
|
|
|
| 710 |
|
| 711 |
def _batched_deduce_and_evaluate(problem: Problem, hyps: List['Hypothesis']) -> List[Tuple[Dict, float, List[str], str]]:
|
| 712 |
if not hyps: return []
|
| 713 |
-
B = len(hyps)
|
| 714 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 715 |
for hyp in hyps:
|
| 716 |
xr, mr, tr = [], [], []
|
| 717 |
for v in problem.variables:
|
| 718 |
-
if v in hyp.pinned_vars:
|
| 719 |
-
|
| 720 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 721 |
|
| 722 |
X = torch.tensor(x_data, device=DEVICE, dtype=torch.float32, requires_grad=True)
|
| 723 |
mask = torch.tensor(mask_data, device=DEVICE, dtype=torch.float32)
|
|
@@ -731,14 +841,18 @@ def _batched_deduce_and_evaluate(problem: Problem, hyps: List['Hypothesis']) ->
|
|
| 731 |
step_ratio = min(1.0, step / (DEDUCE_ADAM_STEPS * 0.8))
|
| 732 |
ce = problem.tensor_energy(X, step_ratio)
|
| 733 |
|
| 734 |
-
if isinstance(ce, torch.Tensor) and (ce < SOLVE_THRESHOLD).all() and step_ratio == 1.0:
|
| 735 |
-
|
|
|
|
|
|
|
|
|
|
| 736 |
|
| 737 |
with torch.no_grad():
|
| 738 |
X.grad.clamp_(-10.0, 10.0)
|
| 739 |
X.grad *= mask
|
| 740 |
optimizer.step()
|
| 741 |
X.data = torch.where(mask == 0.0, target, X.data)
|
|
|
|
| 742 |
for j, v in enumerate(problem.variables):
|
| 743 |
lo, hi = problem.bounds[v]
|
| 744 |
margin = (hi - lo) * 0.1 * (1.0 - step_ratio) # Exploratory bounds fade to 0
|
|
@@ -750,26 +864,39 @@ def _batched_deduce_and_evaluate(problem: Problem, hyps: List['Hypothesis']) ->
|
|
| 750 |
|
| 751 |
ce_vals = final_ce.detach().cpu().numpy()
|
| 752 |
X_vals = X.detach().cpu().numpy()
|
| 753 |
-
grads_abs = X.grad.abs()
|
| 754 |
-
|
|
|
|
|
|
|
|
|
|
| 755 |
|
| 756 |
results = []
|
| 757 |
for i in range(B):
|
| 758 |
final_b = {problem.variables[j]: float(X_vals[i, j]) for j in range(V)}
|
| 759 |
dom_vars = [problem.variables[idx] for idx in topk_idx_np[i] if float(grads_np[i, idx]) > 1e-4]
|
| 760 |
-
n_dom = len(dom_vars)
|
|
|
|
| 761 |
results.append((final_b, float(ce_vals[i]), dom_vars, tension_class))
|
|
|
|
| 762 |
return results
|
| 763 |
|
| 764 |
def _mprt_sample(problem, work_box, N):
|
| 765 |
-
var_list = problem.variables
|
|
|
|
|
|
|
| 766 |
lo_t = torch.tensor([max(problem.bounds.get(v, (-10.0, 10.0))[0], work_box[v].lo if v in work_box else problem.bounds.get(v, (-10, 10))[0]) for v in var_list], device=DEVICE, dtype=torch.float32)
|
| 767 |
hi_t = torch.tensor([min(problem.bounds.get(v, (-10.0, 10.0))[1], work_box[v].hi if v in work_box else problem.bounds.get(v, (-10, 10))[1]) for v in var_list], device=DEVICE, dtype=torch.float32)
|
|
|
|
| 768 |
for i in range(V):
|
| 769 |
-
if lo_t[i] >= hi_t[i]:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 770 |
X = lo_t.unsqueeze(0) + (hi_t - lo_t).unsqueeze(0) * torch.rand((N, V), device=DEVICE)
|
| 771 |
ce_batch = problem.tensor_energy(X, 1.0)
|
| 772 |
best_idx = torch.argmin(ce_batch).item()
|
|
|
|
| 773 |
return {v: float(X[best_idx, i].item()) for i, v in enumerate(var_list)}, ce_batch[best_idx].item()
|
| 774 |
|
| 775 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -788,7 +915,8 @@ class Axiom:
|
|
| 788 |
COMPOSITE="COMPOSITE"; HOLISM="HOLISM"; PARSIMONY="PARSIMONY"; DUALITY="DUALITY"
|
| 789 |
|
| 790 |
ALL_AXIOMS = [getattr(Axiom, a) for a in dir(Axiom) if not a.startswith("__")]
|
| 791 |
-
AXIOM_ABBR = {a: a[:3] for a in ALL_AXIOMS}
|
|
|
|
| 792 |
_ALL_AXIOMS_PLACEHOLDER.extend(ALL_AXIOMS)
|
| 793 |
|
| 794 |
ADJACENT_CONTRADICTIONS = [
|
|
@@ -813,41 +941,72 @@ RAY_TYPES = ["seed", "branch", "tension", "scout", "recombine", "invert", "targe
|
|
| 813 |
|
| 814 |
@dataclass
|
| 815 |
class Hypothesis:
|
| 816 |
-
hid: str
|
| 817 |
-
|
| 818 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 819 |
|
| 820 |
@dataclass
|
| 821 |
class Baton:
|
| 822 |
-
binding: Dict[str, float]
|
| 823 |
-
|
|
|
|
|
|
|
|
|
|
| 824 |
|
| 825 |
@dataclass
|
| 826 |
class AxiomRay:
|
| 827 |
-
sequence: List[str]
|
| 828 |
-
|
| 829 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 830 |
@property
|
| 831 |
-
def name(self) -> str:
|
|
|
|
|
|
|
| 832 |
def extend(self, axiom: str, rtype: str, new_prior: float = float('inf')) -> Optional['AxiomRay']:
|
| 833 |
new_seq = self.sequence + [axiom]
|
| 834 |
if sequence_valid(new_seq):
|
| 835 |
-
return AxiomRay(
|
| 836 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 837 |
return None
|
| 838 |
|
| 839 |
@dataclass
|
| 840 |
class HypothesisTrace:
|
| 841 |
-
hid: str
|
| 842 |
-
|
| 843 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 844 |
binding: Dict[str, float] = field(default_factory=dict)
|
| 845 |
invariant_results: Dict[str, Tuple[float, bool]] = field(default_factory=dict)
|
| 846 |
-
tension_class: str = "unknown"
|
|
|
|
| 847 |
|
| 848 |
@dataclass
|
| 849 |
class StructuralModel:
|
| 850 |
-
best_binding: Dict[str, float]
|
|
|
|
| 851 |
best_ray: str = "β"
|
| 852 |
failure_patterns: Set[str] = field(default_factory=set)
|
| 853 |
resonant_pairs: List[Tuple[str, str]] = field(default_factory=list)
|
|
@@ -859,11 +1018,15 @@ def _make_hyp(hid, binding, h_type, claim, derivation, pinned, free, conf):
|
|
| 859 |
return Hypothesis(hid=hid, binding=binding, h_type=h_type, claim=claim,
|
| 860 |
derivation=derivation, pinned_vars=pinned, free_vars=free, confidence=conf)
|
| 861 |
|
| 862 |
-
def _hyp_continuous(p, bt, a, m):
|
|
|
|
|
|
|
| 863 |
def _hyp_discrete(p, bt, a, m):
|
| 864 |
-
b = dict(bt.binding)
|
|
|
|
| 865 |
for sn in p.scope_order:
|
| 866 |
-
svars = p.scope_vars.get(sn, [])
|
|
|
|
| 867 |
if svars and smcs:
|
| 868 |
box = {v: IV(b.get(v, 0) - max(0.05 * (p.bounds[v][1] - p.bounds[v][0]), 1e-4),
|
| 869 |
b.get(v, 0) + max(0.05 * (p.bounds[v][1] - p.bounds[v][0]), 1e-4)) for v in svars if v in p.bounds}
|
|
@@ -871,82 +1034,114 @@ def _hyp_discrete(p, bt, a, m):
|
|
| 871 |
if cont:
|
| 872 |
for v, iv in cont.items():
|
| 873 |
b[v] = iv.mid()
|
| 874 |
-
if iv.width() < 1e-2:
|
|
|
|
| 875 |
return [_make_hyp("dis", b, "discrete", "TopoScope", [], pinned, p.variables, 0.80)]
|
| 876 |
|
| 877 |
def _hyp_quadratic(p, bt, a, m):
|
| 878 |
-
hyps = []
|
|
|
|
| 879 |
if bt.l9 and bt.l9.dominant_vars:
|
| 880 |
-
for v in bt.l9.dominant_vars[:2]:
|
|
|
|
| 881 |
return hyps
|
| 882 |
|
| 883 |
def _hyp_bilinear(p, bt, a, m):
|
| 884 |
-
hyps = []
|
|
|
|
| 885 |
for vi, vj in p.bilinear_pairs:
|
| 886 |
-
lo_i, hi_i = p.bounds.get(vi, (0, 10))
|
|
|
|
| 887 |
product = abs(b.get(vi, 1) * b.get(vj, 1))
|
|
|
|
| 888 |
if product <= 0: continue
|
| 889 |
gm = math.sqrt(product)
|
|
|
|
| 890 |
if lo_i <= gm <= hi_i and lo_j <= gm <= hi_j:
|
| 891 |
-
nb = dict(b)
|
|
|
|
| 892 |
hyps.append(_make_hyp(f"bil_eq_{vi}_{vj}", nb, "bilinear", f"GeoMean({vi}={vj}={gm:.3f})", ["bilinear"], {vi: gm, vj: gm}, [v for v in p.variables if v not in [vi, vj]], 0.70))
|
|
|
|
| 893 |
for ratio in [0.4, 0.7071, 0.9]:
|
| 894 |
-
vs = gm * ratio
|
|
|
|
| 895 |
if lo_i <= vs <= hi_i and lo_j <= vl <= hi_j and vs < vl:
|
| 896 |
-
nb2 = dict(b)
|
|
|
|
|
|
|
| 897 |
hyps.append(_make_hyp(f"bil_asc_{int(ratio*100)}_{vi}_{vj}", nb2, "bilinear", f"BilAsc({vi}={vs:.3f}<{vj}={vl:.3f})", ["bilinear"], {vi: vs, vj: vl}, [v for v in p.variables if v not in [vi, vj]], 0.75))
|
| 898 |
return hyps
|
| 899 |
|
| 900 |
def _hyp_monotone_product(p, bt, a, m):
|
| 901 |
-
hyps = []
|
|
|
|
| 902 |
if not p.monotone_targets: return hyps
|
| 903 |
tb = _global_hc4_tighten_bounds(p)
|
|
|
|
| 904 |
for v_small, v_large, k in p.monotone_targets:
|
| 905 |
-
lo_s, hi_s = p.bounds.get(v_small, (-1e9, 1e9))
|
|
|
|
|
|
|
| 906 |
for ratio in [0.25, 0.5, 0.707, 0.9]:
|
| 907 |
vs_sq = k * ratio
|
| 908 |
if vs_sq <= 0: continue
|
| 909 |
-
vs = math.sqrt(vs_sq)
|
|
|
|
| 910 |
if not (lo_s <= vs <= hi_s and lo_l <= vl <= hi_l and vs <= vl): continue
|
| 911 |
-
|
|
|
|
|
|
|
|
|
|
| 912 |
box = {u: IV(*tb.get(u, p.bounds.get(u, (-10, 10)))) for u in p.variables}
|
| 913 |
-
box[v_small] = IV(vs - 1e-6, vs + 1e-6)
|
|
|
|
| 914 |
cont = _hc4(box, p.compiled_constraints)
|
|
|
|
| 915 |
pinned = {v_small: vs, v_large: vl}
|
| 916 |
if cont:
|
| 917 |
for u, iv in cont.items():
|
| 918 |
if u in p.bounds: nb[u] = iv.mid()
|
| 919 |
pinned = {u: nb[u] for u in p.variables if cont[u].width() < 1e-2}
|
|
|
|
| 920 |
hyps.append(_make_hyp(f"mpr_{v_small}_{v_large}_r{int(ratio*100)}", nb, "monotone_product", f"MonoProd({v_small}={vs:.4f}β€{v_large}={vl:.4f})", ["ordered", "hc4"], pinned, [u for u in p.variables if u not in pinned], 0.88))
|
| 921 |
return hyps
|
| 922 |
|
| 923 |
def _hyp_metric(p, bt, a, m):
|
| 924 |
-
hyps = []
|
|
|
|
| 925 |
for mc in p.compiled_constraints:
|
| 926 |
if mc.kind != "equality" or not mc.parsed: continue
|
| 927 |
if not mc.parsed.is_Add: continue
|
|
|
|
| 928 |
sq_terms = [t for t in mc.parsed.args if t.is_Pow and t.args[1] == 2]
|
| 929 |
if len(sq_terms) < 1: continue
|
| 930 |
vars_in = [str(s) for s in mc.parsed.free_symbols if str(s) in p.variables]
|
| 931 |
if not vars_in: continue
|
|
|
|
| 932 |
const_terms = [float(t) for t in mc.parsed.args if t.is_Number]
|
| 933 |
if not const_terms: continue
|
|
|
|
| 934 |
target = -const_terms[0]
|
| 935 |
if target <= 0: continue
|
|
|
|
| 936 |
curr_val = sum(b.get(v, 0)**2 for v in vars_in)
|
| 937 |
if curr_val < 1e-8: continue
|
|
|
|
| 938 |
scale = math.sqrt(target / curr_val)
|
| 939 |
nb = dict(b)
|
| 940 |
for v in vars_in:
|
| 941 |
lo, hi = p.bounds.get(v, (-10, 10))
|
| 942 |
nb[v] = max(lo, min(hi, b.get(v, 0) * scale))
|
|
|
|
| 943 |
hyps.append(_make_hyp(f"met_{hash(mc.expr_str)%9999}", nb, "metric", f"RadialProject(scale={scale:.4f},dim={len(vars_in)})", ["metric", mc.expr_str], {}, list(p.variables), 0.75))
|
| 944 |
return hyps
|
| 945 |
|
| 946 |
def _hyp_symmetric(p, bt, a, m):
|
| 947 |
-
hyps = []
|
|
|
|
| 948 |
groups_to_check = list(p.scope_vars.values()) if p.scope_vars else [p.variables]
|
| 949 |
-
if not any(p.scope_vars.values()):
|
|
|
|
| 950 |
|
| 951 |
seen_pairs = set()
|
| 952 |
for grp in groups_to_check:
|
|
@@ -957,14 +1152,21 @@ def _hyp_symmetric(p, bt, a, m):
|
|
| 957 |
vi, vj = vl[i], vl[j]
|
| 958 |
if (vi, vj) in seen_pairs: continue
|
| 959 |
seen_pairs.add((vi, vj))
|
| 960 |
-
|
|
|
|
|
|
|
| 961 |
bvi, bvj = b.get(vi, 0), b.get(vj, 0)
|
|
|
|
| 962 |
if lo_i <= bvj <= hi_i and lo_j <= bvi <= hi_j:
|
| 963 |
-
nb = dict(b)
|
|
|
|
| 964 |
hyps.append(_make_hyp(f"sym_{vi}_{vj}", nb, "symmetric", f"Swap({vi}β{vj})", ["symmetric"], {vi: nb[vi], vj: nb[vj]}, [v for v in p.variables if v not in [vi, vj]], 0.60))
|
|
|
|
| 965 |
avg = (bvi + bvj) / 2
|
| 966 |
if lo_i <= avg <= hi_i and lo_j <= avg <= hi_j:
|
| 967 |
-
nb2 = dict(b)
|
|
|
|
|
|
|
| 968 |
hyps.append(_make_hyp(f"sym_avg_{vi}_{vj}", nb2, "symmetric", f"Average({vi}={vj}={avg:.4f})", ["symmetric"], {vi: avg, vj: avg}, [v for v in p.variables if v not in [vi, vj]], 0.55))
|
| 969 |
return hyps[:10]
|
| 970 |
|
|
@@ -975,24 +1177,29 @@ def _hyp_conserved(p, bt, a, m): return [_make_hyp("csv", bt.binding, "conserved
|
|
| 975 |
def _hyp_mutable(p, bt, a, m):
|
| 976 |
b = dict(bt.binding)
|
| 977 |
if bt.l9 and bt.l9.dominant_vars:
|
| 978 |
-
v = bt.l9.dominant_vars[0]
|
|
|
|
| 979 |
b[v] = max(lo, min(hi, b.get(v, 0) + random.gauss(0, (hi - lo) * 0.05)))
|
| 980 |
return [_make_hyp("mut", b, "mutable", "Perturb", [], {}, p.variables, 0.40)]
|
| 981 |
def _hyp_network(p, bt, a, m): return [_make_hyp("net", bt.binding, "network", "HubProp", [], {}, p.variables, 0.65)]
|
| 982 |
def _hyp_equilibrium(p, bt, a, m): return [_make_hyp("eql", bt.binding, "equilibrium", "GradBal", [], {}, p.variables, 0.72)]
|
| 983 |
def _hyp_superposition(p, bt, a, m):
|
| 984 |
if a and len(a) > 0:
|
| 985 |
-
other = random.choice(a)
|
|
|
|
| 986 |
nb = {v: lam * bt.binding.get(v, 0) + (1 - lam) * other.binding.get(v, 0) for v in p.variables}
|
| 987 |
return [_make_hyp("sup", nb, "superposition", "Superpose", [], {}, p.variables, 0.58)]
|
| 988 |
return []
|
| 989 |
def _hyp_locality(p, bt, a, m): return [_make_hyp("loc", bt.binding, "locality", "LocalFirst", [], {}, p.variables, 0.72)]
|
| 990 |
def _hyp_extremal(p, bt, a, m):
|
| 991 |
-
hyps = []
|
|
|
|
| 992 |
if bt.l9 and bt.l9.dominant_vars:
|
| 993 |
-
v = bt.l9.dominant_vars[0]
|
|
|
|
| 994 |
for val in [lo, hi, (lo + hi) / 2]:
|
| 995 |
-
nb = dict(b)
|
|
|
|
| 996 |
hyps.append(_make_hyp(f"ext_{v}_{val:.3f}", nb, "extremal", f"PinBound({v}={val:.3f})", [], {v: val}, p.variables, 0.65))
|
| 997 |
return hyps
|
| 998 |
def _hyp_entropy(p, bt, a, m): return [_make_hyp("ent", {v: random.uniform(*p.bounds[v]) for v in p.variables}, "entropy", "MaxEnt", [], {}, p.variables, 0.48)]
|
|
@@ -1000,7 +1207,8 @@ def _hyp_injective(p, bt, a, m): return [_make_hyp("inj", bt.binding, "injective
|
|
| 1000 |
def _hyp_surjective(p, bt, a, m): return [_make_hyp("sur", bt.binding, "surjective", "Sweep", [], {}, p.variables, 0.45)]
|
| 1001 |
def _hyp_transitive(p, bt, a, m): return [_make_hyp("tra", bt.binding, "transitive", "TransSnap", [], {}, p.variables, 0.77)]
|
| 1002 |
def _hyp_atomic(p, bt, a, m):
|
| 1003 |
-
hyps = []
|
|
|
|
| 1004 |
for mc in p.compiled_constraints:
|
| 1005 |
if not mc.projections: continue
|
| 1006 |
for v, projs in mc.projections.items():
|
|
@@ -1009,7 +1217,8 @@ def _hyp_atomic(p, bt, a, m):
|
|
| 1009 |
val = float(proj["func"](*[b.get(s, 0.0) for s in proj["syms"]]))
|
| 1010 |
lo, hi = p.bounds.get(v, (-1e9, 1e9))
|
| 1011 |
if math.isfinite(val) and lo <= val <= hi:
|
| 1012 |
-
nb = dict(b)
|
|
|
|
| 1013 |
hyps.append(_make_hyp(f"ato_{v}", nb, "atomic", f"Solve({v})", [], {v: val}, p.variables, 0.70))
|
| 1014 |
break
|
| 1015 |
except: pass
|
|
@@ -1022,11 +1231,14 @@ def _hyp_negation(p, bt, a, m):
|
|
| 1022 |
def _hyp_composite(p, bt, a, m): return [_make_hyp("cmp", bt.binding, "composite", "Enz", [], {}, p.variables, 0.90)]
|
| 1023 |
def _hyp_holism(p, bt, a, m): return [_make_hyp("hol", bt.binding, "holism", "Global", [], {}, p.variables, 0.73)]
|
| 1024 |
def _hyp_parsimony(p, bt, a, m):
|
| 1025 |
-
b = dict(bt.binding)
|
|
|
|
| 1026 |
max_val = max((abs(v) for v in b.values()), default=1.0)
|
| 1027 |
for v in p.variables:
|
| 1028 |
-
val = b[v]
|
| 1029 |
-
|
|
|
|
|
|
|
| 1030 |
else:
|
| 1031 |
candidates = [round(val * m) / m for m in [1, 2, 4] if lo <= round(val * m) / m <= hi]
|
| 1032 |
nb[v] = min(candidates, key=lambda c: abs(c - val)) if candidates else val
|
|
@@ -1080,9 +1292,13 @@ class CreativeSeeder:
|
|
| 1080 |
scored = []
|
| 1081 |
for ax in remaining_axioms:
|
| 1082 |
w_allos = 1.0
|
| 1083 |
-
if n_dom == 1 and ax in isolated:
|
| 1084 |
-
|
| 1085 |
-
elif n_dom
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1086 |
w_sketch = sketch.axiom_affinities.get(ax, 1.0) if sketch else 1.0
|
| 1087 |
scored.append((w_allos * w_sketch, ax))
|
| 1088 |
|
|
@@ -1090,7 +1306,9 @@ class CreativeSeeder:
|
|
| 1090 |
children = []
|
| 1091 |
for _, axiom in scored[:effective_width]:
|
| 1092 |
child = ray.extend(axiom, "branch", new_prior=out_baton.ce)
|
| 1093 |
-
if child:
|
|
|
|
|
|
|
| 1094 |
return children
|
| 1095 |
|
| 1096 |
def sketch_weighted_seeds(self, sketch: StructuralSketch, init_ce: float) -> List[AxiomRay]:
|
|
@@ -1109,17 +1327,24 @@ class CreativeSeeder:
|
|
| 1109 |
if b2 in (a, b1, mid, c): continue
|
| 1110 |
if frozenset([mid, b2]) not in _CONTRA_SET and frozenset([b2, c]) not in _CONTRA_SET:
|
| 1111 |
results.append(AxiomRay([a, b1, mid, b2, c], f"T5_{AXIOM_ABBR.get(a, '?')}_{AXIOM_ABBR.get(c, '?')}", "tension"))
|
| 1112 |
-
random.shuffle(results)
|
|
|
|
| 1113 |
|
| 1114 |
def random_scouts(self, n: int = 600) -> List[AxiomRay]:
|
| 1115 |
-
scouts = []
|
|
|
|
| 1116 |
while len(scouts) < n and attempts < n * 30:
|
| 1117 |
-
attempts += 1
|
| 1118 |
-
|
|
|
|
|
|
|
|
|
|
| 1119 |
for ax in pool[1:]:
|
| 1120 |
if len(seq) >= length: break
|
| 1121 |
-
if ax != seq[-1] and frozenset([seq[-1], ax]) not in _CONTRA_SET:
|
| 1122 |
-
|
|
|
|
|
|
|
| 1123 |
return scouts
|
| 1124 |
|
| 1125 |
def recombine(self, ray_a, ray_b, ba, bb) -> List[AxiomRay]:
|
|
@@ -1131,21 +1356,26 @@ class CreativeSeeder:
|
|
| 1131 |
cut = min(len(ray_a.sequence), len(ray_b.sequence)) // 2
|
| 1132 |
if cut > 0:
|
| 1133 |
seq = ray_a.sequence[:cut] + [x for x in ray_b.sequence[cut:] if x not in ray_a.sequence[:cut]]
|
| 1134 |
-
if sequence_valid(seq):
|
|
|
|
| 1135 |
return results
|
| 1136 |
|
| 1137 |
def invert(self, ray, parent_ce) -> Optional[AxiomRay]:
|
| 1138 |
inv = list(reversed(ray.sequence))
|
| 1139 |
-
if sequence_valid(inv) and inv != ray.sequence:
|
|
|
|
| 1140 |
return None
|
| 1141 |
|
| 1142 |
def resonance_extensions(self, ray, parent_ce, resonant_pairs) -> List[AxiomRay]:
|
| 1143 |
if not ray.sequence or not resonant_pairs: return []
|
| 1144 |
-
last = ray.sequence[-1]
|
|
|
|
| 1145 |
nexts = [b for (a, b) in resonant_pairs if a == last and b != last and frozenset([a, b]) not in _CONTRA_SET and b not in ray.sequence]
|
| 1146 |
for b in nexts:
|
| 1147 |
child = ray.extend(b, "branch", new_prior=parent_ce)
|
| 1148 |
-
if child:
|
|
|
|
|
|
|
| 1149 |
return results
|
| 1150 |
|
| 1151 |
CREATIVE_SEEDER = CreativeSeeder()
|
|
@@ -1159,15 +1389,25 @@ def _verify(binding, base_problem, anchors):
|
|
| 1159 |
g2 = {}
|
| 1160 |
for inv in anchors:
|
| 1161 |
try:
|
| 1162 |
-
if inv.compiled_func:
|
| 1163 |
-
|
|
|
|
|
|
|
|
|
|
| 1164 |
err = abs(val)
|
| 1165 |
-
if inv.mode == "eq":
|
| 1166 |
-
|
| 1167 |
-
elif inv.mode == "
|
| 1168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1169 |
g2[inv.name] = (round(val if inv.mode in ("geq", "leq") else err, 6), passed)
|
| 1170 |
-
except:
|
|
|
|
|
|
|
| 1171 |
g2_pass = all(v[1] for v in g2.values()) if g2 else True
|
| 1172 |
return g1_pass, g2_pass, g2, round(g1_ce, 6)
|
| 1173 |
|
|
@@ -1178,55 +1418,77 @@ class SequenceRayTracer:
|
|
| 1178 |
|
| 1179 |
def trace(self, axl_def: AXLProblemDef, base_problem: Problem):
|
| 1180 |
hero_traces: List[HypothesisTrace] = []
|
| 1181 |
-
baton_registry: Dict[str, Baton] = {}
|
| 1182 |
-
|
|
|
|
|
|
|
| 1183 |
|
| 1184 |
for inv in axl_def.anchors:
|
| 1185 |
-
if not inv.compiled_func:
|
|
|
|
| 1186 |
|
| 1187 |
-
_update_state(phase="SKETCHING")
|
|
|
|
| 1188 |
sketch = compute_sketch(base_problem)
|
| 1189 |
_update_state(sketch_summary="; ".join(sketch.sketch_notes[:4]), sympy_derivation=sketch.sympy_derivation)
|
| 1190 |
_add_log(f"β Sketch: {sketch.dominant_type} system, DOF={sketch.n_free_dof}")
|
| 1191 |
|
| 1192 |
-
_update_state(phase="TEMPLATING")
|
|
|
|
| 1193 |
templates = generate_templates(base_problem, sketch)
|
| 1194 |
_update_state(template_count=len(templates))
|
| 1195 |
|
| 1196 |
init_b, init_ce = _mprt_sample(base_problem, {v: IV(*base_problem.bounds[v]) for v in base_problem.variables}, N_MPRT_EXPLORE)
|
| 1197 |
seed_baton = Baton(binding=init_b, ce=init_ce, ray_id="SEED", l9=L9Certificate(init_ce, base_problem.variables[:3], [], "systemic"))
|
| 1198 |
|
| 1199 |
-
best_ce = init_ce
|
|
|
|
|
|
|
| 1200 |
if templates:
|
| 1201 |
_add_log("β Evaluating templates (Phase 0 batch)β¦")
|
| 1202 |
template_hyps = templates_to_hypotheses(templates, base_problem, init_b)
|
| 1203 |
t_results = _batched_deduce_and_evaluate(base_problem, template_hyps)
|
|
|
|
| 1204 |
for (th, template), (final_b, final_ce, dom_vars, tc) in zip(zip(template_hyps, templates), t_results):
|
| 1205 |
g1p, g2p, inv_res, g1ce = _verify(final_b, base_problem, axl_def.anchors)
|
| 1206 |
overall = g1p and g2p
|
|
|
|
| 1207 |
if overall or final_ce < best_ce:
|
| 1208 |
hero_traces.append(HypothesisTrace(
|
| 1209 |
hid=template.template_id, round_idx=0, ray_name=f"template:{template.source}", ray_type="template",
|
| 1210 |
ce_before=init_ce, ce_after=final_ce, survived=overall, elapsed_ms=0.0,
|
| 1211 |
g1_pass=g1p, g2_pass=g2p, binding={k: round(v, 5) for k, v in final_b.items()},
|
| 1212 |
invariant_results=inv_res, tension_class=tc, depth=0))
|
| 1213 |
-
|
|
|
|
|
|
|
|
|
|
| 1214 |
if final_ce < best_ce:
|
| 1215 |
-
best_ce = final_ce
|
|
|
|
| 1216 |
_update_state(best_ce=best_ce)
|
|
|
|
| 1217 |
if overall:
|
| 1218 |
_add_log(f"β Template solved at Phase 0! Source: {template.source}")
|
| 1219 |
_update_state(best_ce=best_ce, template_best_ce=best_ce, best_ray=f"template:{template.source}")
|
| 1220 |
return best_binding, best_ce, hero_traces, 0, {"isolated": 0, "relational": 0, "systemic": 0}
|
|
|
|
| 1221 |
_update_state(template_best_ce=best_ce)
|
| 1222 |
|
| 1223 |
_update_state(phase="SEARCHING")
|
| 1224 |
seed_rays = CREATIVE_SEEDER.sketch_weighted_seeds(sketch, best_ce)
|
| 1225 |
|
| 1226 |
-
queues = {
|
| 1227 |
-
|
| 1228 |
-
|
| 1229 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1230 |
allosteric_counts = {"isolated": 0, "relational": 0, "systemic": 0}
|
| 1231 |
model = StructuralModel(best_binding, best_ce)
|
| 1232 |
seed_baton = Baton(binding=best_binding, ce=best_ce, ray_id="SEED", l9=L9Certificate(best_ce, base_problem.variables[:3], [], "systemic"))
|
|
@@ -1239,31 +1501,39 @@ class SequenceRayTracer:
|
|
| 1239 |
q_idx = (q_idx + 1) % 3
|
| 1240 |
if q_idx == start_idx: break
|
| 1241 |
if not any(queues[k] for k in queue_order): break
|
| 1242 |
-
ray = queues[queue_order[q_idx]].pop(0)
|
| 1243 |
-
|
|
|
|
|
|
|
|
|
|
| 1244 |
if not batch_rays: break
|
| 1245 |
|
| 1246 |
t0 = time.time()
|
| 1247 |
historical_batons = list(baton_registry.values())
|
| 1248 |
batch_hyps: List[Tuple[int, Hypothesis]] = []
|
|
|
|
| 1249 |
for i, ray in enumerate(batch_rays):
|
| 1250 |
p_baton = ray.baton or seed_baton
|
| 1251 |
constructor = AXIOM_CONSTRUCTORS.get(ray.sequence[-1])
|
| 1252 |
hyps = constructor(base_problem, p_baton, historical_batons, model) if constructor else []
|
| 1253 |
-
if not hyps:
|
|
|
|
| 1254 |
batch_hyps.append((i, hyps[0]))
|
| 1255 |
|
| 1256 |
eval_results = _batched_deduce_and_evaluate(base_problem, [h for _, h in batch_hyps])
|
| 1257 |
elapsed_ms = (time.time() - t0) * 1000 / max(1, len(batch_rays))
|
| 1258 |
|
| 1259 |
-
solved = False
|
|
|
|
|
|
|
| 1260 |
for (ray_idx, hyp), (final_b, final_ce, dom_vars, tension_class) in zip(batch_hyps, eval_results):
|
| 1261 |
ray = batch_rays[ray_idx]
|
| 1262 |
parent_ce = (ray.baton or seed_baton).ce
|
| 1263 |
allosteric_counts[tension_class] = allosteric_counts.get(tension_class, 0) + 1
|
| 1264 |
|
| 1265 |
g1_pass, g2_pass, inv_results, g1_ce = _verify(final_b, base_problem, axl_def.anchors)
|
| 1266 |
-
overall_pass = g1_pass and g2_pass
|
|
|
|
| 1267 |
|
| 1268 |
if improved or overall_pass or random.random() < 0.002:
|
| 1269 |
trace = HypothesisTrace(
|
|
@@ -1277,21 +1547,30 @@ class SequenceRayTracer:
|
|
| 1277 |
out_baton = Baton(binding=final_b, ce=final_ce, ray_id=ray.ray_id, l9=L9Certificate(final_ce, dom_vars, [], tension_class))
|
| 1278 |
|
| 1279 |
if final_ce < BATON_REGISTRY_THRESHOLD:
|
| 1280 |
-
if ray.ray_id in baton_registry:
|
|
|
|
| 1281 |
else:
|
| 1282 |
if len(baton_registry) >= BATON_REGISTRY_MAX:
|
| 1283 |
-
old_key = baton_registry_keys.popleft()
|
| 1284 |
-
|
|
|
|
|
|
|
| 1285 |
|
| 1286 |
if improved:
|
| 1287 |
-
best_ce = final_ce
|
| 1288 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1289 |
|
| 1290 |
-
if overall_pass:
|
|
|
|
| 1291 |
|
| 1292 |
if improved and len(ray.sequence) >= 2:
|
| 1293 |
pair = (ray.sequence[-2], ray.sequence[-1])
|
| 1294 |
-
if pair not in resonant_pairs:
|
|
|
|
| 1295 |
model.resonant_pairs = resonant_pairs
|
| 1296 |
|
| 1297 |
earned = (final_ce < parent_ce * CE_EARN_RATIO or ray.depth < 1)
|
|
@@ -1301,25 +1580,39 @@ class SequenceRayTracer:
|
|
| 1301 |
remaining = [a for a in ALL_AXIOMS if a != ray.sequence[-1] and frozenset([ray.sequence[-1], a]) not in _CONTRA_SET and a not in ray.sequence]
|
| 1302 |
new_children = []
|
| 1303 |
new_children.extend(CREATIVE_SEEDER.intelligent_branch(ray, out_baton, remaining, BRANCH_WIDTH, sketch=sketch))
|
|
|
|
| 1304 |
inv = CREATIVE_SEEDER.invert(ray, final_ce)
|
| 1305 |
-
if inv:
|
|
|
|
|
|
|
| 1306 |
if len(successful_rays) >= 2:
|
| 1307 |
candidates = [r for r in successful_rays if r.ray_id != ray.ray_id]
|
| 1308 |
if candidates:
|
| 1309 |
-
partner = random.choice(candidates)
|
| 1310 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1311 |
new_children.extend(CREATIVE_SEEDER.resonance_extensions(ray, final_ce, resonant_pairs))
|
|
|
|
| 1312 |
for child in new_children:
|
| 1313 |
-
if child.ray_type in ("seed", "branch", "target"):
|
| 1314 |
-
|
| 1315 |
-
elif child.ray_type in ("
|
|
|
|
|
|
|
|
|
|
| 1316 |
|
| 1317 |
queues["core"].sort(key=lambda r: r.ce_prior + (r.depth * 0.0001))
|
| 1318 |
queues["genetic"].sort(key=lambda r: r.ce_prior + (r.depth * 0.0001))
|
| 1319 |
|
| 1320 |
with STATE_LOCK:
|
| 1321 |
-
GLOBAL_SOLVE_STATE["best_ce"] = best_ce
|
| 1322 |
-
|
|
|
|
|
|
|
|
|
|
| 1323 |
|
| 1324 |
if solved: break
|
| 1325 |
|
|
@@ -1363,84 +1656,149 @@ def encode_problem_to_axl(problem_text, api_key) -> AXLProblemDef:
|
|
| 1363 |
resp = client.models.generate_content(model=GEMINI_MODEL, contents=[types.Content(role="user", parts=[types.Part.from_text(text=problem_text)])], config=config)
|
| 1364 |
|
| 1365 |
text = resp.text.strip()
|
| 1366 |
-
if text.startswith("```"):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1367 |
text = text.strip().rstrip("`").strip()
|
| 1368 |
d = json.loads(text)
|
| 1369 |
|
| 1370 |
anchors = [AXLInvariant(name=a["name"], expr=a["expr"], tolerance=a.get("tolerance", VERIFY_G2_TOLERANCE), mode=a.get("mode", "eq")) for a in d.get("anchors", [])]
|
| 1371 |
variables = [{"name": v["name"], "lo": float(v.get("lo", -1000.0)), "hi": float(v.get("hi", 1000.0))} for v in d["variables"]]
|
|
|
|
| 1372 |
return AXLProblemDef(name=d["name"], description=d.get("description", ""), axioms=set(), variables=variables, constraints=d.get("constraints", []), scopes=d.get("scopes", []), anchors=anchors, observations=d.get("observations", {}))
|
| 1373 |
|
| 1374 |
def collapse_solution(problem_text, axl_def, psl_text, binding, g1_pass, g2_pass, inv_results, best_ray, total_fired, sketch_notes, sympy_derivation, api_key) -> str:
|
| 1375 |
if not api_key: return "ERROR: API Key required."
|
| 1376 |
client = genai.Client(api_key=api_key)
|
| 1377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1378 |
config = types.GenerateContentConfig(thinking_config=types.ThinkingConfig(thinking_level="HIGH"), system_instruction=[types.Part.from_text(text=COLLAPSER_SYSTEM_PROMPT)], temperature=0.2)
|
| 1379 |
resp = client.models.generate_content(model=GEMINI_MODEL, contents=[types.Content(role="user", parts=[types.Part.from_text(text=json.dumps(payload, indent=2))])], config=config)
|
| 1380 |
return resp.text
|
| 1381 |
|
| 1382 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1383 |
-
# SECTION 15: GLOBAL SOLVE TASK
|
| 1384 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1385 |
def global_solve_task(original_problem_text, api_key, prebuilt_axl=None):
|
| 1386 |
-
_update_state(
|
| 1387 |
-
|
| 1388 |
-
|
| 1389 |
-
|
| 1390 |
-
|
| 1391 |
-
|
| 1392 |
-
|
| 1393 |
-
|
| 1394 |
-
|
| 1395 |
-
|
| 1396 |
-
|
| 1397 |
-
|
| 1398 |
-
|
| 1399 |
-
|
| 1400 |
-
|
| 1401 |
-
|
| 1402 |
-
|
| 1403 |
-
|
| 1404 |
-
|
| 1405 |
-
|
| 1406 |
-
|
| 1407 |
-
|
| 1408 |
-
|
| 1409 |
-
|
| 1410 |
-
|
| 1411 |
-
|
| 1412 |
-
|
| 1413 |
-
|
| 1414 |
-
|
| 1415 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1416 |
try:
|
| 1417 |
-
|
| 1418 |
-
|
| 1419 |
-
|
| 1420 |
-
except
|
| 1421 |
-
|
| 1422 |
-
|
| 1423 |
-
|
| 1424 |
-
|
| 1425 |
-
|
| 1426 |
-
|
| 1427 |
-
|
| 1428 |
-
|
| 1429 |
-
|
| 1430 |
-
|
| 1431 |
-
if not g2_pass and attempt < MAX_ATTEMPTS:
|
| 1432 |
-
failed = {k: v for k, (v, ok) in inv_results.items() if not ok}
|
| 1433 |
-
current_text = (original_problem_text + f"\n\nPREVIOUS ATTEMPT FAILED:\nGate 2 failed:\n{json.dumps(failed, indent=2)}\nRevise constraint encoding to capture these conditions.")
|
| 1434 |
-
_add_log("β Gate 2 failed. Retrying with structural feedbackβ¦"); continue
|
| 1435 |
-
|
| 1436 |
-
_add_log("π€ Collapsing isomorphism to domain languageβ¦")
|
| 1437 |
-
_update_state(phase="COLLAPSING")
|
| 1438 |
-
try:
|
| 1439 |
-
answer = collapse_solution(original_problem_text, axl_def, psl_text, binding, g1_pass, g2_pass, inv_results, best_ray, total_fired, sketch_notes, current_sympy_derivation, used_key)
|
| 1440 |
-
_update_state(answer=answer, phase="DONE"); _add_log("β Done.")
|
| 1441 |
-
except Exception as e: _update_state(answer=f"Collapsing error: {e}", phase="ERROR"); _add_log("β Collapse failed.")
|
| 1442 |
-
break
|
| 1443 |
-
_update_state(is_running=False)
|
| 1444 |
|
| 1445 |
def trigger_solve(problem_text, api_key):
|
| 1446 |
if GLOBAL_SOLVE_STATE["is_running"] or not problem_text.strip(): return
|
|
@@ -1448,28 +1806,46 @@ def trigger_solve(problem_text, api_key):
|
|
| 1448 |
|
| 1449 |
def trigger_quantum_solve(example_name, api_key):
|
| 1450 |
if not HAS_QUANTUM or GLOBAL_SOLVE_STATE["is_running"]: return
|
| 1451 |
-
_update_state(is_running=True)
|
| 1452 |
|
| 1453 |
-
|
| 1454 |
-
|
| 1455 |
-
|
| 1456 |
-
|
| 1457 |
-
|
| 1458 |
-
|
| 1459 |
-
|
| 1460 |
-
|
| 1461 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1462 |
|
| 1463 |
-
threading.Thread(target=
|
| 1464 |
|
| 1465 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1466 |
# SECTION 16: GRADIO INTERFACE
|
| 1467 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1468 |
-
|
| 1469 |
-
|
| 1470 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1471 |
|
| 1472 |
-
RAY_ICONS = {"seed": "π±", "branch": "πΏ", "tension": "β‘", "scout": "π", "recombine": "π§¬", "invert": "π", "target": "π―", "template": "πΊ", "fallback": "Β·"}
|
| 1473 |
PLACEHOLDER_HINT = textwrap.dedent("""
|
| 1474 |
Try any natural language problem. Gemini encodes it, the system finds the structural solution.
|
| 1475 |
Examples:
|
|
@@ -1479,28 +1855,50 @@ PLACEHOLDER_HINT = textwrap.dedent("""
|
|
| 1479 |
|
| 1480 |
def build_live_html():
|
| 1481 |
with STATE_LOCK:
|
| 1482 |
-
phase = GLOBAL_SOLVE_STATE["phase"]
|
| 1483 |
-
|
| 1484 |
-
|
|
|
|
|
|
|
|
|
|
| 1485 |
sketch_summary = GLOBAL_SOLVE_STATE["sketch_summary"]
|
| 1486 |
-
template_count = GLOBAL_SOLVE_STATE["template_count"]
|
|
|
|
| 1487 |
|
| 1488 |
ce_color = "#4CAF50" if ce < SOLVE_THRESHOLD else "#FF9800"
|
| 1489 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1490 |
|
| 1491 |
log_html = "<ul style='margin:0;padding-left:20px;color:#aaa;font-size:0.82em'>"
|
| 1492 |
-
for l in logs[-5:]:
|
|
|
|
| 1493 |
log_html += "</ul>"
|
| 1494 |
|
| 1495 |
-
sketch_html =
|
| 1496 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1497 |
|
| 1498 |
ray_trail = ""
|
| 1499 |
for t in reversed(traces):
|
| 1500 |
-
icon = RAY_ICONS.get(t.ray_type, "Β·")
|
|
|
|
|
|
|
| 1501 |
ray_trail += f"<div style='color:{c};font-size:0.78em;margin-bottom:2px'>{icon} [{t.ray_name}] CE={t.ce_after:.4f} <span style='color:#888'>({t.tension_class[:3]})</span><span style='color:#4CAF50;font-weight:700'>{star}</span></div>"
|
| 1502 |
|
| 1503 |
-
return f"""
|
|
|
|
| 1504 |
<div style='color:{phase_color};font-weight:bold;margin-bottom:8px'>β Phase: {phase}</div>
|
| 1505 |
<div style='margin-bottom:10px;border-bottom:1px solid #222;padding-bottom:8px'>{log_html}</div>
|
| 1506 |
{sketch_html}{template_html}
|
|
@@ -1510,38 +1908,55 @@ def build_live_html():
|
|
| 1510 |
</div>
|
| 1511 |
<div style='color:#aaa;margin-bottom:8px;font-size:0.85em'>Best Iso: <span style='color:#FF9800'>{best_ray}</span></div>
|
| 1512 |
<div style='flex:1;overflow-y:auto;border-top:1px solid #222;padding-top:8px'>{ray_trail}</div>
|
| 1513 |
-
</div>
|
|
|
|
| 1514 |
|
| 1515 |
with gr.Blocks(css=CSS, title="Practicality 24.1") as demo:
|
| 1516 |
gr.Markdown("## β Practicality 24.1 β Structural Sketch, World Model Prior & Quantum Engine\n`[Gemini Encoder] β [Structural Sketch / SymPy] β [Morphing Ray Solver] β [Gemini Collapser]`")
|
| 1517 |
-
|
| 1518 |
-
|
|
|
|
| 1519 |
api_key_input = gr.Textbox(label="Gemini API Key", type="password", placeholder="AIza...", value=DEFAULT_GEMINI_API_KEY, elem_classes=["solver-log"])
|
| 1520 |
with gr.Tabs():
|
| 1521 |
with gr.Tab("Natural Language"):
|
| 1522 |
problem_input = gr.Textbox(label="Problem Description", placeholder=PLACEHOLDER_HINT, lines=5, elem_classes=["solver-log"])
|
| 1523 |
with gr.Row():
|
| 1524 |
-
solve_btn = gr.Button("β Solve Natural Language", variant="primary")
|
|
|
|
|
|
|
| 1525 |
if HAS_QUANTUM:
|
| 1526 |
with gr.Tab("Quantum Circuits (Heisenberg Abstraction)"):
|
| 1527 |
q_dropdown = gr.Dropdown(choices=["Bell State", "VQE H2", "QAOA MaxCut"], label="Select Circuit Template", value="Bell State")
|
| 1528 |
q_solve_btn = gr.Button("β Run Quantum Solver (Bypass Encoder)", variant="primary")
|
| 1529 |
-
|
| 1530 |
-
|
| 1531 |
-
|
| 1532 |
-
|
| 1533 |
-
|
| 1534 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1535 |
|
| 1536 |
def fetch_ui():
|
| 1537 |
while True:
|
| 1538 |
-
time.sleep(1.0)
|
|
|
|
| 1539 |
|
| 1540 |
solve_btn.click(fn=trigger_solve, inputs=[problem_input, api_key_input], outputs=None)
|
| 1541 |
clear_btn.click(fn=lambda: ("", "", ""), inputs=[], outputs=[problem_input, live_html, answer_box])
|
| 1542 |
-
|
|
|
|
|
|
|
|
|
|
| 1543 |
demo.load(fetch_ui, inputs=None, outputs=[live_html, answer_box])
|
| 1544 |
|
| 1545 |
if __name__ == "__main__":
|
| 1546 |
print(f"[SYSTEM 24.1] Compute: {DEVICE.type.upper()} | Feature Flags: Quantum={HAS_QUANTUM}")
|
| 1547 |
-
demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
PRACTICALITY SYSTEM 24.1 β STRUCTURAL SKETCH, QUANTUM ENGINE & HOMOTOPY CONTINUATION
|
| 4 |
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 9 |
β [WISDOM LAYER] β Sketch-weighted rays + Masked Deduction (with Homotopy)
|
| 10 |
β [GEMINI COLLAPSER] β Domain-language explanation
|
| 11 |
|
| 12 |
+
CRITICAL STABILITY FIXES:
|
| 13 |
+
1. Thread Crash Safety: Entire solver loop wrapped in try/finally to prevent UI lockups.
|
| 14 |
+
2. UI Responsive Layout: Unminified HTML generators and removed nested f-strings.
|
| 15 |
+
3. Expanded Axiom Logic: Restored full readability of structural heuristics.
|
|
|
|
| 16 |
"""
|
| 17 |
|
| 18 |
import os, time, random, math, threading, warnings, json, textwrap
|
|
|
|
| 42 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 43 |
# AI CONFIGURATION
|
| 44 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 45 |
+
DEFAULT_GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
|
| 46 |
+
GEMINI_MODEL = "gemini-2.5-pro-preview-06-05"
|
| 47 |
|
| 48 |
warnings.filterwarnings("ignore")
|
| 49 |
USE_GPU = torch.cuda.is_available()
|
| 50 |
DEVICE = torch.device("cuda" if USE_GPU else "cpu")
|
| 51 |
+
print(f"[SYSTEM 24.1] Compute: {DEVICE.type.upper()} | Homotopy Continuation + Thread Safety")
|
| 52 |
|
| 53 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 54 |
# SECTION 1: CONSTANTS
|
|
|
|
| 79 |
STATE_LOCK = threading.Lock()
|
| 80 |
|
| 81 |
GLOBAL_SOLVE_STATE = {
|
| 82 |
+
"is_running": False,
|
| 83 |
+
"phase": "IDLE",
|
| 84 |
+
"best_ce": float('inf'),
|
| 85 |
+
"total_fired": 0,
|
| 86 |
+
"best_ray": "β",
|
| 87 |
+
"recent_traces": deque(maxlen=25),
|
| 88 |
+
"high_level_logs": [],
|
| 89 |
+
"answer": "",
|
| 90 |
+
"sketch_summary": "",
|
| 91 |
+
"template_count": 0,
|
| 92 |
+
"template_best_ce": float('inf'),
|
| 93 |
+
"sympy_derivation": [],
|
| 94 |
}
|
| 95 |
|
| 96 |
def _update_state(**kwargs):
|
| 97 |
with STATE_LOCK:
|
| 98 |
+
for k, v in kwargs.items():
|
| 99 |
+
GLOBAL_SOLVE_STATE[k] = v
|
| 100 |
|
| 101 |
def _add_log(line: str):
|
| 102 |
+
with STATE_LOCK:
|
| 103 |
+
GLOBAL_SOLVE_STATE["high_level_logs"].append(line)
|
| 104 |
|
| 105 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 106 |
# SECTION 3: INTERVAL ARITHMETIC (HC4)
|
|
|
|
| 316 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 317 |
@dataclass
|
| 318 |
class Constraint:
|
| 319 |
+
kind:str; expr:str; direction:str; weight:float=1.0; scope:str="root"
|
| 320 |
+
branches:List[str]=field(default_factory=list)
|
| 321 |
|
| 322 |
@dataclass
|
| 323 |
class MathConstraint:
|
|
|
|
| 499 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 500 |
@dataclass
|
| 501 |
class StructuralSketch:
|
| 502 |
+
axiom_affinities: Dict[str, float]
|
| 503 |
+
solvable_by_sympy: bool
|
| 504 |
+
exact_solutions: List[Dict[str, float]]
|
| 505 |
+
sympy_derivation: List[str]
|
| 506 |
+
n_free_dof: int
|
| 507 |
+
has_conservation: bool
|
| 508 |
+
has_bilinear: bool
|
| 509 |
+
has_ordering: bool
|
| 510 |
+
has_transcendental: bool
|
| 511 |
+
dominant_type: str
|
| 512 |
+
sketch_notes: List[str]
|
| 513 |
|
| 514 |
@dataclass
|
| 515 |
class HypothesisTemplate:
|
| 516 |
+
template_id: str
|
| 517 |
+
pinned_vars: Dict[str,float]
|
| 518 |
+
free_vars: List[str]
|
| 519 |
+
source: str
|
| 520 |
+
confidence: float
|
| 521 |
+
derivation: str
|
| 522 |
|
| 523 |
def _try_sympy_solve(problem: Problem) -> Tuple[List[Dict[str, float]], bool, List[str]]:
|
| 524 |
has_transcendental = any(
|
| 525 |
mc.parsed is not None and (mc.parsed.has(sp.sin) or mc.parsed.has(sp.cos) or mc.parsed.has(sp.exp) or mc.parsed.has(sp.log))
|
| 526 |
for mc in problem.compiled_constraints)
|
| 527 |
if has_transcendental: return [], False, []
|
| 528 |
+
|
| 529 |
eq_mcs = [mc for mc in problem.compiled_constraints if mc.kind == "equality" and mc.parsed is not None and mc.syms_used]
|
| 530 |
if len(eq_mcs) < len(problem.variables): return [], False, []
|
| 531 |
+
|
| 532 |
syms = [sp.Symbol(v) for v in problem.variables]
|
| 533 |
equations = [mc.parsed for mc in eq_mcs]
|
| 534 |
|
| 535 |
+
def _solve():
|
| 536 |
+
return sp.solve(equations, syms, dict=True)
|
| 537 |
|
| 538 |
try:
|
| 539 |
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as ex:
|
| 540 |
future = ex.submit(_solve)
|
| 541 |
raw = future.result(timeout=SYMPY_TIMEOUT_SECS)
|
| 542 |
except Exception: return [], False, []
|
| 543 |
+
|
| 544 |
if not raw: return [], False, []
|
| 545 |
|
| 546 |
derivation = ["SYSTEM HANDED TO SYMPY:"]
|
| 547 |
for mc in eq_mcs: derivation.append(f" {mc.expr_str} = 0")
|
| 548 |
+
|
| 549 |
for sol_idx, sol in enumerate(raw[:2]):
|
| 550 |
derivation.append(f"\nSYMBOLIC SOLUTION #{sol_idx + 1}:")
|
| 551 |
sorted_sol = sorted(sol.items(), key=lambda kv: len(kv[1].free_symbols))
|
| 552 |
for sym, val in sorted_sol:
|
| 553 |
simplified = sp.simplify(val); free_s = sorted(simplified.free_symbols, key=str)
|
| 554 |
if not free_s:
|
| 555 |
+
try:
|
| 556 |
+
num = float(simplified.evalf())
|
| 557 |
+
derivation.append(f" {sym} = {simplified} = {num:.8g} [constant root]")
|
| 558 |
+
except:
|
| 559 |
+
derivation.append(f" {sym} = {simplified} [symbolic constant]")
|
| 560 |
+
else:
|
| 561 |
+
derivation.append(f" {sym} = {simplified} [eliminates {sym}, depends on {', '.join(str(s) for s in free_s)}]")
|
| 562 |
+
|
| 563 |
if len(sorted_sol) == 1:
|
| 564 |
sym, val = sorted_sol[0]
|
| 565 |
try:
|
| 566 |
poly = sp.Poly(equations[0], sp.Symbol(str(sym)))
|
| 567 |
+
b_lo, b_hi = problem.bounds.get(str(sym), ('?', '?'))
|
| 568 |
+
derivation.append(f" Univariate polynomial: degree {poly.degree()}, roots selected by bounds")
|
| 569 |
except: pass
|
| 570 |
|
| 571 |
valid = []
|
| 572 |
b_mid = {v: (problem.bounds[v][0] + problem.bounds[v][1]) / 2 for v in problem.variables}
|
| 573 |
for sol in raw:
|
| 574 |
+
binding = dict(b_mid)
|
| 575 |
+
ok = True
|
| 576 |
for sym, val in sol.items():
|
| 577 |
try:
|
| 578 |
num = float(val.evalf()); vn = str(sym)
|
|
|
|
| 584 |
if ok:
|
| 585 |
ce = problem.scalar_energy(binding)
|
| 586 |
if ce < 1.0: valid.append((binding, ce))
|
| 587 |
+
|
| 588 |
valid.sort(key=lambda x: x[1])
|
| 589 |
if valid: derivation.append(f"\nBOUND-FILTERED: {len(valid)} of {len(raw)} symbolic solutions fall within domains.")
|
| 590 |
else: derivation.append(f"\nBOUND CHECK: all {len(raw)} symbolic solutions lie outside variable domains.")
|
| 591 |
+
|
| 592 |
return [v[0] for v in valid], len(valid) > 0, derivation
|
| 593 |
|
| 594 |
def compute_sketch(problem: Problem) -> StructuralSketch:
|
| 595 |
+
affinities = {a: 1.0 for a in _ALL_AXIOMS_PLACEHOLDER}
|
| 596 |
+
notes = []
|
| 597 |
+
n_vars = len(problem.variables)
|
| 598 |
+
n_eq = sum(1 for mc in problem.compiled_constraints if mc.kind == "equality")
|
| 599 |
|
| 600 |
has_conservation = any(mc.weight >= 5.0 for mc in problem.compiled_constraints if mc.kind == "equality")
|
| 601 |
if has_conservation:
|
| 602 |
+
affinities["CONSERVED"] += 3.0
|
| 603 |
+
affinities["COMPOSITE"] += 1.5
|
| 604 |
notes.append("Conservation laws β CONSERVED/COMPOSITE boosted")
|
| 605 |
|
| 606 |
if problem.bilinear_pairs:
|
|
|
|
| 608 |
notes.append(f"{len(problem.bilinear_pairs)} bilinear pairs β BILINEAR boosted")
|
| 609 |
|
| 610 |
if problem.monotone_targets:
|
| 611 |
+
affinities["MONOTONE_PRODUCT"] += 5.0
|
| 612 |
+
affinities["ORDERED"] += 2.5
|
| 613 |
notes.append(f"{len(problem.monotone_targets)} monotone targets β MPR strongly boosted")
|
| 614 |
|
| 615 |
if problem.ordering_pairs:
|
| 616 |
+
affinities["ORDERED"] += 2.0
|
| 617 |
+
affinities["DISCRETE"] += 1.0
|
| 618 |
notes.append(f"{len(problem.ordering_pairs)} ordering constraints β ORDERED boosted")
|
| 619 |
|
| 620 |
if any(problem.scope_vars.values()):
|
| 621 |
+
affinities["DISCRETE"] += 2.0
|
| 622 |
+
affinities["LOCALITY"] += 1.0
|
| 623 |
notes.append("Scope structure detected β DISCRETE boosted")
|
| 624 |
|
| 625 |
n_proj = sum(1 for mc in problem.compiled_constraints if mc.projections)
|
| 626 |
if n_proj > 0:
|
| 627 |
+
affinities["ATOMIC"] += 2.0 + n_proj * 0.3
|
| 628 |
+
affinities["IMPLICATION"] += 1.5
|
| 629 |
+
affinities["TRANSITIVE"] += 1.5
|
| 630 |
notes.append(f"{n_proj} projectable constraints β ATOMIC/IMPLICATION boosted")
|
| 631 |
|
| 632 |
has_sos = any(mc.parsed is not None and mc.parsed.is_Add and any(t.is_Pow and t.args[1] == 2 for t in mc.parsed.args) for mc in problem.compiled_constraints if mc.kind == "equality")
|
| 633 |
if has_sos:
|
| 634 |
+
affinities["METRIC"] += 2.5
|
| 635 |
+
affinities["QUADRATIC"] += 2.0
|
| 636 |
+
affinities["CONTINUOUS"] += 1.5
|
| 637 |
notes.append("Sum-of-squares β METRIC/QUADRATIC/CONTINUOUS boosted")
|
| 638 |
|
| 639 |
tight = sum(1 for v in problem.variables if abs(problem.bounds[v][1] - problem.bounds[v][0]) < 10)
|
| 640 |
+
if tight > n_vars // 2:
|
| 641 |
+
affinities["PARSIMONY"] += 2.0
|
| 642 |
+
notes.append("Tight bounds β PARSIMONY boosted")
|
| 643 |
|
| 644 |
+
if n_vars >= 6:
|
| 645 |
+
affinities["HOLISM"] += 1.5
|
| 646 |
+
affinities["NETWORK"] += 1.5
|
| 647 |
+
notes.append(f"High-D ({n_vars} vars) β HOLISM/NETWORK boosted")
|
| 648 |
|
| 649 |
bound_groups = defaultdict(list)
|
| 650 |
for v in problem.variables: bound_groups[problem.bounds[v]].append(v)
|
| 651 |
+
if any(len(g) >= 2 for g in bound_groups.values()):
|
| 652 |
+
affinities["SYMMETRIC"] += 1.5
|
| 653 |
+
notes.append("Symmetric bounds β SYMMETRIC boosted")
|
| 654 |
|
| 655 |
has_transcendental = any(mc.parsed is not None and (mc.parsed.has(sp.sin) or mc.parsed.has(sp.cos) or mc.parsed.has(sp.exp)) for mc in problem.compiled_constraints)
|
| 656 |
+
if has_transcendental:
|
| 657 |
+
affinities["CONTINUOUS"] += 2.0
|
| 658 |
+
affinities["EQUILIBRIUM"] += 1.5
|
| 659 |
+
notes.append("Transcendental constraints β CONTINUOUS/EQUILIBRIUM boosted")
|
| 660 |
|
| 661 |
max_deg = 1
|
| 662 |
for mc in problem.compiled_constraints:
|
|
|
|
| 675 |
n_obs = sum(1 for v in problem.variables if problem.bounds[v][0] == problem.bounds[v][1])
|
| 676 |
n_free_dof = max(0, n_vars - n_obs - n_eq)
|
| 677 |
|
| 678 |
+
exact_solutions = []
|
| 679 |
+
solvable = False
|
| 680 |
+
sympy_derivation = []
|
| 681 |
if n_vars <= SYMPY_MAX_VARS and dom_type in ("linear", "quadratic") and not has_transcendental:
|
| 682 |
exact_solutions, solvable, sympy_derivation = _try_sympy_solve(problem)
|
| 683 |
+
if solvable:
|
| 684 |
+
notes.append(f"β SymPy found {len(exact_solutions)} exact solution(s) via {len(sympy_derivation)} steps")
|
| 685 |
+
else:
|
| 686 |
+
notes.append("SymPy attempted (no closed form) β proceeding to ray search")
|
| 687 |
+
|
| 688 |
+
return StructuralSketch(
|
| 689 |
+
axiom_affinities=affinities, solvable_by_sympy=solvable,
|
| 690 |
+
exact_solutions=exact_solutions, sympy_derivation=sympy_derivation,
|
| 691 |
+
n_free_dof=n_free_dof, has_conservation=has_conservation,
|
| 692 |
+
has_bilinear=bool(problem.bilinear_pairs), has_ordering=bool(problem.ordering_pairs),
|
| 693 |
+
has_transcendental=has_transcendental, dominant_type=dom_type, sketch_notes=notes)
|
| 694 |
|
| 695 |
def generate_templates(problem: Problem, sketch: StructuralSketch) -> List[HypothesisTemplate]:
|
| 696 |
+
templates = []
|
| 697 |
+
b_mid = {v: (problem.bounds[v][0] + problem.bounds[v][1]) / 2 for v in problem.variables}
|
| 698 |
|
| 699 |
for i, sol in enumerate(sketch.exact_solutions):
|
| 700 |
+
templates.append(HypothesisTemplate(
|
| 701 |
+
template_id=f"sympy_{i}", pinned_vars=sol,
|
| 702 |
+
free_vars=[v for v in problem.variables if v not in sol],
|
| 703 |
+
source="sympy_exact", confidence=0.99, derivation=f"SymPy exact solution #{i+1}"))
|
| 704 |
|
| 705 |
for mc in problem.compiled_constraints:
|
| 706 |
if mc.kind != "equality" or mc.weight < 5.0 or not mc.projections: continue
|
|
|
|
| 710 |
try:
|
| 711 |
val = float(proj["func"](*[b_mid.get(s, 0.0) for s in proj["syms"]]))
|
| 712 |
if math.isfinite(val) and lo <= val <= hi:
|
| 713 |
+
templates.append(HypothesisTemplate(
|
| 714 |
+
template_id=f"cons_{v}_{hash(mc.expr_str)%9999}", pinned_vars={v: val},
|
| 715 |
+
free_vars=[u for u in problem.variables if u != v], source="conservation",
|
| 716 |
+
confidence=0.75, derivation=f"Conservation {mc.expr_str} β {v}={val:.4f}"))
|
| 717 |
except: pass
|
| 718 |
|
| 719 |
tb = _global_hc4_tighten_bounds(problem)
|
| 720 |
for v_small, v_large, k in problem.monotone_targets:
|
| 721 |
+
lo_s, hi_s = problem.bounds.get(v_small, (-1e9, 1e9))
|
| 722 |
+
lo_l, hi_l = problem.bounds.get(v_large, (-1e9, 1e9))
|
| 723 |
for ratio in [0.1, 0.25, 0.5, 0.707, 0.9]:
|
| 724 |
vs_sq = k * ratio
|
| 725 |
if vs_sq <= 0: continue
|
| 726 |
vs = math.sqrt(vs_sq); vl = k / vs
|
| 727 |
if not (lo_s <= vs <= hi_s and lo_l <= vl <= hi_l and vs <= vl): continue
|
| 728 |
+
|
| 729 |
+
nb = dict(b_mid)
|
| 730 |
+
nb[v_small] = vs
|
| 731 |
+
nb[v_large] = vl
|
| 732 |
box = {u: IV(*tb.get(u, problem.bounds.get(u, (-10, 10)))) for u in problem.variables}
|
| 733 |
+
box[v_small] = IV(vs - 1e-6, vs + 1e-6)
|
| 734 |
+
box[v_large] = IV(vl - 1e-6, vl + 1e-6)
|
| 735 |
cont = _hc4(box, problem.compiled_constraints)
|
| 736 |
+
|
| 737 |
pinned = {v_small: vs, v_large: vl}
|
| 738 |
if cont:
|
| 739 |
for u, iv in cont.items():
|
| 740 |
if u in problem.bounds: nb[u] = iv.mid()
|
| 741 |
pinned = {u: nb[u] for u in problem.variables if cont[u].width() < 1e-2}
|
| 742 |
+
|
| 743 |
+
templates.append(HypothesisTemplate(
|
| 744 |
+
template_id=f"mpr_{v_small}_{v_large}_r{int(ratio*100)}", pinned_vars=pinned,
|
| 745 |
+
free_vars=[u for u in problem.variables if u not in pinned], source="monotone_prod",
|
| 746 |
+
confidence=0.88, derivation=f"Monotone {v_small}={vs:.4f}β€{v_large}={vl:.4f}"))
|
| 747 |
|
| 748 |
for mc in problem.compiled_constraints:
|
| 749 |
if mc.kind != "equality" or not mc.projections: continue
|
|
|
|
| 753 |
try:
|
| 754 |
val = float(proj["func"](*[b_mid.get(s, 0.0) for s in proj["syms"]]))
|
| 755 |
if math.isfinite(val) and lo <= val <= hi:
|
| 756 |
+
templates.append(HypothesisTemplate(
|
| 757 |
+
template_id=f"proj_{v}_{hash(mc.expr_str)%9999}", pinned_vars={v: val},
|
| 758 |
+
free_vars=[u for u in problem.variables if u != v], source="projection",
|
| 759 |
+
confidence=0.72, derivation=f"Root of {mc.expr_str[:30]} β {v}={val:.4f}"))
|
| 760 |
except: pass
|
| 761 |
|
| 762 |
bound_groups = defaultdict(list)
|
| 763 |
for v in problem.variables: bound_groups[problem.bounds[v]].append(v)
|
| 764 |
for bnd, grp in bound_groups.items():
|
| 765 |
if len(grp) < 2: continue
|
| 766 |
+
avg = sum(b_mid[v] for v in grp) / len(grp)
|
| 767 |
+
lo, hi = bnd
|
| 768 |
if lo <= avg <= hi:
|
| 769 |
pinned = {v: avg for v in grp}
|
| 770 |
+
templates.append(HypothesisTemplate(
|
| 771 |
+
template_id=f"sym_avg_{'_'.join(grp[:3])}", pinned_vars=pinned,
|
| 772 |
+
free_vars=[u for u in problem.variables if u not in pinned], source="symmetry",
|
| 773 |
+
confidence=0.55, derivation=f"Symmetry orbit: {grp} averaged to {avg:.4f}"))
|
| 774 |
|
| 775 |
seen = set(); unique = []
|
| 776 |
for t in sorted(templates, key=lambda t: -t.confidence):
|
| 777 |
key = str(sorted(t.pinned_vars.items()))
|
| 778 |
+
if key not in seen:
|
| 779 |
+
seen.add(key)
|
| 780 |
+
unique.append(t)
|
| 781 |
+
|
| 782 |
return unique[:TEMPLATE_BATCH_SIZE]
|
| 783 |
|
| 784 |
def templates_to_hypotheses(templates, problem, init_binding):
|
| 785 |
hyps = []
|
| 786 |
for t in templates:
|
| 787 |
+
binding = dict(init_binding)
|
| 788 |
+
binding.update(t.pinned_vars)
|
| 789 |
+
hyps.append(Hypothesis(
|
| 790 |
+
hid=t.template_id, binding=binding, h_type=t.source, claim=t.derivation,
|
| 791 |
+
derivation=[t.source], pinned_vars=t.pinned_vars, free_vars=t.free_vars, confidence=t.confidence))
|
| 792 |
return hyps
|
| 793 |
|
| 794 |
_ALL_AXIOMS_PLACEHOLDER: List[str] = []
|
|
|
|
| 798 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 799 |
@dataclass
|
| 800 |
class L9Certificate:
|
| 801 |
+
residual_ce: float
|
| 802 |
+
dominant_vars: List[str]
|
| 803 |
+
dominant_exprs: List[str]
|
| 804 |
+
tension_class: str = "unknown"
|
| 805 |
|
| 806 |
def _batched_deduce_and_evaluate(problem: Problem, hyps: List['Hypothesis']) -> List[Tuple[Dict, float, List[str], str]]:
|
| 807 |
if not hyps: return []
|
| 808 |
+
B = len(hyps)
|
| 809 |
+
V = len(problem.variables)
|
| 810 |
+
|
| 811 |
+
x_data = []
|
| 812 |
+
mask_data = []
|
| 813 |
+
target_data = []
|
| 814 |
+
|
| 815 |
for hyp in hyps:
|
| 816 |
xr, mr, tr = [], [], []
|
| 817 |
for v in problem.variables:
|
| 818 |
+
if v in hyp.pinned_vars:
|
| 819 |
+
val = hyp.pinned_vars[v]
|
| 820 |
+
xr.append(val)
|
| 821 |
+
mr.append(0.0)
|
| 822 |
+
tr.append(val)
|
| 823 |
+
else:
|
| 824 |
+
val = hyp.binding.get(v, (problem.bounds[v][0] + problem.bounds[v][1]) / 2)
|
| 825 |
+
xr.append(val)
|
| 826 |
+
mr.append(1.0)
|
| 827 |
+
tr.append(0.0)
|
| 828 |
+
x_data.append(xr)
|
| 829 |
+
mask_data.append(mr)
|
| 830 |
+
target_data.append(tr)
|
| 831 |
|
| 832 |
X = torch.tensor(x_data, device=DEVICE, dtype=torch.float32, requires_grad=True)
|
| 833 |
mask = torch.tensor(mask_data, device=DEVICE, dtype=torch.float32)
|
|
|
|
| 841 |
step_ratio = min(1.0, step / (DEDUCE_ADAM_STEPS * 0.8))
|
| 842 |
ce = problem.tensor_energy(X, step_ratio)
|
| 843 |
|
| 844 |
+
if isinstance(ce, torch.Tensor) and (ce < SOLVE_THRESHOLD).all() and step_ratio == 1.0:
|
| 845 |
+
break
|
| 846 |
+
|
| 847 |
+
loss = ce.sum()
|
| 848 |
+
loss.backward()
|
| 849 |
|
| 850 |
with torch.no_grad():
|
| 851 |
X.grad.clamp_(-10.0, 10.0)
|
| 852 |
X.grad *= mask
|
| 853 |
optimizer.step()
|
| 854 |
X.data = torch.where(mask == 0.0, target, X.data)
|
| 855 |
+
|
| 856 |
for j, v in enumerate(problem.variables):
|
| 857 |
lo, hi = problem.bounds[v]
|
| 858 |
margin = (hi - lo) * 0.1 * (1.0 - step_ratio) # Exploratory bounds fade to 0
|
|
|
|
| 864 |
|
| 865 |
ce_vals = final_ce.detach().cpu().numpy()
|
| 866 |
X_vals = X.detach().cpu().numpy()
|
| 867 |
+
grads_abs = X.grad.abs()
|
| 868 |
+
_, topk_idx = torch.topk(grads_abs, k=min(3, V), dim=1)
|
| 869 |
+
|
| 870 |
+
topk_idx_np = topk_idx.cpu().numpy()
|
| 871 |
+
grads_np = grads_abs.cpu().numpy()
|
| 872 |
|
| 873 |
results = []
|
| 874 |
for i in range(B):
|
| 875 |
final_b = {problem.variables[j]: float(X_vals[i, j]) for j in range(V)}
|
| 876 |
dom_vars = [problem.variables[idx] for idx in topk_idx_np[i] if float(grads_np[i, idx]) > 1e-4]
|
| 877 |
+
n_dom = len(dom_vars)
|
| 878 |
+
tension_class = ("isolated" if n_dom <= 1 else "relational" if n_dom == 2 else "systemic")
|
| 879 |
results.append((final_b, float(ce_vals[i]), dom_vars, tension_class))
|
| 880 |
+
|
| 881 |
return results
|
| 882 |
|
| 883 |
def _mprt_sample(problem, work_box, N):
|
| 884 |
+
var_list = problem.variables
|
| 885 |
+
V = len(var_list)
|
| 886 |
+
|
| 887 |
lo_t = torch.tensor([max(problem.bounds.get(v, (-10.0, 10.0))[0], work_box[v].lo if v in work_box else problem.bounds.get(v, (-10, 10))[0]) for v in var_list], device=DEVICE, dtype=torch.float32)
|
| 888 |
hi_t = torch.tensor([min(problem.bounds.get(v, (-10.0, 10.0))[1], work_box[v].hi if v in work_box else problem.bounds.get(v, (-10, 10))[1]) for v in var_list], device=DEVICE, dtype=torch.float32)
|
| 889 |
+
|
| 890 |
for i in range(V):
|
| 891 |
+
if lo_t[i] >= hi_t[i]:
|
| 892 |
+
m = (lo_t[i] + hi_t[i]) / 2
|
| 893 |
+
lo_t[i] = m - 1e-6
|
| 894 |
+
hi_t[i] = m + 1e-6
|
| 895 |
+
|
| 896 |
X = lo_t.unsqueeze(0) + (hi_t - lo_t).unsqueeze(0) * torch.rand((N, V), device=DEVICE)
|
| 897 |
ce_batch = problem.tensor_energy(X, 1.0)
|
| 898 |
best_idx = torch.argmin(ce_batch).item()
|
| 899 |
+
|
| 900 |
return {v: float(X[best_idx, i].item()) for i, v in enumerate(var_list)}, ce_batch[best_idx].item()
|
| 901 |
|
| 902 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 915 |
COMPOSITE="COMPOSITE"; HOLISM="HOLISM"; PARSIMONY="PARSIMONY"; DUALITY="DUALITY"
|
| 916 |
|
| 917 |
ALL_AXIOMS = [getattr(Axiom, a) for a in dir(Axiom) if not a.startswith("__")]
|
| 918 |
+
AXIOM_ABBR = {a: a[:3] for a in ALL_AXIOMS}
|
| 919 |
+
AXIOM_ABBR[Axiom.MONOTONE_PRODUCT] = "MPR"
|
| 920 |
_ALL_AXIOMS_PLACEHOLDER.extend(ALL_AXIOMS)
|
| 921 |
|
| 922 |
ADJACENT_CONTRADICTIONS = [
|
|
|
|
| 941 |
|
| 942 |
@dataclass
|
| 943 |
class Hypothesis:
|
| 944 |
+
hid: str
|
| 945 |
+
binding: Dict[str, float]
|
| 946 |
+
h_type: str
|
| 947 |
+
claim: str
|
| 948 |
+
derivation: List[str]
|
| 949 |
+
pinned_vars: Dict[str, float]
|
| 950 |
+
free_vars: List[str]
|
| 951 |
+
confidence: float
|
| 952 |
+
ce: float = float('inf')
|
| 953 |
|
| 954 |
@dataclass
|
| 955 |
class Baton:
|
| 956 |
+
binding: Dict[str, float]
|
| 957 |
+
ce: float
|
| 958 |
+
ray_id: str = ""
|
| 959 |
+
depth: int = 0
|
| 960 |
+
l9: Optional[L9Certificate] = None
|
| 961 |
|
| 962 |
@dataclass
|
| 963 |
class AxiomRay:
|
| 964 |
+
sequence: List[str]
|
| 965 |
+
ray_id: str
|
| 966 |
+
ray_type: str = "seed"
|
| 967 |
+
depth: int = 0
|
| 968 |
+
parent_id: Optional[str] = None
|
| 969 |
+
baton: Optional[Baton] = None
|
| 970 |
+
ce_prior: float = float('inf')
|
| 971 |
+
|
| 972 |
@property
|
| 973 |
+
def name(self) -> str:
|
| 974 |
+
return "β".join(AXIOM_ABBR.get(a, a[:3]) for a in self.sequence)
|
| 975 |
+
|
| 976 |
def extend(self, axiom: str, rtype: str, new_prior: float = float('inf')) -> Optional['AxiomRay']:
|
| 977 |
new_seq = self.sequence + [axiom]
|
| 978 |
if sequence_valid(new_seq):
|
| 979 |
+
return AxiomRay(
|
| 980 |
+
sequence=new_seq,
|
| 981 |
+
ray_id=f"{self.ray_id}+{AXIOM_ABBR.get(axiom, '?')}",
|
| 982 |
+
ray_type=rtype,
|
| 983 |
+
depth=self.depth + 1,
|
| 984 |
+
parent_id=self.ray_id,
|
| 985 |
+
ce_prior=new_prior
|
| 986 |
+
)
|
| 987 |
return None
|
| 988 |
|
| 989 |
@dataclass
|
| 990 |
class HypothesisTrace:
|
| 991 |
+
hid: str
|
| 992 |
+
round_idx: int
|
| 993 |
+
ray_name: str
|
| 994 |
+
ray_type: str
|
| 995 |
+
ce_before: float
|
| 996 |
+
ce_after: float
|
| 997 |
+
survived: bool
|
| 998 |
+
elapsed_ms: float
|
| 999 |
+
g1_pass: bool = False
|
| 1000 |
+
g2_pass: bool = False
|
| 1001 |
binding: Dict[str, float] = field(default_factory=dict)
|
| 1002 |
invariant_results: Dict[str, Tuple[float, bool]] = field(default_factory=dict)
|
| 1003 |
+
tension_class: str = "unknown"
|
| 1004 |
+
depth: int = 0
|
| 1005 |
|
| 1006 |
@dataclass
|
| 1007 |
class StructuralModel:
|
| 1008 |
+
best_binding: Dict[str, float]
|
| 1009 |
+
best_ce: float
|
| 1010 |
best_ray: str = "β"
|
| 1011 |
failure_patterns: Set[str] = field(default_factory=set)
|
| 1012 |
resonant_pairs: List[Tuple[str, str]] = field(default_factory=list)
|
|
|
|
| 1018 |
return Hypothesis(hid=hid, binding=binding, h_type=h_type, claim=claim,
|
| 1019 |
derivation=derivation, pinned_vars=pinned, free_vars=free, confidence=conf)
|
| 1020 |
|
| 1021 |
+
def _hyp_continuous(p, bt, a, m):
|
| 1022 |
+
return [_make_hyp("cnt", bt.binding, "continuous", "Manifold", [], {}, p.variables, 0.45)]
|
| 1023 |
+
|
| 1024 |
def _hyp_discrete(p, bt, a, m):
|
| 1025 |
+
b = dict(bt.binding)
|
| 1026 |
+
pinned = {}
|
| 1027 |
for sn in p.scope_order:
|
| 1028 |
+
svars = p.scope_vars.get(sn, [])
|
| 1029 |
+
smcs = [p.compiled_constraints[i] for i in p.scope_groups.get(sn, [])]
|
| 1030 |
if svars and smcs:
|
| 1031 |
box = {v: IV(b.get(v, 0) - max(0.05 * (p.bounds[v][1] - p.bounds[v][0]), 1e-4),
|
| 1032 |
b.get(v, 0) + max(0.05 * (p.bounds[v][1] - p.bounds[v][0]), 1e-4)) for v in svars if v in p.bounds}
|
|
|
|
| 1034 |
if cont:
|
| 1035 |
for v, iv in cont.items():
|
| 1036 |
b[v] = iv.mid()
|
| 1037 |
+
if iv.width() < 1e-2:
|
| 1038 |
+
pinned[v] = b[v]
|
| 1039 |
return [_make_hyp("dis", b, "discrete", "TopoScope", [], pinned, p.variables, 0.80)]
|
| 1040 |
|
| 1041 |
def _hyp_quadratic(p, bt, a, m):
|
| 1042 |
+
hyps = []
|
| 1043 |
+
b = dict(bt.binding)
|
| 1044 |
if bt.l9 and bt.l9.dominant_vars:
|
| 1045 |
+
for v in bt.l9.dominant_vars[:2]:
|
| 1046 |
+
hyps.append(_make_hyp(f"qua_{v}", b, "quadratic", f"Root({v})", [], {v: b[v]}, p.variables, 0.70))
|
| 1047 |
return hyps
|
| 1048 |
|
| 1049 |
def _hyp_bilinear(p, bt, a, m):
|
| 1050 |
+
hyps = []
|
| 1051 |
+
b = dict(bt.binding)
|
| 1052 |
for vi, vj in p.bilinear_pairs:
|
| 1053 |
+
lo_i, hi_i = p.bounds.get(vi, (0, 10))
|
| 1054 |
+
lo_j, hi_j = p.bounds.get(vj, (0, 10))
|
| 1055 |
product = abs(b.get(vi, 1) * b.get(vj, 1))
|
| 1056 |
+
|
| 1057 |
if product <= 0: continue
|
| 1058 |
gm = math.sqrt(product)
|
| 1059 |
+
|
| 1060 |
if lo_i <= gm <= hi_i and lo_j <= gm <= hi_j:
|
| 1061 |
+
nb = dict(b)
|
| 1062 |
+
nb[vi] = nb[vj] = gm
|
| 1063 |
hyps.append(_make_hyp(f"bil_eq_{vi}_{vj}", nb, "bilinear", f"GeoMean({vi}={vj}={gm:.3f})", ["bilinear"], {vi: gm, vj: gm}, [v for v in p.variables if v not in [vi, vj]], 0.70))
|
| 1064 |
+
|
| 1065 |
for ratio in [0.4, 0.7071, 0.9]:
|
| 1066 |
+
vs = gm * ratio
|
| 1067 |
+
vl = product / (vs + 1e-9)
|
| 1068 |
if lo_i <= vs <= hi_i and lo_j <= vl <= hi_j and vs < vl:
|
| 1069 |
+
nb2 = dict(b)
|
| 1070 |
+
nb2[vi] = vs
|
| 1071 |
+
nb2[vj] = vl
|
| 1072 |
hyps.append(_make_hyp(f"bil_asc_{int(ratio*100)}_{vi}_{vj}", nb2, "bilinear", f"BilAsc({vi}={vs:.3f}<{vj}={vl:.3f})", ["bilinear"], {vi: vs, vj: vl}, [v for v in p.variables if v not in [vi, vj]], 0.75))
|
| 1073 |
return hyps
|
| 1074 |
|
| 1075 |
def _hyp_monotone_product(p, bt, a, m):
|
| 1076 |
+
hyps = []
|
| 1077 |
+
b = dict(bt.binding)
|
| 1078 |
if not p.monotone_targets: return hyps
|
| 1079 |
tb = _global_hc4_tighten_bounds(p)
|
| 1080 |
+
|
| 1081 |
for v_small, v_large, k in p.monotone_targets:
|
| 1082 |
+
lo_s, hi_s = p.bounds.get(v_small, (-1e9, 1e9))
|
| 1083 |
+
lo_l, hi_l = p.bounds.get(v_large, (-1e9, 1e9))
|
| 1084 |
+
|
| 1085 |
for ratio in [0.25, 0.5, 0.707, 0.9]:
|
| 1086 |
vs_sq = k * ratio
|
| 1087 |
if vs_sq <= 0: continue
|
| 1088 |
+
vs = math.sqrt(vs_sq)
|
| 1089 |
+
vl = k / vs
|
| 1090 |
if not (lo_s <= vs <= hi_s and lo_l <= vl <= hi_l and vs <= vl): continue
|
| 1091 |
+
|
| 1092 |
+
nb = dict(b)
|
| 1093 |
+
nb[v_small] = vs
|
| 1094 |
+
nb[v_large] = vl
|
| 1095 |
box = {u: IV(*tb.get(u, p.bounds.get(u, (-10, 10)))) for u in p.variables}
|
| 1096 |
+
box[v_small] = IV(vs - 1e-6, vs + 1e-6)
|
| 1097 |
+
box[v_large] = IV(vl - 1e-6, vl + 1e-6)
|
| 1098 |
cont = _hc4(box, p.compiled_constraints)
|
| 1099 |
+
|
| 1100 |
pinned = {v_small: vs, v_large: vl}
|
| 1101 |
if cont:
|
| 1102 |
for u, iv in cont.items():
|
| 1103 |
if u in p.bounds: nb[u] = iv.mid()
|
| 1104 |
pinned = {u: nb[u] for u in p.variables if cont[u].width() < 1e-2}
|
| 1105 |
+
|
| 1106 |
hyps.append(_make_hyp(f"mpr_{v_small}_{v_large}_r{int(ratio*100)}", nb, "monotone_product", f"MonoProd({v_small}={vs:.4f}β€{v_large}={vl:.4f})", ["ordered", "hc4"], pinned, [u for u in p.variables if u not in pinned], 0.88))
|
| 1107 |
return hyps
|
| 1108 |
|
| 1109 |
def _hyp_metric(p, bt, a, m):
|
| 1110 |
+
hyps = []
|
| 1111 |
+
b = dict(bt.binding)
|
| 1112 |
for mc in p.compiled_constraints:
|
| 1113 |
if mc.kind != "equality" or not mc.parsed: continue
|
| 1114 |
if not mc.parsed.is_Add: continue
|
| 1115 |
+
|
| 1116 |
sq_terms = [t for t in mc.parsed.args if t.is_Pow and t.args[1] == 2]
|
| 1117 |
if len(sq_terms) < 1: continue
|
| 1118 |
vars_in = [str(s) for s in mc.parsed.free_symbols if str(s) in p.variables]
|
| 1119 |
if not vars_in: continue
|
| 1120 |
+
|
| 1121 |
const_terms = [float(t) for t in mc.parsed.args if t.is_Number]
|
| 1122 |
if not const_terms: continue
|
| 1123 |
+
|
| 1124 |
target = -const_terms[0]
|
| 1125 |
if target <= 0: continue
|
| 1126 |
+
|
| 1127 |
curr_val = sum(b.get(v, 0)**2 for v in vars_in)
|
| 1128 |
if curr_val < 1e-8: continue
|
| 1129 |
+
|
| 1130 |
scale = math.sqrt(target / curr_val)
|
| 1131 |
nb = dict(b)
|
| 1132 |
for v in vars_in:
|
| 1133 |
lo, hi = p.bounds.get(v, (-10, 10))
|
| 1134 |
nb[v] = max(lo, min(hi, b.get(v, 0) * scale))
|
| 1135 |
+
|
| 1136 |
hyps.append(_make_hyp(f"met_{hash(mc.expr_str)%9999}", nb, "metric", f"RadialProject(scale={scale:.4f},dim={len(vars_in)})", ["metric", mc.expr_str], {}, list(p.variables), 0.75))
|
| 1137 |
return hyps
|
| 1138 |
|
| 1139 |
def _hyp_symmetric(p, bt, a, m):
|
| 1140 |
+
hyps = []
|
| 1141 |
+
b = dict(bt.binding)
|
| 1142 |
groups_to_check = list(p.scope_vars.values()) if p.scope_vars else [p.variables]
|
| 1143 |
+
if not any(p.scope_vars.values()):
|
| 1144 |
+
groups_to_check = [p.variables]
|
| 1145 |
|
| 1146 |
seen_pairs = set()
|
| 1147 |
for grp in groups_to_check:
|
|
|
|
| 1152 |
vi, vj = vl[i], vl[j]
|
| 1153 |
if (vi, vj) in seen_pairs: continue
|
| 1154 |
seen_pairs.add((vi, vj))
|
| 1155 |
+
|
| 1156 |
+
lo_i, hi_i = p.bounds.get(vi, (-1e9, 1e9))
|
| 1157 |
+
lo_j, hi_j = p.bounds.get(vj, (-1e9, 1e9))
|
| 1158 |
bvi, bvj = b.get(vi, 0), b.get(vj, 0)
|
| 1159 |
+
|
| 1160 |
if lo_i <= bvj <= hi_i and lo_j <= bvi <= hi_j:
|
| 1161 |
+
nb = dict(b)
|
| 1162 |
+
nb[vi], nb[vj] = bvj, bvi
|
| 1163 |
hyps.append(_make_hyp(f"sym_{vi}_{vj}", nb, "symmetric", f"Swap({vi}β{vj})", ["symmetric"], {vi: nb[vi], vj: nb[vj]}, [v for v in p.variables if v not in [vi, vj]], 0.60))
|
| 1164 |
+
|
| 1165 |
avg = (bvi + bvj) / 2
|
| 1166 |
if lo_i <= avg <= hi_i and lo_j <= avg <= hi_j:
|
| 1167 |
+
nb2 = dict(b)
|
| 1168 |
+
nb2[vi] = avg
|
| 1169 |
+
nb2[vj] = avg
|
| 1170 |
hyps.append(_make_hyp(f"sym_avg_{vi}_{vj}", nb2, "symmetric", f"Average({vi}={vj}={avg:.4f})", ["symmetric"], {vi: avg, vj: avg}, [v for v in p.variables if v not in [vi, vj]], 0.55))
|
| 1171 |
return hyps[:10]
|
| 1172 |
|
|
|
|
| 1177 |
def _hyp_mutable(p, bt, a, m):
|
| 1178 |
b = dict(bt.binding)
|
| 1179 |
if bt.l9 and bt.l9.dominant_vars:
|
| 1180 |
+
v = bt.l9.dominant_vars[0]
|
| 1181 |
+
lo, hi = p.bounds.get(v, (-10, 10))
|
| 1182 |
b[v] = max(lo, min(hi, b.get(v, 0) + random.gauss(0, (hi - lo) * 0.05)))
|
| 1183 |
return [_make_hyp("mut", b, "mutable", "Perturb", [], {}, p.variables, 0.40)]
|
| 1184 |
def _hyp_network(p, bt, a, m): return [_make_hyp("net", bt.binding, "network", "HubProp", [], {}, p.variables, 0.65)]
|
| 1185 |
def _hyp_equilibrium(p, bt, a, m): return [_make_hyp("eql", bt.binding, "equilibrium", "GradBal", [], {}, p.variables, 0.72)]
|
| 1186 |
def _hyp_superposition(p, bt, a, m):
|
| 1187 |
if a and len(a) > 0:
|
| 1188 |
+
other = random.choice(a)
|
| 1189 |
+
lam = 0.5
|
| 1190 |
nb = {v: lam * bt.binding.get(v, 0) + (1 - lam) * other.binding.get(v, 0) for v in p.variables}
|
| 1191 |
return [_make_hyp("sup", nb, "superposition", "Superpose", [], {}, p.variables, 0.58)]
|
| 1192 |
return []
|
| 1193 |
def _hyp_locality(p, bt, a, m): return [_make_hyp("loc", bt.binding, "locality", "LocalFirst", [], {}, p.variables, 0.72)]
|
| 1194 |
def _hyp_extremal(p, bt, a, m):
|
| 1195 |
+
hyps = []
|
| 1196 |
+
b = dict(bt.binding)
|
| 1197 |
if bt.l9 and bt.l9.dominant_vars:
|
| 1198 |
+
v = bt.l9.dominant_vars[0]
|
| 1199 |
+
lo, hi = p.bounds.get(v, (0, 1))
|
| 1200 |
for val in [lo, hi, (lo + hi) / 2]:
|
| 1201 |
+
nb = dict(b)
|
| 1202 |
+
nb[v] = val
|
| 1203 |
hyps.append(_make_hyp(f"ext_{v}_{val:.3f}", nb, "extremal", f"PinBound({v}={val:.3f})", [], {v: val}, p.variables, 0.65))
|
| 1204 |
return hyps
|
| 1205 |
def _hyp_entropy(p, bt, a, m): return [_make_hyp("ent", {v: random.uniform(*p.bounds[v]) for v in p.variables}, "entropy", "MaxEnt", [], {}, p.variables, 0.48)]
|
|
|
|
| 1207 |
def _hyp_surjective(p, bt, a, m): return [_make_hyp("sur", bt.binding, "surjective", "Sweep", [], {}, p.variables, 0.45)]
|
| 1208 |
def _hyp_transitive(p, bt, a, m): return [_make_hyp("tra", bt.binding, "transitive", "TransSnap", [], {}, p.variables, 0.77)]
|
| 1209 |
def _hyp_atomic(p, bt, a, m):
|
| 1210 |
+
hyps = []
|
| 1211 |
+
b = dict(bt.binding)
|
| 1212 |
for mc in p.compiled_constraints:
|
| 1213 |
if not mc.projections: continue
|
| 1214 |
for v, projs in mc.projections.items():
|
|
|
|
| 1217 |
val = float(proj["func"](*[b.get(s, 0.0) for s in proj["syms"]]))
|
| 1218 |
lo, hi = p.bounds.get(v, (-1e9, 1e9))
|
| 1219 |
if math.isfinite(val) and lo <= val <= hi:
|
| 1220 |
+
nb = dict(b)
|
| 1221 |
+
nb[v] = val
|
| 1222 |
hyps.append(_make_hyp(f"ato_{v}", nb, "atomic", f"Solve({v})", [], {v: val}, p.variables, 0.70))
|
| 1223 |
break
|
| 1224 |
except: pass
|
|
|
|
| 1231 |
def _hyp_composite(p, bt, a, m): return [_make_hyp("cmp", bt.binding, "composite", "Enz", [], {}, p.variables, 0.90)]
|
| 1232 |
def _hyp_holism(p, bt, a, m): return [_make_hyp("hol", bt.binding, "holism", "Global", [], {}, p.variables, 0.73)]
|
| 1233 |
def _hyp_parsimony(p, bt, a, m):
|
| 1234 |
+
b = dict(bt.binding)
|
| 1235 |
+
nb = {}
|
| 1236 |
max_val = max((abs(v) for v in b.values()), default=1.0)
|
| 1237 |
for v in p.variables:
|
| 1238 |
+
val = b[v]
|
| 1239 |
+
lo, hi = p.bounds[v]
|
| 1240 |
+
if abs(val) < 0.1 * max_val and lo <= 0.0 <= hi:
|
| 1241 |
+
nb[v] = 0.0
|
| 1242 |
else:
|
| 1243 |
candidates = [round(val * m) / m for m in [1, 2, 4] if lo <= round(val * m) / m <= hi]
|
| 1244 |
nb[v] = min(candidates, key=lambda c: abs(c - val)) if candidates else val
|
|
|
|
| 1292 |
scored = []
|
| 1293 |
for ax in remaining_axioms:
|
| 1294 |
w_allos = 1.0
|
| 1295 |
+
if n_dom == 1 and ax in isolated:
|
| 1296 |
+
w_allos += 5.0
|
| 1297 |
+
elif n_dom == 2 and ax in relational:
|
| 1298 |
+
w_allos += 5.0
|
| 1299 |
+
elif n_dom >= 3 and ax in systemic:
|
| 1300 |
+
w_allos += 5.0
|
| 1301 |
+
|
| 1302 |
w_sketch = sketch.axiom_affinities.get(ax, 1.0) if sketch else 1.0
|
| 1303 |
scored.append((w_allos * w_sketch, ax))
|
| 1304 |
|
|
|
|
| 1306 |
children = []
|
| 1307 |
for _, axiom in scored[:effective_width]:
|
| 1308 |
child = ray.extend(axiom, "branch", new_prior=out_baton.ce)
|
| 1309 |
+
if child:
|
| 1310 |
+
child.baton = out_baton
|
| 1311 |
+
children.append(child)
|
| 1312 |
return children
|
| 1313 |
|
| 1314 |
def sketch_weighted_seeds(self, sketch: StructuralSketch, init_ce: float) -> List[AxiomRay]:
|
|
|
|
| 1327 |
if b2 in (a, b1, mid, c): continue
|
| 1328 |
if frozenset([mid, b2]) not in _CONTRA_SET and frozenset([b2, c]) not in _CONTRA_SET:
|
| 1329 |
results.append(AxiomRay([a, b1, mid, b2, c], f"T5_{AXIOM_ABBR.get(a, '?')}_{AXIOM_ABBR.get(c, '?')}", "tension"))
|
| 1330 |
+
random.shuffle(results)
|
| 1331 |
+
return results[:max_n]
|
| 1332 |
|
| 1333 |
def random_scouts(self, n: int = 600) -> List[AxiomRay]:
|
| 1334 |
+
scouts = []
|
| 1335 |
+
attempts = 0
|
| 1336 |
while len(scouts) < n and attempts < n * 30:
|
| 1337 |
+
attempts += 1
|
| 1338 |
+
length = random.randint(3, 12)
|
| 1339 |
+
pool = list(ALL_AXIOMS)
|
| 1340 |
+
random.shuffle(pool)
|
| 1341 |
+
seq = [pool[0]]
|
| 1342 |
for ax in pool[1:]:
|
| 1343 |
if len(seq) >= length: break
|
| 1344 |
+
if ax != seq[-1] and frozenset([seq[-1], ax]) not in _CONTRA_SET:
|
| 1345 |
+
seq.append(ax)
|
| 1346 |
+
if len(seq) >= 3:
|
| 1347 |
+
scouts.append(AxiomRay(seq, f"SC_{''.join(AXIOM_ABBR.get(a, a[:2]) for a in seq)}", "scout"))
|
| 1348 |
return scouts
|
| 1349 |
|
| 1350 |
def recombine(self, ray_a, ray_b, ba, bb) -> List[AxiomRay]:
|
|
|
|
| 1356 |
cut = min(len(ray_a.sequence), len(ray_b.sequence)) // 2
|
| 1357 |
if cut > 0:
|
| 1358 |
seq = ray_a.sequence[:cut] + [x for x in ray_b.sequence[cut:] if x not in ray_a.sequence[:cut]]
|
| 1359 |
+
if sequence_valid(seq):
|
| 1360 |
+
results.append(AxiomRay(seq, f"RC_l{int(lam*100)}", "recombine", baton=ib_baton, ce_prior=ib_ce))
|
| 1361 |
return results
|
| 1362 |
|
| 1363 |
def invert(self, ray, parent_ce) -> Optional[AxiomRay]:
|
| 1364 |
inv = list(reversed(ray.sequence))
|
| 1365 |
+
if sequence_valid(inv) and inv != ray.sequence:
|
| 1366 |
+
return AxiomRay(inv, f"INV_{ray.ray_id}", "invert", parent_id=ray.ray_id, ce_prior=parent_ce)
|
| 1367 |
return None
|
| 1368 |
|
| 1369 |
def resonance_extensions(self, ray, parent_ce, resonant_pairs) -> List[AxiomRay]:
|
| 1370 |
if not ray.sequence or not resonant_pairs: return []
|
| 1371 |
+
last = ray.sequence[-1]
|
| 1372 |
+
results = []
|
| 1373 |
nexts = [b for (a, b) in resonant_pairs if a == last and b != last and frozenset([a, b]) not in _CONTRA_SET and b not in ray.sequence]
|
| 1374 |
for b in nexts:
|
| 1375 |
child = ray.extend(b, "branch", new_prior=parent_ce)
|
| 1376 |
+
if child:
|
| 1377 |
+
child.ray_id = f"RES_{child.ray_id}"
|
| 1378 |
+
results.append(child)
|
| 1379 |
return results
|
| 1380 |
|
| 1381 |
CREATIVE_SEEDER = CreativeSeeder()
|
|
|
|
| 1389 |
g2 = {}
|
| 1390 |
for inv in anchors:
|
| 1391 |
try:
|
| 1392 |
+
if inv.compiled_func:
|
| 1393 |
+
val = float(inv.compiled_func(*[binding.get(v, 0.0) for v in inv.syms_used]))
|
| 1394 |
+
else:
|
| 1395 |
+
val = 999.0
|
| 1396 |
+
|
| 1397 |
err = abs(val)
|
| 1398 |
+
if inv.mode == "eq":
|
| 1399 |
+
passed = err < inv.tolerance
|
| 1400 |
+
elif inv.mode == "geq":
|
| 1401 |
+
passed = val >= -inv.tolerance
|
| 1402 |
+
elif inv.mode == "leq":
|
| 1403 |
+
passed = val <= inv.tolerance
|
| 1404 |
+
else:
|
| 1405 |
+
passed = err < inv.tolerance
|
| 1406 |
+
|
| 1407 |
g2[inv.name] = (round(val if inv.mode in ("geq", "leq") else err, 6), passed)
|
| 1408 |
+
except:
|
| 1409 |
+
g2[inv.name] = (999.0, False)
|
| 1410 |
+
|
| 1411 |
g2_pass = all(v[1] for v in g2.values()) if g2 else True
|
| 1412 |
return g1_pass, g2_pass, g2, round(g1_ce, 6)
|
| 1413 |
|
|
|
|
| 1418 |
|
| 1419 |
def trace(self, axl_def: AXLProblemDef, base_problem: Problem):
|
| 1420 |
hero_traces: List[HypothesisTrace] = []
|
| 1421 |
+
baton_registry: Dict[str, Baton] = {}
|
| 1422 |
+
baton_registry_keys: deque = deque()
|
| 1423 |
+
successful_rays: List[AxiomRay] = []
|
| 1424 |
+
resonant_pairs: List[Tuple[str, str]] = []
|
| 1425 |
|
| 1426 |
for inv in axl_def.anchors:
|
| 1427 |
+
if not inv.compiled_func:
|
| 1428 |
+
inv.compile(base_problem.variables)
|
| 1429 |
|
| 1430 |
+
_update_state(phase="SKETCHING")
|
| 1431 |
+
_add_log("πΊ Computing structural sketchβ¦")
|
| 1432 |
sketch = compute_sketch(base_problem)
|
| 1433 |
_update_state(sketch_summary="; ".join(sketch.sketch_notes[:4]), sympy_derivation=sketch.sympy_derivation)
|
| 1434 |
_add_log(f"β Sketch: {sketch.dominant_type} system, DOF={sketch.n_free_dof}")
|
| 1435 |
|
| 1436 |
+
_update_state(phase="TEMPLATING")
|
| 1437 |
+
_add_log("π¬ Generating hypothesis templatesβ¦")
|
| 1438 |
templates = generate_templates(base_problem, sketch)
|
| 1439 |
_update_state(template_count=len(templates))
|
| 1440 |
|
| 1441 |
init_b, init_ce = _mprt_sample(base_problem, {v: IV(*base_problem.bounds[v]) for v in base_problem.variables}, N_MPRT_EXPLORE)
|
| 1442 |
seed_baton = Baton(binding=init_b, ce=init_ce, ray_id="SEED", l9=L9Certificate(init_ce, base_problem.variables[:3], [], "systemic"))
|
| 1443 |
|
| 1444 |
+
best_ce = init_ce
|
| 1445 |
+
best_binding = dict(init_b)
|
| 1446 |
+
|
| 1447 |
if templates:
|
| 1448 |
_add_log("β Evaluating templates (Phase 0 batch)β¦")
|
| 1449 |
template_hyps = templates_to_hypotheses(templates, base_problem, init_b)
|
| 1450 |
t_results = _batched_deduce_and_evaluate(base_problem, template_hyps)
|
| 1451 |
+
|
| 1452 |
for (th, template), (final_b, final_ce, dom_vars, tc) in zip(zip(template_hyps, templates), t_results):
|
| 1453 |
g1p, g2p, inv_res, g1ce = _verify(final_b, base_problem, axl_def.anchors)
|
| 1454 |
overall = g1p and g2p
|
| 1455 |
+
|
| 1456 |
if overall or final_ce < best_ce:
|
| 1457 |
hero_traces.append(HypothesisTrace(
|
| 1458 |
hid=template.template_id, round_idx=0, ray_name=f"template:{template.source}", ray_type="template",
|
| 1459 |
ce_before=init_ce, ce_after=final_ce, survived=overall, elapsed_ms=0.0,
|
| 1460 |
g1_pass=g1p, g2_pass=g2p, binding={k: round(v, 5) for k, v in final_b.items()},
|
| 1461 |
invariant_results=inv_res, tension_class=tc, depth=0))
|
| 1462 |
+
|
| 1463 |
+
with STATE_LOCK:
|
| 1464 |
+
GLOBAL_SOLVE_STATE["recent_traces"].append(hero_traces[-1])
|
| 1465 |
+
|
| 1466 |
if final_ce < best_ce:
|
| 1467 |
+
best_ce = final_ce
|
| 1468 |
+
best_binding = dict(final_b)
|
| 1469 |
_update_state(best_ce=best_ce)
|
| 1470 |
+
|
| 1471 |
if overall:
|
| 1472 |
_add_log(f"β Template solved at Phase 0! Source: {template.source}")
|
| 1473 |
_update_state(best_ce=best_ce, template_best_ce=best_ce, best_ray=f"template:{template.source}")
|
| 1474 |
return best_binding, best_ce, hero_traces, 0, {"isolated": 0, "relational": 0, "systemic": 0}
|
| 1475 |
+
|
| 1476 |
_update_state(template_best_ce=best_ce)
|
| 1477 |
|
| 1478 |
_update_state(phase="SEARCHING")
|
| 1479 |
seed_rays = CREATIVE_SEEDER.sketch_weighted_seeds(sketch, best_ce)
|
| 1480 |
|
| 1481 |
+
queues = {
|
| 1482 |
+
"core": seed_rays,
|
| 1483 |
+
"explore": CREATIVE_SEEDER.tension_seeds(3000) + CREATIVE_SEEDER.random_scouts(600),
|
| 1484 |
+
"genetic": CREATIVE_SEEDER.target_seeds(axl_def.anchors)
|
| 1485 |
+
}
|
| 1486 |
+
random.shuffle(queues["explore"])
|
| 1487 |
+
random.shuffle(queues["genetic"])
|
| 1488 |
+
|
| 1489 |
+
queue_order = ["core", "explore", "genetic"]
|
| 1490 |
+
q_idx = 0
|
| 1491 |
+
total_fired = 0
|
| 1492 |
allosteric_counts = {"isolated": 0, "relational": 0, "systemic": 0}
|
| 1493 |
model = StructuralModel(best_binding, best_ce)
|
| 1494 |
seed_baton = Baton(binding=best_binding, ce=best_ce, ray_id="SEED", l9=L9Certificate(best_ce, base_problem.variables[:3], [], "systemic"))
|
|
|
|
| 1501 |
q_idx = (q_idx + 1) % 3
|
| 1502 |
if q_idx == start_idx: break
|
| 1503 |
if not any(queues[k] for k in queue_order): break
|
| 1504 |
+
ray = queues[queue_order[q_idx]].pop(0)
|
| 1505 |
+
q_idx = (q_idx + 1) % 3
|
| 1506 |
+
batch_rays.append(ray)
|
| 1507 |
+
total_fired += 1
|
| 1508 |
+
|
| 1509 |
if not batch_rays: break
|
| 1510 |
|
| 1511 |
t0 = time.time()
|
| 1512 |
historical_batons = list(baton_registry.values())
|
| 1513 |
batch_hyps: List[Tuple[int, Hypothesis]] = []
|
| 1514 |
+
|
| 1515 |
for i, ray in enumerate(batch_rays):
|
| 1516 |
p_baton = ray.baton or seed_baton
|
| 1517 |
constructor = AXIOM_CONSTRUCTORS.get(ray.sequence[-1])
|
| 1518 |
hyps = constructor(base_problem, p_baton, historical_batons, model) if constructor else []
|
| 1519 |
+
if not hyps:
|
| 1520 |
+
hyps = [_make_hyp("fb", p_baton.binding, "fallback", "Pass", [], {}, base_problem.variables, 0.1)]
|
| 1521 |
batch_hyps.append((i, hyps[0]))
|
| 1522 |
|
| 1523 |
eval_results = _batched_deduce_and_evaluate(base_problem, [h for _, h in batch_hyps])
|
| 1524 |
elapsed_ms = (time.time() - t0) * 1000 / max(1, len(batch_rays))
|
| 1525 |
|
| 1526 |
+
solved = False
|
| 1527 |
+
batch_heroes = []
|
| 1528 |
+
|
| 1529 |
for (ray_idx, hyp), (final_b, final_ce, dom_vars, tension_class) in zip(batch_hyps, eval_results):
|
| 1530 |
ray = batch_rays[ray_idx]
|
| 1531 |
parent_ce = (ray.baton or seed_baton).ce
|
| 1532 |
allosteric_counts[tension_class] = allosteric_counts.get(tension_class, 0) + 1
|
| 1533 |
|
| 1534 |
g1_pass, g2_pass, inv_results, g1_ce = _verify(final_b, base_problem, axl_def.anchors)
|
| 1535 |
+
overall_pass = g1_pass and g2_pass
|
| 1536 |
+
improved = final_ce < best_ce
|
| 1537 |
|
| 1538 |
if improved or overall_pass or random.random() < 0.002:
|
| 1539 |
trace = HypothesisTrace(
|
|
|
|
| 1547 |
out_baton = Baton(binding=final_b, ce=final_ce, ray_id=ray.ray_id, l9=L9Certificate(final_ce, dom_vars, [], tension_class))
|
| 1548 |
|
| 1549 |
if final_ce < BATON_REGISTRY_THRESHOLD:
|
| 1550 |
+
if ray.ray_id in baton_registry:
|
| 1551 |
+
baton_registry[ray.ray_id] = out_baton
|
| 1552 |
else:
|
| 1553 |
if len(baton_registry) >= BATON_REGISTRY_MAX:
|
| 1554 |
+
old_key = baton_registry_keys.popleft()
|
| 1555 |
+
baton_registry.pop(old_key, None)
|
| 1556 |
+
baton_registry[ray.ray_id] = out_baton
|
| 1557 |
+
baton_registry_keys.append(ray.ray_id)
|
| 1558 |
|
| 1559 |
if improved:
|
| 1560 |
+
best_ce = final_ce
|
| 1561 |
+
best_binding = dict(final_b)
|
| 1562 |
+
successful_rays.append(ray)
|
| 1563 |
+
model.best_binding = best_binding
|
| 1564 |
+
model.best_ce = best_ce
|
| 1565 |
+
model.best_ray = ray.name
|
| 1566 |
|
| 1567 |
+
if overall_pass:
|
| 1568 |
+
solved = True
|
| 1569 |
|
| 1570 |
if improved and len(ray.sequence) >= 2:
|
| 1571 |
pair = (ray.sequence[-2], ray.sequence[-1])
|
| 1572 |
+
if pair not in resonant_pairs:
|
| 1573 |
+
resonant_pairs.append(pair)
|
| 1574 |
model.resonant_pairs = resonant_pairs
|
| 1575 |
|
| 1576 |
earned = (final_ce < parent_ce * CE_EARN_RATIO or ray.depth < 1)
|
|
|
|
| 1580 |
remaining = [a for a in ALL_AXIOMS if a != ray.sequence[-1] and frozenset([ray.sequence[-1], a]) not in _CONTRA_SET and a not in ray.sequence]
|
| 1581 |
new_children = []
|
| 1582 |
new_children.extend(CREATIVE_SEEDER.intelligent_branch(ray, out_baton, remaining, BRANCH_WIDTH, sketch=sketch))
|
| 1583 |
+
|
| 1584 |
inv = CREATIVE_SEEDER.invert(ray, final_ce)
|
| 1585 |
+
if inv:
|
| 1586 |
+
new_children.append(inv)
|
| 1587 |
+
|
| 1588 |
if len(successful_rays) >= 2:
|
| 1589 |
candidates = [r for r in successful_rays if r.ray_id != ray.ray_id]
|
| 1590 |
if candidates:
|
| 1591 |
+
partner = random.choice(candidates)
|
| 1592 |
+
ba = baton_registry.get(ray.ray_id, out_baton)
|
| 1593 |
+
bb = baton_registry.get(partner.ray_id)
|
| 1594 |
+
if bb is not None:
|
| 1595 |
+
new_children.extend(CREATIVE_SEEDER.recombine(ray, partner, ba, bb)[:3])
|
| 1596 |
+
|
| 1597 |
new_children.extend(CREATIVE_SEEDER.resonance_extensions(ray, final_ce, resonant_pairs))
|
| 1598 |
+
|
| 1599 |
for child in new_children:
|
| 1600 |
+
if child.ray_type in ("seed", "branch", "target"):
|
| 1601 |
+
queues["core"].append(child)
|
| 1602 |
+
elif child.ray_type in ("scout", "tension"):
|
| 1603 |
+
queues["explore"].append(child)
|
| 1604 |
+
elif child.ray_type in ("recombine", "invert"):
|
| 1605 |
+
queues["genetic"].append(child)
|
| 1606 |
|
| 1607 |
queues["core"].sort(key=lambda r: r.ce_prior + (r.depth * 0.0001))
|
| 1608 |
queues["genetic"].sort(key=lambda r: r.ce_prior + (r.depth * 0.0001))
|
| 1609 |
|
| 1610 |
with STATE_LOCK:
|
| 1611 |
+
GLOBAL_SOLVE_STATE["best_ce"] = best_ce
|
| 1612 |
+
GLOBAL_SOLVE_STATE["total_fired"] = total_fired
|
| 1613 |
+
GLOBAL_SOLVE_STATE["best_ray"] = model.best_ray
|
| 1614 |
+
for t in batch_heroes:
|
| 1615 |
+
GLOBAL_SOLVE_STATE["recent_traces"].append(t)
|
| 1616 |
|
| 1617 |
if solved: break
|
| 1618 |
|
|
|
|
| 1656 |
resp = client.models.generate_content(model=GEMINI_MODEL, contents=[types.Content(role="user", parts=[types.Part.from_text(text=problem_text)])], config=config)
|
| 1657 |
|
| 1658 |
text = resp.text.strip()
|
| 1659 |
+
if text.startswith("```"):
|
| 1660 |
+
text = text.split("```")[1]
|
| 1661 |
+
if text.startswith("json"):
|
| 1662 |
+
text = text[4:]
|
| 1663 |
+
|
| 1664 |
text = text.strip().rstrip("`").strip()
|
| 1665 |
d = json.loads(text)
|
| 1666 |
|
| 1667 |
anchors = [AXLInvariant(name=a["name"], expr=a["expr"], tolerance=a.get("tolerance", VERIFY_G2_TOLERANCE), mode=a.get("mode", "eq")) for a in d.get("anchors", [])]
|
| 1668 |
variables = [{"name": v["name"], "lo": float(v.get("lo", -1000.0)), "hi": float(v.get("hi", 1000.0))} for v in d["variables"]]
|
| 1669 |
+
|
| 1670 |
return AXLProblemDef(name=d["name"], description=d.get("description", ""), axioms=set(), variables=variables, constraints=d.get("constraints", []), scopes=d.get("scopes", []), anchors=anchors, observations=d.get("observations", {}))
|
| 1671 |
|
| 1672 |
def collapse_solution(problem_text, axl_def, psl_text, binding, g1_pass, g2_pass, inv_results, best_ray, total_fired, sketch_notes, sympy_derivation, api_key) -> str:
|
| 1673 |
if not api_key: return "ERROR: API Key required."
|
| 1674 |
client = genai.Client(api_key=api_key)
|
| 1675 |
+
|
| 1676 |
+
payload = {
|
| 1677 |
+
"original_problem": problem_text,
|
| 1678 |
+
"solved": g1_pass and g2_pass,
|
| 1679 |
+
"binding": {k: round(v, 6) for k, v in binding.items()},
|
| 1680 |
+
"psl_program_text": psl_text,
|
| 1681 |
+
"isomorphism_hypothesis": best_ray,
|
| 1682 |
+
"structural_sketch_notes": sketch_notes,
|
| 1683 |
+
"sympy_derivation_chain": sympy_derivation,
|
| 1684 |
+
"invariant_results": inv_results
|
| 1685 |
+
}
|
| 1686 |
+
|
| 1687 |
config = types.GenerateContentConfig(thinking_config=types.ThinkingConfig(thinking_level="HIGH"), system_instruction=[types.Part.from_text(text=COLLAPSER_SYSTEM_PROMPT)], temperature=0.2)
|
| 1688 |
resp = client.models.generate_content(model=GEMINI_MODEL, contents=[types.Content(role="user", parts=[types.Part.from_text(text=json.dumps(payload, indent=2))])], config=config)
|
| 1689 |
return resp.text
|
| 1690 |
|
| 1691 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1692 |
+
# SECTION 15: GLOBAL SOLVE TASK (With Thread Crash Safety)
|
| 1693 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1694 |
def global_solve_task(original_problem_text, api_key, prebuilt_axl=None):
|
| 1695 |
+
_update_state(
|
| 1696 |
+
is_running=True, phase="ENCODING", high_level_logs=[], answer="",
|
| 1697 |
+
best_ce=float('inf'), total_fired=0, best_ray="β", recent_traces=deque(maxlen=25),
|
| 1698 |
+
sketch_summary="", template_count=0, template_best_ce=float('inf'), sympy_derivation=[]
|
| 1699 |
+
)
|
| 1700 |
+
|
| 1701 |
+
try:
|
| 1702 |
+
MAX_ATTEMPTS = 3
|
| 1703 |
+
current_text = original_problem_text
|
| 1704 |
+
used_key = api_key or DEFAULT_GEMINI_API_KEY
|
| 1705 |
+
sketch_notes = []
|
| 1706 |
+
|
| 1707 |
+
for attempt in range(1, MAX_ATTEMPTS + 1):
|
| 1708 |
+
if prebuilt_axl is not None:
|
| 1709 |
+
_add_log("β‘ Bypassing Encoder: Using Pre-compiled Quantum AXL")
|
| 1710 |
+
axl_def = prebuilt_axl
|
| 1711 |
+
else:
|
| 1712 |
+
_add_log(f"π Encoding (attempt {attempt}/{MAX_ATTEMPTS})β¦")
|
| 1713 |
+
try:
|
| 1714 |
+
axl_def = encode_problem_to_axl(current_text, used_key)
|
| 1715 |
+
except Exception as e:
|
| 1716 |
+
_add_log(f"β Encode failed: {e}")
|
| 1717 |
+
_update_state(phase="ERROR", answer=f"Encoder API Failed: {str(e)}")
|
| 1718 |
+
return
|
| 1719 |
+
|
| 1720 |
+
_add_log(f"β `{axl_def.name}` | vars: {', '.join(v['name'] for v in axl_def.variables)}")
|
| 1721 |
+
_update_state(phase="COMPILING")
|
| 1722 |
+
|
| 1723 |
+
try:
|
| 1724 |
+
psl_text = AXL_COMPILER.compile(axl_def)
|
| 1725 |
+
base_prob = build_base_problem(axl_def)
|
| 1726 |
+
except Exception as e:
|
| 1727 |
+
_add_log(f"β Compile failed: {e}")
|
| 1728 |
+
_update_state(phase="ERROR", answer=f"Compiler Failed: {str(e)}")
|
| 1729 |
+
return
|
| 1730 |
+
|
| 1731 |
+
try:
|
| 1732 |
+
tracer = SequenceRayTracer()
|
| 1733 |
+
binding, ce, traces, total_fired, allosteric = tracer.trace(axl_def, base_prob)
|
| 1734 |
+
except Exception as e:
|
| 1735 |
+
_add_log(f"β Solver error: {e}")
|
| 1736 |
+
_update_state(phase="ERROR", answer=f"Ray Tracer Crashed: {str(e)}")
|
| 1737 |
+
return
|
| 1738 |
+
|
| 1739 |
+
with STATE_LOCK:
|
| 1740 |
+
sketch_notes = GLOBAL_SOLVE_STATE.get("sketch_summary", "").split("; ")
|
| 1741 |
+
current_sympy_derivation = GLOBAL_SOLVE_STATE.get("sympy_derivation", [])
|
| 1742 |
+
|
| 1743 |
+
survived = [t for t in traces if t.survived]
|
| 1744 |
+
best_t = min(survived, key=lambda t: t.ce_after, default=None)
|
| 1745 |
+
|
| 1746 |
+
for inv in axl_def.anchors:
|
| 1747 |
+
if not inv.compiled_func:
|
| 1748 |
+
inv.compile(base_prob.variables)
|
| 1749 |
+
|
| 1750 |
+
g1_ce = base_prob.scalar_energy(binding)
|
| 1751 |
+
g1_pass = g1_ce < VERIFY_G1_THRESHOLD
|
| 1752 |
+
inv_results = {}
|
| 1753 |
+
|
| 1754 |
+
for inv in axl_def.anchors:
|
| 1755 |
+
try:
|
| 1756 |
+
val = float(inv.compiled_func(*[binding.get(v, 0.0) for v in inv.syms_used]))
|
| 1757 |
+
err = abs(val)
|
| 1758 |
+
if inv.mode == "eq":
|
| 1759 |
+
passed = err < inv.tolerance
|
| 1760 |
+
elif inv.mode == "geq":
|
| 1761 |
+
passed = val >= -inv.tolerance
|
| 1762 |
+
else:
|
| 1763 |
+
passed = val <= inv.tolerance
|
| 1764 |
+
inv_results[inv.name] = (round(val, 6), passed)
|
| 1765 |
+
except:
|
| 1766 |
+
inv_results[inv.name] = (999.0, False)
|
| 1767 |
+
|
| 1768 |
+
g2_pass = all(v[1] for v in inv_results.values())
|
| 1769 |
+
|
| 1770 |
+
solved_str = "β SOLVED" if (g1_pass and g2_pass) else "~ PARTIAL" if g1_pass else "β UNSOLVED"
|
| 1771 |
+
best_ray = best_t.ray_name if best_t else "β"
|
| 1772 |
+
_add_log(f"π {solved_str} (CE: {ce:.5f}) | Ray: {best_ray}")
|
| 1773 |
+
|
| 1774 |
+
if prebuilt_axl is None:
|
| 1775 |
+
if not g1_pass and attempt < MAX_ATTEMPTS:
|
| 1776 |
+
current_text = (original_problem_text + f"\n\nPREVIOUS ATTEMPT FAILED (Best CE: {ce}):\nGEOMETRIC SOLVER FAILED. Apply ALGEBRAIC REDUCTION: substitute simple equalities to eliminate variables, output simplified AXL.")
|
| 1777 |
+
_add_log("β Geometric solver failed. Triggering algebraic reductionβ¦")
|
| 1778 |
+
continue
|
| 1779 |
+
if not g2_pass and attempt < MAX_ATTEMPTS:
|
| 1780 |
+
failed = {k: v for k, (v, ok) in inv_results.items() if not ok}
|
| 1781 |
+
current_text = (original_problem_text + f"\n\nPREVIOUS ATTEMPT FAILED:\nGate 2 failed:\n{json.dumps(failed, indent=2)}\nRevise constraint encoding to capture these conditions.")
|
| 1782 |
+
_add_log("β Gate 2 failed. Retrying with structural feedbackβ¦")
|
| 1783 |
+
continue
|
| 1784 |
+
|
| 1785 |
+
_add_log("π€ Collapsing isomorphism to domain languageβ¦")
|
| 1786 |
+
_update_state(phase="COLLAPSING")
|
| 1787 |
try:
|
| 1788 |
+
answer = collapse_solution(original_problem_text, axl_def, psl_text, binding, g1_pass, g2_pass, inv_results, best_ray, total_fired, sketch_notes, current_sympy_derivation, used_key)
|
| 1789 |
+
_update_state(answer=answer, phase="DONE")
|
| 1790 |
+
_add_log("β Done.")
|
| 1791 |
+
except Exception as e:
|
| 1792 |
+
_update_state(answer=f"Collapsing error: {e}", phase="ERROR")
|
| 1793 |
+
_add_log("β Collapse failed.")
|
| 1794 |
+
break
|
| 1795 |
+
|
| 1796 |
+
except Exception as e:
|
| 1797 |
+
_add_log(f"π₯ FATAL SYSTEM ERROR: {str(e)}")
|
| 1798 |
+
_update_state(phase="ERROR", answer=f"Fatal System Error: {str(e)}")
|
| 1799 |
+
finally:
|
| 1800 |
+
# ABSOLUTE GUARANTEE: Never lock the UI
|
| 1801 |
+
_update_state(is_running=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1802 |
|
| 1803 |
def trigger_solve(problem_text, api_key):
|
| 1804 |
if GLOBAL_SOLVE_STATE["is_running"] or not problem_text.strip(): return
|
|
|
|
| 1806 |
|
| 1807 |
def trigger_quantum_solve(example_name, api_key):
|
| 1808 |
if not HAS_QUANTUM or GLOBAL_SOLVE_STATE["is_running"]: return
|
|
|
|
| 1809 |
|
| 1810 |
+
# We yield control to the thread immediately so the button click finishes safely
|
| 1811 |
+
def _run_q():
|
| 1812 |
+
if example_name == "Bell State":
|
| 1813 |
+
circ = QuantumCircuits.example_bell_state()
|
| 1814 |
+
elif example_name == "VQE H2":
|
| 1815 |
+
circ = QuantumCircuits.example_vqe_h2()
|
| 1816 |
+
elif example_name == "QAOA MaxCut":
|
| 1817 |
+
circ = QuantumCircuits.example_qaoa_maxcut_p1()
|
| 1818 |
+
else:
|
| 1819 |
+
return
|
| 1820 |
+
|
| 1821 |
+
problem_desc = f"Quantum Circuit: {circ.name}\nDescription: {circ.description}\nTarget Observables: {circ.expected_observables}"
|
| 1822 |
+
|
| 1823 |
+
try:
|
| 1824 |
+
axl_def = QuantumCircuits.build_quantum_axl(circ, AXLProblemDef, AXLInvariant)
|
| 1825 |
+
except Exception as e:
|
| 1826 |
+
_update_state(is_running=False, phase="ERROR", answer=f"Quantum compiler failed: {str(e)}")
|
| 1827 |
+
return
|
| 1828 |
+
|
| 1829 |
+
global_solve_task(problem_desc, api_key, axl_def)
|
| 1830 |
|
| 1831 |
+
threading.Thread(target=_run_q, daemon=True).start()
|
| 1832 |
|
| 1833 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1834 |
# SECTION 16: GRADIO INTERFACE
|
| 1835 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1836 |
+
# Layout fixes for mobile sizing and wrapping
|
| 1837 |
+
CSS = """
|
| 1838 |
+
body { background: #090909; color: #e0e0e0; font-family: monospace; }
|
| 1839 |
+
.solver-log { font-size: 0.75em; background: #0d0d0d; border: 1px solid #181818; }
|
| 1840 |
+
.answer-box { font-size: 0.85em; background: #0d0d0d; border: 1px solid #222; padding: 10px; }
|
| 1841 |
+
.wrap-row { flex-wrap: wrap !important; }
|
| 1842 |
+
"""
|
| 1843 |
+
|
| 1844 |
+
RAY_ICONS = {
|
| 1845 |
+
"seed": "π±", "branch": "πΏ", "tension": "β‘", "scout": "π",
|
| 1846 |
+
"recombine": "π§¬", "invert": "π", "target": "π―", "template": "πΊ", "fallback": "Β·"
|
| 1847 |
+
}
|
| 1848 |
|
|
|
|
| 1849 |
PLACEHOLDER_HINT = textwrap.dedent("""
|
| 1850 |
Try any natural language problem. Gemini encodes it, the system finds the structural solution.
|
| 1851 |
Examples:
|
|
|
|
| 1855 |
|
| 1856 |
def build_live_html():
|
| 1857 |
with STATE_LOCK:
|
| 1858 |
+
phase = GLOBAL_SOLVE_STATE["phase"]
|
| 1859 |
+
ce = GLOBAL_SOLVE_STATE["best_ce"]
|
| 1860 |
+
fired = GLOBAL_SOLVE_STATE["total_fired"]
|
| 1861 |
+
best_ray = GLOBAL_SOLVE_STATE["best_ray"]
|
| 1862 |
+
traces = list(GLOBAL_SOLVE_STATE["recent_traces"])
|
| 1863 |
+
logs = GLOBAL_SOLVE_STATE["high_level_logs"]
|
| 1864 |
sketch_summary = GLOBAL_SOLVE_STATE["sketch_summary"]
|
| 1865 |
+
template_count = GLOBAL_SOLVE_STATE["template_count"]
|
| 1866 |
+
template_best = GLOBAL_SOLVE_STATE["template_best_ce"]
|
| 1867 |
|
| 1868 |
ce_color = "#4CAF50" if ce < SOLVE_THRESHOLD else "#FF9800"
|
| 1869 |
+
|
| 1870 |
+
if phase in ["SEARCHING", "COLLAPSING", "ENCODING", "SKETCHING", "TEMPLATING"]:
|
| 1871 |
+
phase_color = "#26C6DA"
|
| 1872 |
+
elif phase == "DONE":
|
| 1873 |
+
phase_color = "#4CAF50"
|
| 1874 |
+
elif phase == "ERROR":
|
| 1875 |
+
phase_color = "#F44336"
|
| 1876 |
+
else:
|
| 1877 |
+
phase_color = "#888"
|
| 1878 |
|
| 1879 |
log_html = "<ul style='margin:0;padding-left:20px;color:#aaa;font-size:0.82em'>"
|
| 1880 |
+
for l in logs[-5:]:
|
| 1881 |
+
log_html += f"<li>{l}</li>"
|
| 1882 |
log_html += "</ul>"
|
| 1883 |
|
| 1884 |
+
sketch_html = ""
|
| 1885 |
+
if sketch_summary:
|
| 1886 |
+
sketch_html = f"<div style='color:#555;font-size:0.72em;margin:6px 0;padding:4px 8px;border-left:2px solid #26C6DA;background:#0a0a0a'>πΊ <span style='color:#26C6DA'>Sketch</span>: {sketch_summary[:120]}</div>"
|
| 1887 |
+
|
| 1888 |
+
template_html = ""
|
| 1889 |
+
if template_count > 0:
|
| 1890 |
+
t_ce_str = f"{template_best:.5f}" if template_best < float('inf') else "β"
|
| 1891 |
+
template_html = f"<div style='color:#555;font-size:0.72em;margin:4px 0'>πΊ Templates: {template_count} generated | floor CE: {t_ce_str}</div>"
|
| 1892 |
|
| 1893 |
ray_trail = ""
|
| 1894 |
for t in reversed(traces):
|
| 1895 |
+
icon = RAY_ICONS.get(t.ray_type, "Β·")
|
| 1896 |
+
c = "#4CAF50" if t.survived else "#555"
|
| 1897 |
+
star = " β" if t.survived else ""
|
| 1898 |
ray_trail += f"<div style='color:{c};font-size:0.78em;margin-bottom:2px'>{icon} [{t.ray_name}] CE={t.ce_after:.4f} <span style='color:#888'>({t.tension_class[:3]})</span><span style='color:#4CAF50;font-weight:700'>{star}</span></div>"
|
| 1899 |
|
| 1900 |
+
return f"""
|
| 1901 |
+
<div style='border:1px solid #222;border-radius:6px;padding:12px;background:#0d0d0d;min-height:440px;display:flex;flex-direction:column'>
|
| 1902 |
<div style='color:{phase_color};font-weight:bold;margin-bottom:8px'>β Phase: {phase}</div>
|
| 1903 |
<div style='margin-bottom:10px;border-bottom:1px solid #222;padding-bottom:8px'>{log_html}</div>
|
| 1904 |
{sketch_html}{template_html}
|
|
|
|
| 1908 |
</div>
|
| 1909 |
<div style='color:#aaa;margin-bottom:8px;font-size:0.85em'>Best Iso: <span style='color:#FF9800'>{best_ray}</span></div>
|
| 1910 |
<div style='flex:1;overflow-y:auto;border-top:1px solid #222;padding-top:8px'>{ray_trail}</div>
|
| 1911 |
+
</div>
|
| 1912 |
+
"""
|
| 1913 |
|
| 1914 |
with gr.Blocks(css=CSS, title="Practicality 24.1") as demo:
|
| 1915 |
gr.Markdown("## β Practicality 24.1 β Structural Sketch, World Model Prior & Quantum Engine\n`[Gemini Encoder] β [Structural Sketch / SymPy] β [Morphing Ray Solver] β [Gemini Collapser]`")
|
| 1916 |
+
|
| 1917 |
+
with gr.Row(elem_classes=["wrap-row"]):
|
| 1918 |
+
with gr.Column(scale=2, min_width=300):
|
| 1919 |
api_key_input = gr.Textbox(label="Gemini API Key", type="password", placeholder="AIza...", value=DEFAULT_GEMINI_API_KEY, elem_classes=["solver-log"])
|
| 1920 |
with gr.Tabs():
|
| 1921 |
with gr.Tab("Natural Language"):
|
| 1922 |
problem_input = gr.Textbox(label="Problem Description", placeholder=PLACEHOLDER_HINT, lines=5, elem_classes=["solver-log"])
|
| 1923 |
with gr.Row():
|
| 1924 |
+
solve_btn = gr.Button("β Solve Natural Language", variant="primary")
|
| 1925 |
+
clear_btn = gr.Button("Clear")
|
| 1926 |
+
|
| 1927 |
if HAS_QUANTUM:
|
| 1928 |
with gr.Tab("Quantum Circuits (Heisenberg Abstraction)"):
|
| 1929 |
q_dropdown = gr.Dropdown(choices=["Bell State", "VQE H2", "QAOA MaxCut"], label="Select Circuit Template", value="Bell State")
|
| 1930 |
q_solve_btn = gr.Button("β Run Quantum Solver (Bypass Encoder)", variant="primary")
|
| 1931 |
+
|
| 1932 |
+
with gr.Column(scale=1, min_width=250):
|
| 1933 |
+
gr.Textbox(value=(f"Compute: {DEVICE.type.upper()}\n"
|
| 1934 |
+
f"Axioms: {len(ALL_AXIOMS)}\n"
|
| 1935 |
+
f"New: Thread Crash Safety & UI Layout Fix\n"
|
| 1936 |
+
f"New: Quantum BBGKY Cumulant Expansion\n"
|
| 1937 |
+
f"New: Homotopy Continuation (Morphing Ray)\n"
|
| 1938 |
+
f"New: Anchor Fix (Gate 2 Sync)"),
|
| 1939 |
+
lines=7, interactive=False, elem_classes=["solver-log"])
|
| 1940 |
+
|
| 1941 |
+
with gr.Row(elem_classes=["wrap-row"]):
|
| 1942 |
+
with gr.Column(scale=1, min_width=300):
|
| 1943 |
+
live_html = gr.HTML(value=build_live_html())
|
| 1944 |
+
with gr.Column(scale=1, min_width=300):
|
| 1945 |
+
answer_box = gr.Textbox(label="Isomorphic Collapse", lines=20, interactive=False, elem_classes=["answer-box"])
|
| 1946 |
|
| 1947 |
def fetch_ui():
|
| 1948 |
while True:
|
| 1949 |
+
time.sleep(1.0)
|
| 1950 |
+
yield build_live_html(), GLOBAL_SOLVE_STATE["answer"]
|
| 1951 |
|
| 1952 |
solve_btn.click(fn=trigger_solve, inputs=[problem_input, api_key_input], outputs=None)
|
| 1953 |
clear_btn.click(fn=lambda: ("", "", ""), inputs=[], outputs=[problem_input, live_html, answer_box])
|
| 1954 |
+
|
| 1955 |
+
if HAS_QUANTUM:
|
| 1956 |
+
q_solve_btn.click(fn=trigger_quantum_solve, inputs=[q_dropdown, api_key_input], outputs=None)
|
| 1957 |
+
|
| 1958 |
demo.load(fetch_ui, inputs=None, outputs=[live_html, answer_box])
|
| 1959 |
|
| 1960 |
if __name__ == "__main__":
|
| 1961 |
print(f"[SYSTEM 24.1] Compute: {DEVICE.type.upper()} | Feature Flags: Quantum={HAS_QUANTUM}")
|
| 1962 |
+
demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
|