Spaces:
Sleeping
Sleeping
Update practicality_axioms.py
Browse files- practicality_axioms.py +97 -8
practicality_axioms.py
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
import random
|
| 3 |
import torch
|
| 4 |
import itertools
|
| 5 |
-
from typing import Dict, List, Tuple, Set, Optional, Any
|
| 6 |
from dataclasses import dataclass, field
|
|
|
|
| 7 |
import practicality_core as core
|
| 8 |
|
| 9 |
@dataclass
|
|
@@ -56,9 +65,13 @@ class StructuralModel:
|
|
| 56 |
class Axiom:
|
| 57 |
CONTINUOUS = "CONTINUOUS"; DISCRETE = "DISCRETE"; QUADRATIC = "QUADRATIC"
|
| 58 |
BILINEAR = "BILINEAR"; METRIC = "METRIC"; SYMMETRIC = "SYMMETRIC"
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
|
| 63 |
ALL_AXIOMS = [getattr(Axiom, a) for a in dir(Axiom) if not a.startswith("__")]
|
| 64 |
|
|
@@ -71,6 +84,7 @@ def _make_hyp(hid, binding, h_type, claim, derivation, pinned, free, conf, is_fd
|
|
| 71 |
confidence=conf, is_fully_determined=is_fd)
|
| 72 |
|
| 73 |
def _hyp_continuous(p, bt, a, m): return [_make_hyp("cnt", bt.binding, "continuous", "Manifold", [], {}, p.variables, 0.45)]
|
|
|
|
| 74 |
def _hyp_discrete(p, bt, a, m):
|
| 75 |
b = dict(bt.binding); pinned = {}
|
| 76 |
box = {v: core.IV(b.get(v, 0)-max(0.05*(p.bounds[v][1]-p.bounds[v][0]), 1e-4),
|
|
@@ -81,11 +95,13 @@ def _hyp_discrete(p, bt, a, m):
|
|
| 81 |
b[v] = iv.mid()
|
| 82 |
if iv.width() < 1e-2: pinned[v] = b[v]
|
| 83 |
return [_make_hyp("dis", b, "discrete", "TopoScope", [], pinned, p.variables, 0.80)]
|
|
|
|
| 84 |
def _hyp_quadratic(p, bt, a, m):
|
| 85 |
hyps = []; b = dict(bt.binding)
|
| 86 |
if bt.l9 and bt.l9.dominant_vars:
|
| 87 |
for v in bt.l9.dominant_vars[:2]: hyps.append(_make_hyp(f"qua_{v}", b, "quadratic", f"Root({v})", [], {v: b[v]}, p.variables, 0.70))
|
| 88 |
return hyps if hyps else [_make_hyp("qua", b, "quadratic", "Root", [], {}, p.variables, 0.55)]
|
|
|
|
| 89 |
def _hyp_bilinear(p, bt, a, m):
|
| 90 |
hyps = []; b = dict(bt.binding)
|
| 91 |
for vi, vj in p.bilinear_pairs:
|
|
@@ -97,6 +113,7 @@ def _hyp_bilinear(p, bt, a, m):
|
|
| 97 |
nb = dict(b); nb[vi] = nb[vj] = gm
|
| 98 |
hyps.append(_make_hyp(f"bil_eq_{vi}_{vj}", nb, "bilinear", "GeoMean", ["bilinear"], {vi: gm, vj: gm}, [v for v in p.variables if v not in [vi, vj]], 0.70))
|
| 99 |
return hyps
|
|
|
|
| 100 |
def _hyp_monotone_product(p, bt, a, m):
|
| 101 |
hyps = []; b = dict(bt.binding)
|
| 102 |
if not p.monotone_targets: return hyps
|
|
@@ -120,6 +137,7 @@ def _hyp_monotone_product(p, bt, a, m):
|
|
| 120 |
hyps.append(_make_hyp(f"mpr_{v_small}_{v_large}_r{int(ratio*100)}", nb, "monotone_product",
|
| 121 |
"MonoProd", ["ordered", "hc4"], pinned, [u for u in p.variables if u not in pinned], 0.88))
|
| 122 |
return hyps
|
|
|
|
| 123 |
def _hyp_metric(p, bt, a, m):
|
| 124 |
hyps = []; b = dict(bt.binding)
|
| 125 |
for mc in p.compiled_constraints:
|
|
@@ -139,6 +157,7 @@ def _hyp_metric(p, bt, a, m):
|
|
| 139 |
lo, hi = p.bounds.get(v, (-10, 10)); nb[v] = max(lo, min(hi, b.get(v, 0)*scale))
|
| 140 |
hyps.append(_make_hyp(f"met_{hash(mc.expr_str)%9999}", nb, "metric", "RadialProject", ["metric", mc.expr_str], {}, list(p.variables), 0.75))
|
| 141 |
return hyps
|
|
|
|
| 142 |
def _hyp_symmetric(p, bt, a, m):
|
| 143 |
hyps = []; b = dict(bt.binding)
|
| 144 |
vl = p.variables
|
|
@@ -151,21 +170,43 @@ def _hyp_symmetric(p, bt, a, m):
|
|
| 151 |
nb = dict(b); nb[vi], nb[vj] = bvj, bvi
|
| 152 |
hyps.append(_make_hyp(f"sym_{vi}_{vj}", nb, "symmetric", "Swap", ["symmetric"], {vi: nb[vi], vj: nb[vj]}, [v for v in p.variables if v not in [vi, vj]], 0.60))
|
| 153 |
return hyps[:5]
|
|
|
|
| 154 |
def _hyp_ordered(p, bt, a, m): return [_make_hyp("ord", bt.binding, "ordered", "OrderBal", [], {}, p.variables, 0.67)]
|
| 155 |
def _hyp_monotone(p, bt, a, m): return [_make_hyp("mon", bt.binding, "monotone", "MonoPath", [], {}, p.variables, 0.67)]
|
|
|
|
|
|
|
|
|
|
| 156 |
def _hyp_mutable(p, bt, a, m):
|
| 157 |
b = dict(bt.binding); pinned = {}
|
| 158 |
if bt.l9 and bt.l9.dominant_vars:
|
| 159 |
v = bt.l9.dominant_vars[0]; lo, hi = p.bounds.get(v, (-10, 10))
|
| 160 |
b[v] = max(lo, min(hi, b.get(v, 0)+random.gauss(0, (hi-lo)*0.05))); pinned = {v: b[v]}
|
| 161 |
return [_make_hyp("mut", b, "mutable", "Perturb", [], pinned, p.variables, 0.40)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
def _hyp_extremal(p, bt, a, m):
|
| 163 |
hyps = []; b = dict(bt.binding)
|
| 164 |
if bt.l9 and bt.l9.dominant_vars:
|
| 165 |
v = bt.l9.dominant_vars[0]; lo, hi = p.bounds.get(v, (0, 1))
|
| 166 |
for val in [lo, hi]: nb = dict(b); nb[v] = val; hyps.append(_make_hyp(f"ext_{v}_{val:.3f}", nb, "extremal", "PinBound", [], {v: val}, p.variables, 0.65))
|
| 167 |
return hyps
|
|
|
|
| 168 |
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)]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
def _hyp_atomic(p, bt, a, m):
|
| 170 |
hyps = []; b = dict(bt.binding)
|
| 171 |
for mc in p.compiled_constraints:
|
|
@@ -179,6 +220,14 @@ def _hyp_atomic(p, bt, a, m):
|
|
| 179 |
except: pass
|
| 180 |
if hyps: break
|
| 181 |
return hyps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
def _hyp_parsimony(p, bt, a, m):
|
| 183 |
b = dict(bt.binding); nb = {}
|
| 184 |
max_val = max((abs(v) for v in b.values() if math.isfinite(v)), default=1.0)
|
|
@@ -190,6 +239,7 @@ def _hyp_parsimony(p, bt, a, m):
|
|
| 190 |
candidates = [round(val*m)/m for m in [1, 2, 4] if lo <= round(val*m)/m <= hi]
|
| 191 |
nb[v] = min(candidates, key=lambda c: abs(c-val)) if candidates else val
|
| 192 |
return [_make_hyp("par", nb, "parsimony", "Occam", [], {}, p.variables, 0.58)]
|
|
|
|
| 193 |
def _hyp_duality(p, bt, a, m): return [_make_hyp("dua", bt.binding, "duality", "Tight", [], {}, p.variables, 0.68)]
|
| 194 |
|
| 195 |
AXIOM_CONSTRUCTORS = {
|
|
@@ -197,10 +247,16 @@ AXIOM_CONSTRUCTORS = {
|
|
| 197 |
Axiom.QUADRATIC: _hyp_quadratic, Axiom.BILINEAR: _hyp_bilinear,
|
| 198 |
Axiom.METRIC: _hyp_metric, Axiom.SYMMETRIC: _hyp_symmetric,
|
| 199 |
Axiom.ORDERED: _hyp_ordered, Axiom.MONOTONE: _hyp_monotone,
|
| 200 |
-
Axiom.
|
| 201 |
-
Axiom.
|
| 202 |
-
Axiom.
|
| 203 |
-
Axiom.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
}
|
| 205 |
|
| 206 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -379,6 +435,39 @@ class SequenceRayTracer:
|
|
| 379 |
|
| 380 |
return best_binding, best_ce, traces, best_ray_name
|
| 381 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 382 |
# Re-expose batch optimization so axioms engine remains self-contained
|
| 383 |
_batched_deduce_and_evaluate = axioms._batched_deduce_and_evaluate
|
| 384 |
_mprt_sample = axioms._mprt_sample
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
practicality_axioms.py
|
| 3 |
+
======================
|
| 4 |
+
The complete, unabridged Axiom Deduction Engine.
|
| 5 |
+
Houses all 28 structural axioms, constructors, the UCB1 Bandit,
|
| 6 |
+
and the full decoupled SequenceRayTracer.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
import math
|
| 10 |
import random
|
| 11 |
import torch
|
| 12 |
import itertools
|
| 13 |
+
from typing import Dict, List, Tuple, Set, Optional, Any, Callable
|
| 14 |
from dataclasses import dataclass, field
|
| 15 |
+
from collections import defaultdict, deque
|
| 16 |
import practicality_core as core
|
| 17 |
|
| 18 |
@dataclass
|
|
|
|
| 65 |
class Axiom:
|
| 66 |
CONTINUOUS = "CONTINUOUS"; DISCRETE = "DISCRETE"; QUADRATIC = "QUADRATIC"
|
| 67 |
BILINEAR = "BILINEAR"; METRIC = "METRIC"; SYMMETRIC = "SYMMETRIC"
|
| 68 |
+
ORDERED = "ORDERED"; MONOTONE = "MONOTONE"; CONVEX = "CONVEX"
|
| 69 |
+
MONOTONE_PRODUCT = "MONOTONE_PRODUCT"; CONSERVED = "CONSERVED"; MUTABLE = "MUTABLE"
|
| 70 |
+
NETWORK = "NETWORK"; EQUILIBRIUM = "EQUILIBRIUM"; SUPERPOSITION = "SUPERPOSITION"
|
| 71 |
+
LOCALITY = "LOCALITY"; EXTREMAL = "EXTREMAL"; ENTROPY = "ENTROPY"
|
| 72 |
+
INJECTIVE = "INJECTIVE"; SURJECTIVE = "SURJECTIVE"; TRANSITIVE = "TRANSITIVE"
|
| 73 |
+
ATOMIC = "ATOMIC"; IMPLICATION = "IMPLICATION"; NEGATION = "NEGATION"
|
| 74 |
+
COMPOSITE = "COMPOSITE"; HOLISM = "HOLISM"; PARSIMONY = "PARSIMONY"; DUALITY = "DUALITY"
|
| 75 |
|
| 76 |
ALL_AXIOMS = [getattr(Axiom, a) for a in dir(Axiom) if not a.startswith("__")]
|
| 77 |
|
|
|
|
| 84 |
confidence=conf, is_fully_determined=is_fd)
|
| 85 |
|
| 86 |
def _hyp_continuous(p, bt, a, m): return [_make_hyp("cnt", bt.binding, "continuous", "Manifold", [], {}, p.variables, 0.45)]
|
| 87 |
+
|
| 88 |
def _hyp_discrete(p, bt, a, m):
|
| 89 |
b = dict(bt.binding); pinned = {}
|
| 90 |
box = {v: core.IV(b.get(v, 0)-max(0.05*(p.bounds[v][1]-p.bounds[v][0]), 1e-4),
|
|
|
|
| 95 |
b[v] = iv.mid()
|
| 96 |
if iv.width() < 1e-2: pinned[v] = b[v]
|
| 97 |
return [_make_hyp("dis", b, "discrete", "TopoScope", [], pinned, p.variables, 0.80)]
|
| 98 |
+
|
| 99 |
def _hyp_quadratic(p, bt, a, m):
|
| 100 |
hyps = []; b = dict(bt.binding)
|
| 101 |
if bt.l9 and bt.l9.dominant_vars:
|
| 102 |
for v in bt.l9.dominant_vars[:2]: hyps.append(_make_hyp(f"qua_{v}", b, "quadratic", f"Root({v})", [], {v: b[v]}, p.variables, 0.70))
|
| 103 |
return hyps if hyps else [_make_hyp("qua", b, "quadratic", "Root", [], {}, p.variables, 0.55)]
|
| 104 |
+
|
| 105 |
def _hyp_bilinear(p, bt, a, m):
|
| 106 |
hyps = []; b = dict(bt.binding)
|
| 107 |
for vi, vj in p.bilinear_pairs:
|
|
|
|
| 113 |
nb = dict(b); nb[vi] = nb[vj] = gm
|
| 114 |
hyps.append(_make_hyp(f"bil_eq_{vi}_{vj}", nb, "bilinear", "GeoMean", ["bilinear"], {vi: gm, vj: gm}, [v for v in p.variables if v not in [vi, vj]], 0.70))
|
| 115 |
return hyps
|
| 116 |
+
|
| 117 |
def _hyp_monotone_product(p, bt, a, m):
|
| 118 |
hyps = []; b = dict(bt.binding)
|
| 119 |
if not p.monotone_targets: return hyps
|
|
|
|
| 137 |
hyps.append(_make_hyp(f"mpr_{v_small}_{v_large}_r{int(ratio*100)}", nb, "monotone_product",
|
| 138 |
"MonoProd", ["ordered", "hc4"], pinned, [u for u in p.variables if u not in pinned], 0.88))
|
| 139 |
return hyps
|
| 140 |
+
|
| 141 |
def _hyp_metric(p, bt, a, m):
|
| 142 |
hyps = []; b = dict(bt.binding)
|
| 143 |
for mc in p.compiled_constraints:
|
|
|
|
| 157 |
lo, hi = p.bounds.get(v, (-10, 10)); nb[v] = max(lo, min(hi, b.get(v, 0)*scale))
|
| 158 |
hyps.append(_make_hyp(f"met_{hash(mc.expr_str)%9999}", nb, "metric", "RadialProject", ["metric", mc.expr_str], {}, list(p.variables), 0.75))
|
| 159 |
return hyps
|
| 160 |
+
|
| 161 |
def _hyp_symmetric(p, bt, a, m):
|
| 162 |
hyps = []; b = dict(bt.binding)
|
| 163 |
vl = p.variables
|
|
|
|
| 170 |
nb = dict(b); nb[vi], nb[vj] = bvj, bvi
|
| 171 |
hyps.append(_make_hyp(f"sym_{vi}_{vj}", nb, "symmetric", "Swap", ["symmetric"], {vi: nb[vi], vj: nb[vj]}, [v for v in p.variables if v not in [vi, vj]], 0.60))
|
| 172 |
return hyps[:5]
|
| 173 |
+
|
| 174 |
def _hyp_ordered(p, bt, a, m): return [_make_hyp("ord", bt.binding, "ordered", "OrderBal", [], {}, p.variables, 0.67)]
|
| 175 |
def _hyp_monotone(p, bt, a, m): return [_make_hyp("mon", bt.binding, "monotone", "MonoPath", [], {}, p.variables, 0.67)]
|
| 176 |
+
def _hyp_convex(p, bt, a, m): return [_make_hyp("cvx", bt.binding, "convex", "ConvMix", [], {}, p.variables, 0.63)]
|
| 177 |
+
def _hyp_conserved(p, bt, a, m): return [_make_hyp("csv", bt.binding, "conserved", "Conserve", [], {}, p.variables, 0.82)]
|
| 178 |
+
|
| 179 |
def _hyp_mutable(p, bt, a, m):
|
| 180 |
b = dict(bt.binding); pinned = {}
|
| 181 |
if bt.l9 and bt.l9.dominant_vars:
|
| 182 |
v = bt.l9.dominant_vars[0]; lo, hi = p.bounds.get(v, (-10, 10))
|
| 183 |
b[v] = max(lo, min(hi, b.get(v, 0)+random.gauss(0, (hi-lo)*0.05))); pinned = {v: b[v]}
|
| 184 |
return [_make_hyp("mut", b, "mutable", "Perturb", [], pinned, p.variables, 0.40)]
|
| 185 |
+
|
| 186 |
+
def _hyp_network(p, bt, a, m): return [_make_hyp("net", bt.binding, "network", "HubProp", [], {}, p.variables, 0.65)]
|
| 187 |
+
def _hyp_equilibrium(p, bt, a, m): return [_make_hyp("eql", bt.binding, "equilibrium", "GradBal", [], {}, p.variables, 0.72)]
|
| 188 |
+
|
| 189 |
+
def _hyp_superposition(p, bt, a, m):
|
| 190 |
+
if a and len(a)>0:
|
| 191 |
+
other=random.choice(a); lam=0.5
|
| 192 |
+
nb={v:lam*bt.binding.get(v,0)+(1-lam)*other.binding.get(v,0) for v in p.variables}
|
| 193 |
+
return [_make_hyp("sup",nb,"superposition","Superpose",[],{},p.variables,0.58)]
|
| 194 |
+
return []
|
| 195 |
+
|
| 196 |
+
def _hyp_locality(p, bt, a, m): return [_make_hyp("loc", bt.binding, "locality", "LocalFirst", [], {}, p.variables, 0.72)]
|
| 197 |
+
|
| 198 |
def _hyp_extremal(p, bt, a, m):
|
| 199 |
hyps = []; b = dict(bt.binding)
|
| 200 |
if bt.l9 and bt.l9.dominant_vars:
|
| 201 |
v = bt.l9.dominant_vars[0]; lo, hi = p.bounds.get(v, (0, 1))
|
| 202 |
for val in [lo, hi]: nb = dict(b); nb[v] = val; hyps.append(_make_hyp(f"ext_{v}_{val:.3f}", nb, "extremal", "PinBound", [], {v: val}, p.variables, 0.65))
|
| 203 |
return hyps
|
| 204 |
+
|
| 205 |
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)]
|
| 206 |
+
def _hyp_injective(p, bt, a, m): return [_make_hyp("inj", bt.binding, "injective", "Distinct", [], {}, p.variables, 0.50)]
|
| 207 |
+
def _hyp_surjective(p, bt, a, m): return [_make_hyp("sur", bt.binding, "surjective", "Sweep", [], {}, p.variables, 0.45)]
|
| 208 |
+
def _hyp_transitive(p, bt, a, m): return [_make_hyp("tra", bt.binding, "transitive", "TransSnap", [], {}, p.variables, 0.77)]
|
| 209 |
+
|
| 210 |
def _hyp_atomic(p, bt, a, m):
|
| 211 |
hyps = []; b = dict(bt.binding)
|
| 212 |
for mc in p.compiled_constraints:
|
|
|
|
| 220 |
except: pass
|
| 221 |
if hyps: break
|
| 222 |
return hyps
|
| 223 |
+
|
| 224 |
+
def _hyp_implication(p, bt, a, m): return [_make_hyp("imp", bt.binding, "implication", "Imply", [], {}, p.variables, 0.78)]
|
| 225 |
+
def _hyp_negation(p, bt, a, m):
|
| 226 |
+
nb={v:max(p.bounds[v][0],min(p.bounds[v][1],(p.bounds[v][0]+p.bounds[v][1])-bt.binding.get(v,(p.bounds[v][0]+p.bounds[v][1])/2))) for v in p.variables}
|
| 227 |
+
return [_make_hyp("neg",nb,"negation","Mirror",[],{},p.variables,0.42)]
|
| 228 |
+
def _hyp_composite(p, bt, a, m): return [_make_hyp("cmp", bt.binding, "composite", "Enz", [], {}, p.variables, 0.90)]
|
| 229 |
+
def _hyp_holism(p, bt, a, m): return [_make_hyp("hol", bt.binding, "holism", "Global", [], {}, p.variables, 0.73)]
|
| 230 |
+
|
| 231 |
def _hyp_parsimony(p, bt, a, m):
|
| 232 |
b = dict(bt.binding); nb = {}
|
| 233 |
max_val = max((abs(v) for v in b.values() if math.isfinite(v)), default=1.0)
|
|
|
|
| 239 |
candidates = [round(val*m)/m for m in [1, 2, 4] if lo <= round(val*m)/m <= hi]
|
| 240 |
nb[v] = min(candidates, key=lambda c: abs(c-val)) if candidates else val
|
| 241 |
return [_make_hyp("par", nb, "parsimony", "Occam", [], {}, p.variables, 0.58)]
|
| 242 |
+
|
| 243 |
def _hyp_duality(p, bt, a, m): return [_make_hyp("dua", bt.binding, "duality", "Tight", [], {}, p.variables, 0.68)]
|
| 244 |
|
| 245 |
AXIOM_CONSTRUCTORS = {
|
|
|
|
| 247 |
Axiom.QUADRATIC: _hyp_quadratic, Axiom.BILINEAR: _hyp_bilinear,
|
| 248 |
Axiom.METRIC: _hyp_metric, Axiom.SYMMETRIC: _hyp_symmetric,
|
| 249 |
Axiom.ORDERED: _hyp_ordered, Axiom.MONOTONE: _hyp_monotone,
|
| 250 |
+
Axiom.CONVEX: _hyp_convex, Axiom.CONSERVED: _hyp_conserved,
|
| 251 |
+
Axiom.MUTABLE: _hyp_mutable, Axiom.NETWORK: _hyp_network,
|
| 252 |
+
Axiom.EQUILIBRIUM: _hyp_equilibrium, Axiom.SUPERPOSITION: _hyp_superposition,
|
| 253 |
+
Axiom.LOCALITY: _hyp_locality, Axiom.EXTREMAL: _hyp_extremal,
|
| 254 |
+
Axiom.ENTROPY: _hyp_entropy, Axiom.INJECTIVE: _hyp_injective,
|
| 255 |
+
Axiom.SURJECTIVE: _hyp_surjective, Axiom.TRANSITIVE: _hyp_transitive,
|
| 256 |
+
Axiom.ATOMIC: _hyp_atomic, Axiom.IMPLICATION: _hyp_implication,
|
| 257 |
+
Axiom.NEGATION: _hyp_negation, Axiom.COMPOSITE: _hyp_composite,
|
| 258 |
+
Axiom.HOLISM: _hyp_holism, Axiom.PARSIMONY: _hyp_parsimony,
|
| 259 |
+
Axiom.DUALITY: _hyp_duality, Axiom.MONOTONE_PRODUCT: _hyp_monotone_product
|
| 260 |
}
|
| 261 |
|
| 262 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 435 |
|
| 436 |
return best_binding, best_ce, traces, best_ray_name
|
| 437 |
|
| 438 |
+
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 439 |
+
# UCB1 BANDIT SEEDER
|
| 440 |
+
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 441 |
+
class UCB1BanditSeeder:
|
| 442 |
+
def __init__(self):
|
| 443 |
+
self.stats = {a: {"tries": 0, "reward": 0.0} for a in ALL_AXIOMS}
|
| 444 |
+
self.total_tries = 0
|
| 445 |
+
|
| 446 |
+
def record_reward(self, axiom, ce_before, ce_after):
|
| 447 |
+
reward = max(0.0, ce_before - ce_after)
|
| 448 |
+
self.stats[axiom]["tries"] += 1
|
| 449 |
+
self.stats[axiom]["reward"] += reward
|
| 450 |
+
self.total_tries += 1
|
| 451 |
+
|
| 452 |
+
def intelligent_branch(self, ray, out_baton, remaining_axioms, branch_width):
|
| 453 |
+
scored = []
|
| 454 |
+
for ax in remaining_axioms:
|
| 455 |
+
tries = self.stats[ax]["tries"]
|
| 456 |
+
if tries == 0: ucb = 999.0
|
| 457 |
+
else:
|
| 458 |
+
avg_reward = self.stats[ax]["reward"] / tries
|
| 459 |
+
exploration = math.sqrt(math.log(self.total_tries + 1) / tries)
|
| 460 |
+
ucb = avg_reward + 0.5 * exploration
|
| 461 |
+
scored.append((ucb, ax))
|
| 462 |
+
scored.sort(key=lambda x: x[0] * random.random(), reverse=True)
|
| 463 |
+
children = []
|
| 464 |
+
for _, axiom in scored[:branch_width]:
|
| 465 |
+
child = ray.extend(axiom, "branch", new_prior=out_baton.ce)
|
| 466 |
+
if child:
|
| 467 |
+
child.baton = out_baton
|
| 468 |
+
children.append(child)
|
| 469 |
+
return children
|
| 470 |
+
|
| 471 |
# Re-expose batch optimization so axioms engine remains self-contained
|
| 472 |
_batched_deduce_and_evaluate = axioms._batched_deduce_and_evaluate
|
| 473 |
_mprt_sample = axioms._mprt_sample
|