def build_tree(b, perms : Iterable [Permutation]): root = Node(None, Permutation([]), b) node_dict = {b : root} if (len(perms) == 0): return Tree(root, set([b]), node_dict, perms) q = [(b, root)] orbit = set([b]) cur_node = root while (len(q) > 0): cur_elem, cur_node = q.pop(0) for p in perms: next_elem = apply(p, [cur_elem])[0] while next_elem not in orbit: node = Node(cur_node, inverse(p), next_elem) cur_node.children.append(node) node_dict[next_elem] = node q.append((next_elem, node)) orbit.add(next_elem) next_elem = apply(p, [cur_elem])[0] return Tree(root, orbit, node_dict, perms)
def check_belongs(chain: FullStabilizerChain, val: Permutation, step=0): if (step == len(chain.trees)): return (val == Permutation([]), []) b = chain.base[step] u = apply(val, [b])[0] if u not in chain.trees[step].orbit: return (False, []) node = chain.trees[step].node_dict[u] new_val = val cert = [] while u != b: new_val = mult([node.perm, new_val]) u = apply(node.perm, [u])[0] cert.append(inverse(node.perm)) node = node.parent res = check_belongs(chain, new_val, step + 1) cert.extend(res[1]) return (res[0], cert)
def test_apply(): p = Permutation([Cycle([1,2,3])]) print(apply(p, [1])) print(apply(p, [2])) print(apply(p, [3])) print(apply(p, [1, 2])) print(apply(p, [1, 2, 4, 3])) print(apply(p, [1, 2, 3])) print(apply(p, [4])) print(apply(p, [4,5])) print(apply(p, [4,5,6, 1]))
def make_gens(tree: Tree, S: Iterable[Permutation]): newS = set() for s in S: for u in tree.orbit: hu = tree.get_h_u(u) hsu = tree.get_h_u(apply(s, [u])[0]) newp = mult([inverse(hsu), s, hu]) if newp not in newS: newS.add(newp) # print(len(newS)) return newS
def build_tree_for_multi(b, perms : Iterable[Permutation]): root = b hash_orbit = set([hash(b)]) orbit = [b] if (len(perms) == 0): return orbit q = [b] cur_node = root while (len(q) > 0): cur_elem = q.pop(0) for p in perms: next_elem = apply(p, cur_elem) while hash(tuple(next_elem)) not in hash_orbit: q.append(next_elem) orbit.append(tuple(next_elem)) hash_orbit.add(hash(tuple(next_elem))) next_elem = apply(p, cur_elem) return orbit
def normalize(S: Iterable[Permutation]): newS = set() n = max(S, key=lambda x: x.n).n base = [{} for _ in range(n)] for s in S: for x in range(1, n + 1): u = apply(s, [x])[0] if u != x: if u in base[x - 1]: s = mult([inverse(s), base[x - 1][u]]) else: base[x - 1][u] = s if s not in newS: newS.add(s) break # print(len(newS)) return newS