"""Disconnected 2x2 cluster approximation: discard every inter-cluster interaction.
Exactly evolves retained clusters; captures local exchange but misses transport across cluster boundaries.
"""
import numpy as np
PRIORS={'family':'disconnected-2x2-clusters','parameters':{'cluster_shape':[2,2],'inter_cluster_coupling':0},'notes':'Exact diagonalization within each cluster; discard inter-cluster terms. No fitted data or offline training.'}
def simulate(instance,times):
    g=instance['geometry']; lx,ly=g['Lx'],g['Ly']; out=np.zeros((len(times),lx*ly))
    pauli={'X':np.array([[0,1],[1,0]],complex),'Y':np.array([[0,-1j],[1j,0]]),'Z':np.diag([1.,-1.]),'I':np.eye(2)}
    for x0 in range(0,lx,2):
        for y0 in range(0,ly,2):
            sites=[x*ly+y for x in range(x0,min(x0+2,lx)) for y in range(y0,min(y0+2,ly))]
            n=len(sites); h=np.zeros((2**n,2**n),complex)
            for c,ops in instance['terms']:
                if not set(map(int,ops)).issubset(sites): continue
                a=np.ones((1,1),complex)
                for s in sites: a=np.kron(a,pauli[ops.get(str(s),'I')])
                h+=c*a
            e,u=np.linalg.eigh(h); bits=[instance['initial_state']['bits'][s] for s in sites]
            v=np.zeros(2**n); v[int(''.join(map(str,bits)),2)]=1
            states=(np.exp(-1j*np.outer(times,e))*(u.conj().T@v))@u.T
            probs=np.abs(states)**2; basis=np.arange(2**n)
            for j,s in enumerate(sites): out[:,s]=probs@(1-2*((basis>>(n-1-j))&1))
    return out.tolist()
