app
Codex
Public Made by Adomby adom
Codex in Adom Hydrogen: ecosystem setup, dock dashboard and live engineering demos.
main
John Lauer
Corrected Astra ESC routing: native zero-open result, full accounting and voiceover handoff
a80479d
23d ago
from component_search import *
from soft_search import search_soft
import copy,sys,random
plans=json.load(open(sys.argv[1] if len(sys.argv)>1 else 'component-repaired.json'))
load(plans)
def gaps():return {p['net']:len(components(p['net']))-1 for p in plans if p['net'] not in ['GND','+3V3'] and len(components(p['net']))>1}
def pathgeo(plan,path):
old=list(m.copper);m.copper.clear();register2(plan['net'],path,plan['width']);cs=list(m.copper);m.copper[:]=old;return cs
best=sum(gaps().values());print('INITIAL',gaps(),flush=True)
for iteration in range(150):
missing=gaps()
if not missing:break
net=list(missing)[iteration%len(missing)];plan=next(p for p in plans if p['net']==net)
before=copy.deepcopy(plans);old=list(m.copper)
cs=components(net);pairs=sorted((unary_union([c['g'] for c in x]).distance(unary_union([c['g'] for c in y])),i,j) for i,x in enumerate(cs) for j,y in enumerate(cs[:i]))
# Search against pads, planes, and this net, then identify exact donor paths.
m.copper[:]=old
candidates=[]
for _,i,j in pairs:
route=search_soft(net,plan['width'],cs[i],cs[j])
if route:candidates.append(route)
if len(candidates)>=3:break
m.copper[:]=old
if not candidates:
print(iteration,'NO CANDIDATE',net,flush=True);continue
scored=[]
for route in candidates:
new=pathgeo(plan,route);donors=[]
for q in plans:
if q['net'] in [net,'GND','+3V3']:continue
for ix,path in enumerate(q['paths']):
gc=pathgeo(q,path)
if any(set(a['zs'])&set(b['zs']) and a['g'].distance(b['g'])<.205 for a in new for b in gc):donors.append((q['net'],ix))
scored.append((len(donors),route,donors))
_,route,donors=min(scored,key=lambda x:x[0]);print(iteration,'RIP',net,donors,flush=True)
for q in plans:q['paths']=[p for i,p in enumerate(q['paths']) if (q['net'],i) not in donors]
load(plans)
# Recheck the route against all remaining copper before registering it.
# Exact paths above came from the hard pad/plane mask; all conflicts removed.
register2(net,route,plan['width']);plan['paths'].append(route)
todo=list(dict.fromkeys(n for n,i in donors))
for n in todo:
q=next(p for p in plans if p['net']==n);route_components(q)
remaining=gaps();score=sum(remaining.values());print('RESULT',score,remaining,flush=True)
Path('soft-current.json').write_text(json.dumps(plans,indent=2))
if score<best:
best=score;Path('soft-best.json').write_text(json.dumps(plans,indent=2));print('BEST',best,flush=True)
if score>max(best+3,5):
plans=before;load(plans);print('REVERT regression',flush=True)