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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
from component_search import *
from soft_search2 import search_soft
import soft_search2 as soft
import ast
src=Path('repair2.py').read_text().replace('width/2-.04','width/2-.005')
exec(compile(ast.Module(body=[n for n in ast.parse(src).body if isinstance(n,ast.FunctionDef) and n.name=='search2'],type_ignores=[]),'plane-search','exec'),globals())
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)
attempts=defaultdict(int)
for iteration in range(300):
m.X0=104.0+.025*(iteration%2);m.Y0=58.0+.025*((iteration//2)%2)
missing=gaps()
if not missing:break
net=min(missing,key=lambda n:attempts[n]);attempts[net]+=1;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:
for _,i,j in pairs:
route=search_soft(net,plan['width'],cs[i],cs[j],allow_planes=True)
if route:candidates.append(route);break
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']==net: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)
plane_pads=[]
for n,i in donors:
if n in ['GND','+3V3']:
q=next(p for p in plans if p['net']==n);v=q['paths'][i][0];pt=Point((v['x'],v['y']) if isinstance(v,dict) else v);plane_pads.append(min((p for p in by[n] if p['type']!='thru_hole'),key=lambda p:p['g'].distance(pt)))
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)
plane_ok=True
for p in plane_pads:
q=next(q for q in plans if q['net']==p['net'])
stub=search2(masks(p['net'],.25),p,(p['x'],p['y']),[],plane=True)
if not stub:plane_ok=False;break
e=stub[-1];stub.append(dict(x=e[0],y=e[1],layer='In1.Cu' if p['net']=='GND' else 'In2.Cu'));register2(p['net'],stub,.25);q['paths'].append(stub)
if not plane_ok:
plans=before;load(plans);print('REVERT plane stub blocked',flush=True);continue
todo=list(dict.fromkeys(n for n,i in donors if n not in ['GND','+3V3']))
for n in todo:
q=next(p for p in plans if p['net']==n);route_components(q)
for c in pathgeo(plan,route):
for z in c['zs']:
tmp=np.zeros((H,W),dtype=np.uint16);raster(tmp,c['g'].buffer(.205),5);soft.history[z]=np.minimum(soft.history[z]+tmp,2000)
remaining=gaps();score=sum(remaining.values());print('RESULT',score,remaining,flush=True)
Path('soft3-current.json').write_text(json.dumps(plans,indent=2))
if score<best:
best=score;Path('soft3-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)