"""Executable shared local scorer and bidding/reservation/differentiation program.
Only one cell's state/cues/neighbor delays/message are available. No host, path
matrix, optimum, external history, random handle or evaluator observation.
"""
import math
N_PARAMETERS=25
BOUNDS=(-4.0,4.0)
# Four tanh units: (four raw inputs + bias) each, four output coefficients,
# then an explicit own-write boundary prior. Output coefficients initially zero.
THETA0=(.3,-.4,.2,.5,0., -.2,.5,-.3,.4,0., .5,.2,.4,-.2,0., -.4,-.3,.5,.3,0., 0.,0.,0.,0., -.25)
def score(theta,x,d,w,q,own):
    inputs=(x/32.0,d/32.0,8.0*w,8.0*q)
    return sum(theta[20+j]*math.tanh(sum(theta[5*j+i]*inputs[i] for i in range(4))+theta[5*j+4]) for j in range(4))+theta[24]*int(own)
def update(state,boundary,adjacent,delivered,theta,analytic=False):
    kind,source,p=delivered; actions=[]; metrics=dict(adjacent)
    def send(v,k,payload): actions.append(('send',v,k,payload))
    if kind=='start':
        # Only query boundary cues supply q; w remains at its write attachment.
        state['a']=0
        a=0; q=next(c['q'][a] for c in boundary if c['kind']=='query')
        send(state['down'][str(a)],'demand',dict(a=a,q=q,D=metrics[state['down'][str(a)]]))
    elif kind=='demand':
        a=p['a']; own=next((c for c in boundary if c['kind']=='write' and c['a']==a),None)
        if own is None:
            v=state['down'][str(a)]; send(v,'demand',dict(p,D=p['D']+metrics[v]))
        else:
            # The write cell proposes at x=0 then the reduction walks upstream.
            bid=dict(p,w=own['w'],x=0,best=None,best_score=None)
            actions.append(('self','bid',bid))
    elif kind=='bid':
        a=p['a']; own=any(c['kind']=='write' and c['a']==a for c in boundary)
        forbidden=any(c['kind'] in ('query','response') or (c['kind']=='write' and c['a']!=a) for c in boundary)
        if not forbidden and state['latch'] is None:
            value=p['w']*p['x']+2*p['q']*(p['D']-p['x']) if analytic else score(theta,p['x'],p['D']-p['x'],p['w'],p['q'],own)
            actions.append(('proposal',dict(a=a,site=state['id'],score=value,x=p['x'],d=p['D']-p['x'],w=p['w'],q=p['q'],own=own)))
            if p['best'] is None or (value,state['id'])<(p['best_score'],p['best']): p=dict(p,best=state['id'],best_score=value)
        if state['parent'] is not None:
            v=state['parent']; send(v,'bid',dict(p,x=p['x']+metrics[v]))
        else:
            if p['best'] is None: raise ValueError('no local feasible bid')
            v=state['down'][str(a)]; state['routes']['Q'+str(a)]=v
            send(v,'reserve',dict(a=a,winner=p['best'],seen=False))
    elif kind=='reserve':
        a=p['a']; winner=state['id']==p['winner']; seen=p['seen']
        if winner:
            if state['latch'] is not None: raise ValueError('invalid double reservation')
            state['latch']=a; seen=True
            actions.append(('differentiate',dict(a=a,site=state['id'])))
        elif seen: state['routes']['W'+str(a)]=state['parent']
        else: state['routes']['Q'+str(a)]=state['down'][str(a)]
        own=any(c['kind']=='write' and c['a']==a for c in boundary)
        if own: send(state['parent'],'ack',dict(a=a))
        else: send(state['down'][str(a)],'reserve',dict(p,seen=seen))
    elif kind=='ack':
        if state['parent'] is not None: send(state['parent'],'ack',p)
        else:
            a=p['a']+1; q=next(c['q'] for c in boundary if c['kind']=='query')
            if a<len(q):
                v=state['down'][str(a)]; send(v,'demand',dict(a=a,q=q[a],D=metrics[v]))
    elif kind=='compile':
        root=any(c['kind']=='query' for c in boundary); response=any(c['kind']=='response' for c in boundary)
        cell=dict(role='interface' if root else 'latch' if state['latch'] is not None else 'router',address=state['latch'],response=response,routes=state['routes'])
        actions.append(('compile',cell))
    return state,actions
