File size: 10,835 Bytes
98bde72 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | """Deterministic reference kernel for frozen computational plans.
Scientific workers, semantic evidence adjudication and chemical standardization
are external contracts. No experimental result action exists in this kernel.
"""
from __future__ import annotations
from copy import deepcopy
from dataclasses import dataclass
from typing import Callable
import math
import numpy as np
from scipy.optimize import minimize
from .schema import canonical, digest
@dataclass(frozen=True)
class Node:
id: str
tool: str
revision: str
inputs: tuple[str, ...]
outputs: tuple[str, ...]
cost: int = 1
attempts: int = 1
@dataclass(frozen=True)
class Plan:
nodes: tuple[Node, ...]
required: tuple[str, ...]
budget: int
seed: int = 2027
def validate_plan(plan: Plan, initial: dict, registry: dict) -> tuple[Node, ...]:
"""Validate unique producers, complete dependencies, DAG, revisions and cap."""
if plan.budget < 0 or not plan.required or len(set(plan.required)) != len(plan.required):
raise ValueError('invalid budget or required artifacts')
ids, produced = set(), set(initial)
for n in plan.nodes:
if not n.id or n.id in ids or n.tool not in registry:
raise ValueError('duplicate node or unknown tool')
if n.revision != registry[n.tool]['revision']:
raise ValueError('revision mismatch')
if n.cost < 1 or not 1 <= n.attempts <= 3 or not n.outputs:
raise ValueError('invalid resource contract')
if len(set(n.outputs)) != len(n.outputs) or produced.intersection(n.outputs):
raise ValueError('artifact overwrite')
produced.update(n.outputs); ids.add(n.id)
if not set(plan.required) <= produced:
raise ValueError('uncovered release obligation')
if sum(n.cost*n.attempts for n in plan.nodes) > plan.budget:
raise ValueError('worst-case budget exceeded')
ordered, pending, available = [], list(plan.nodes), set(initial)
while pending:
ready = sorted((n for n in pending if set(n.inputs) <= available), key=lambda n:n.id)
if not ready:
raise ValueError('cycle or missing input')
n = ready[0]; ordered.append(n); available.update(n.outputs); pending.remove(n)
return tuple(ordered)
def execute(plan: Plan, initial: dict, registry: dict, cache: dict | None = None) -> dict:
"""Atomic artifact commits; deterministic schedule and hash-linked records.
Registry values: revision, run(payload, seed), validate(output). Validation
must reject wrong units, chemistry, identities and out-of-domain use.
Operational timestamps belong in a separate log, outside semantic hashes.
"""
order = validate_plan(plan, initial, registry)
artifacts = deepcopy(initial); events=[]; spent=0
cache = {} if cache is None else cache
def append(payload):
event={'index':len(events),'previous':events[-1]['hash'] if events else '0'*64, **payload}
event['hash']=digest(event); events.append(event)
plan_data={'nodes':[vars(n) for n in order], 'required':plan.required,'budget':plan.budget,'seed':plan.seed}
append({'kind':'initialize','plan_hash':digest(plan_data),'initial':deepcopy(initial)})
for n in order:
if not set(n.inputs) <= set(artifacts):
append({'kind':'blocked','node':n.id,'reason':'DEPENDENCY_FAILED'});continue
payload={k:deepcopy(artifacts[k]) for k in n.inputs}
request={'node':vars(n),'inputs':payload,'seed':plan.seed}
key=digest(request)
for attempt in range(n.attempts):
spent+=n.cost
try:
if key in cache:
saved=cache[key]
if saved['hash'] != digest(saved['value']):raise ValueError('CACHE_CORRUPT')
result=deepcopy(saved['value'])
else:
result=registry[n.tool]['run'](deepcopy(payload),plan.seed)
if not isinstance(result,dict) or set(result)!=set(n.outputs):
raise ValueError('OUTPUT_CONTRACT')
canonical(result) # rejects NaN/infinity and unserializable values
registry[n.tool]['validate'](result)
cache[key]={'value':deepcopy(result),'hash':digest(result)}
artifacts.update(deepcopy(result))
append({'kind':'commit','node':n.id,'request':key,'attempt':attempt+1,'cost':n.cost,'result':deepcopy(result)})
break
except Exception as e:
append({'kind':'failure','node':n.id,'request':key,'attempt':attempt+1,'cost':n.cost,'error':type(e).__name__+': '+str(e)})
missing=sorted(set(plan.required)-set(artifacts))
append({'kind':'close','spent':spent,'missing':missing,'status':'complete' if not missing else 'incomplete'})
return {'artifacts':artifacts,'events':events,'complete':not missing,'spent':spent}
def replay(events: list[dict]) -> dict:
artifacts={};prev='0'*64
if not events or events[0].get('kind')!='initialize' or events[-1].get('kind')!='close':
raise ValueError('incomplete trace')
for i,item in enumerate(events):
e=deepcopy(item); h=e.pop('hash')
if e['index']!=i or e['previous']!=prev or digest(e)!=h:raise ValueError('trace corruption')
prev=h
if e['kind']=='initialize':artifacts=deepcopy(e['initial'])
if e['kind']=='commit':
if set(artifacts).intersection(e['result']):raise ValueError('artifact overwrite')
artifacts.update(deepcopy(e['result']))
return artifacts
def collapse_lineage(values, lineages):
"""Repeated use of an identical model output has exactly one ensemble vote."""
a=np.asarray(values,dtype=float)
if a.ndim != 2 or a.shape[1]!=len(lineages) or not np.isfinite(a).all():
raise ValueError('invalid predictions')
groups={}
for j,k in enumerate(lineages):groups.setdefault(k,[]).append(j)
cols=[]
for k in sorted(groups):
js=groups[k]
if not all(np.array_equal(a[:,js[0]],a[:,j]) for j in js):
raise ValueError('inconsistent duplicate lineage')
cols.append(a[:,js[0]])
return np.column_stack(cols), sorted(groups)
def fit_ensemble(predictions, y, lineages, ridge=0.01):
"""Nonnegative simplex stacking on a fit partition, before calibration."""
a,keys=collapse_lineage(predictions,lineages); y=np.asarray(y,float)
if len(a)==0 or y.shape!=(len(a),) or not np.isfinite(y).all() or ridge<=0:
raise ValueError('invalid fit partition')
m=a.shape[1];w0=np.full(m,1/m)
def loss(w):return np.mean((a@w-y)**2)+ridge*np.sum((w-w0)**2)
r=minimize(loss,w0,method='SLSQP',bounds=[(0,1)]*m,constraints={'type':'eq','fun':lambda w:w.sum()-1},options={'ftol':1e-12,'maxiter':1000})
if not r.success:raise ValueError(r.message)
w=np.maximum(r.x,0);w/=w.sum()
return {'lineages':keys,'weights':w.tolist(),'ridge':ridge}
def aggregate(predictions,lineages,fit):
a,keys=collapse_lineage(predictions,lineages)
if keys!=fit['lineages']:raise ValueError('ensemble membership changed')
w=np.asarray(fit['weights']);mean=a@w
return mean,np.sqrt(np.sum(w*(a-mean[:,None])**2,axis=1))
def release(candidates: list[dict], obligations: list[dict], k=12) -> dict:
"""Complete computational records with typed prediction/proxy support.
Required per score: value, lower, upper, unit, support, lineage, domain_ok.
Proxy bounds are ensemble extrema; calibrated bounds are statistical.
Caller provides standardized chemistry identities after scientific preflight.
"""
from .metrics import diverse_select
if not obligations or k<0 or len({o['id'] for o in obligations})!=len(obligations):
raise ValueError('invalid obligations')
records=[]; seen=set()
for c in sorted(deepcopy(candidates),key=lambda x:x['id']):
if c['id'] in seen:raise ValueError('duplicate chemical identity')
seen.add(c['id']);errors=[];margins=[]
if not c.get('chemistry_verified'):errors.append('CHEMISTRY_UNVERIFIED')
for o in obligations:
s=c.get('scores',{}).get(o['id'])
if s is None:errors.append(o['id']+':MISSING');continue
try:
vals=[s[x] for x in ['value','lower','upper']]
if not all(isinstance(v,(int,float)) and math.isfinite(v) for v in vals):raise ValueError()
if not s['lower']<=s['value']<=s['upper']:raise ValueError()
if s['unit']!=o['unit'] or s['support']!=o['support'] or not s['lineage'] or not s['domain_ok']:raise ValueError()
if o['scale']<=0 or o['direction'] not in ['ge','le']:raise ValueError()
v=s['lower'] if o['direction']=='ge' else s['upper']
margin=(v-o['threshold'])/o['scale']*(1 if o['direction']=='ge' else -1)
margins.append(margin)
if margin<0:errors.append(o['id']+':THRESHOLD')
except (KeyError,TypeError,ValueError):errors.append(o['id']+':INVALID')
c.update(errors=errors,eligible=not errors,worst_margin=min(margins) if margins else None)
records.append(c)
scores={c['id']:c['worst_margin'] for c in records if c['eligible']}
sequences={c['id']:c.get('monomers',c['sequence']) for c in records}
chosen=diverse_select(sequences,scores,k)
return {'records':records,'selected':chosen,'unfilled':k-len(chosen),'obligations_hash':digest(obligations)}
def robust_reward(margins, weights):
"""Rows=endpoints, columns=required contexts; manuscript Eq. robustgen."""
m=np.asarray(margins,float);w=np.asarray(weights,float)
if m.ndim!=2 or not m.shape[1] or w.shape!=(m.shape[0],) or not np.isfinite(m).all() or not np.isfinite(w).all() or (w<0).any() or not np.isclose(w.sum(),1):
raise ValueError('invalid margins or weights')
u=m.min(axis=1)
return float(-np.max(w*np.maximum(0,-u))+.05*np.sum(w*np.tanh(u)))
def redesign_schedule(failures: dict[str,int], slots: int) -> list[str]:
"""Smoothed failure-proportional quotas, largest remainder, stable scheduling."""
if slots<0 or not failures or any(not isinstance(v,int) or v<0 for v in failures.values()):
raise ValueError('invalid failure counts')
order=sorted(failures,key=lambda k:(-failures[k],k))
denominator=sum(failures.values())+len(failures)
exact={k:slots*(failures[k]+1)/denominator for k in order}
quota={k:math.floor(v) for k,v in exact.items()}
residual=slots-sum(quota.values())
for k in sorted(order,key=lambda k:(-(exact[k]-quota[k]),k))[:residual]:quota[k]+=1
schedule=[]
while len(schedule)<slots:
for k in order:
if quota[k]>0:schedule.append(k);quota[k]-=1
return schedule
|