Exemple #1
0
def build_gates(ring, i4, root2, i8):
    qubit = Space(2, ring)
    hom = Hom(qubit, qubit)

    I = Map.from_array([[1, 0], [0, 1]], hom)
    X = Map.from_array([[0, 1], [1, 0]], hom)
    Z = Map.from_array([[1, 0], [0, -1]], hom)
    H = (1/root2)*(X+Z)

    assert H*H == I

    S = Map.from_array([[1, 0], [0, i4]], hom)
    assert S*S == Z

    T = Map.from_array([[1, 0], [0, i8]], hom)
    assert S*S == Z

    #gen = [X, Z, S] # generates 32 elements
    gen = [X, Z, S, H] # generates 192 elements
    #gen = [X, Z, S, H, T]

    if argv.gap:
        print("G := Group(")
        ms = []
        for g in gen:
            m = gapstr(g)
            ms.append(m)
        print(",\n".join(ms)+");;")

    if ring.p <= 41:
        G = mulclose(gen)
        print("|G| =", len(G))
Exemple #2
0
def tensor_rep(G, space):
    "build rep of permutation action of G on tensor power of space"

    gen = G.items
    n = len(gen)
    d = len(space)
    ring = space.ring

    # tensor power of the space
    tensor = lambda x, y: x @ y
    tspace = reduce(tensor, [space] * n)

    # build action on the tensor power
    thom = Hom(tspace, tspace)
    send_perms = {}
    for g in G:
        #print(g)
        items = []
        for idxs in tspace.gen:
            jdxs = tuple(idxs[g[i]] for i in range(len(idxs)))
            items.append(((idxs, jdxs), ring.one))
            #print(idxs, "->", jdxs)
        #print()
        swap = Map(items, thom)
        send_perms[g] = swap

    tp = Cat(G, ring)
    rep = Rep(send_perms, tspace, tp)
    return rep
Exemple #3
0
def main():

    #U = numpy.array([[0, 1], [-1, -1]])

    V = Space(2, Z)
    hom = Hom(V, V)
    U = Map.from_array([[0, 1], [-1, -1]], hom)

    A = Map.from_array([[1, 0], [0, 1]], hom)

    A0 = A
    for i in range(2):
        print(A)
        A = U * A * U.transpose()
        A0 = A0 + A
    print(A)
    print("sum:")
    print(A0)
Exemple #4
0
def find_span(vs):
    rows = []
    for v in vs:
        v = v.transpose()
        row = v.to_array()
        assert row.shape[0] == 1
        rows.append(row[0])
    ring = v.ring
    src = v.src
    hom = Hom(src, Space(len(vs), ring))
    A = Map.from_array(rows, hom)
    A = A.transpose()
    A = A.image()
    return A
Exemple #5
0
    def perm_rep(cls, tp):
        G = tp.G
        ring = tp.ring
        one = ring.one
        basis = G.items
        V = Space(basis, ring)

        send_perms = {}
        hom = Hom(V, V)
        for g in G:
            rg = Map([((g[i], i), one) for i in basis], hom)
            send_perms[g] = rg
        rep = cls(send_perms, V, tp)
        return rep
Exemple #6
0
def specht(n, space):

    assert n >= 2
    d = len(space)
    ring = space.ring

    items = list(range(n))
    gen1 = []
    for i in range(n - 1):
        perm = dict((item, item) for item in items)
        perm[items[i]] = items[i + 1]
        perm[items[i + 1]] = items[i]
        perm = Perm(perm, items)
        gen1.append(perm)
    perms = mulclose(gen1)
    G = Group(perms, items)

    #I = space.ident

    # tensor power of the space
    tensor = lambda x, y: x @ y
    tspace = reduce(tensor, [space] * n)

    # build action of symmetric group on the tensor power
    thom = Hom(tspace, tspace)
    gen2 = []
    for g in gen1:
        items = []
        for idxs in tspace.gen:
            jdxs = tuple(idxs[g[i]] for i in range(len(idxs)))
            items.append(((idxs, jdxs), ring.one))
            #print(idxs, "->", jdxs)
        #print()
        swap = Map(items, thom)
        gen2.append(swap)

    action = mulclose_hom(gen1, gen2)
    for g in G:
        for h in G:
            assert action[g *
                          h] == action[g] * action[h]  # check it's a group hom

    tp = Cat(G, ring)

    rep = Rep(action, tspace, tp)
    return rep
Exemple #7
0
    def mk_rep(cls, act, tp):
        G = tp.G
        ring = tp.ring
        one = ring.one
        gen = act.items
        V = Space(gen, ring)

        send_perms = {}
        hom = Hom(V, V)
        for g in G:
            ag = act[g]
            rg = Map([((ag[i], i), one) for i in gen], hom)
            #print(g, "--->")
            #print(rg)
            send_perms[g] = rg
        rep = cls(send_perms, V, tp)
        rep.check()
        return rep
Exemple #8
0
def test():

    ring = element.Q

    n = argv.get("n", 3)
    d = argv.get("d", 2)

    G = Group.symmetric(n)

    algebra = GroupAlgebra(G, ring)
    v = algebra.zero
    for g in G:
        v = v + g
    assert 2 * v == v + v
    assert v - v == algebra.zero

    for g in algebra.basis:
        assert g * v == v
        assert v * g == v

    center = algebra.get_center()
    for v in center:
        for g in algebra.basis:
            assert g * v == v * g

    # ---------------------------------------

    # build standard representation of symmetric group

    act = G.left_action(list(range(n)))
    #print(act)

    tp = Cat(G, ring)
    rep = Rep.mk_rep(act, tp)
    #rep.dump()

    module = algebra.extend(rep)
    #print(module.action(v))

    # ---------------------------------------

    # build representation of symmetric group on tensor product

    space = Space(d, ring)
    rep = tensor_rep(G, space)
    #rep.check()

    module = algebra.extend(rep)
    #print(module.action(v))

    # ---------------------------------------

    # Build the young symmetrizers
    projs = []
    part = argv.get("part")
    parts = [part] if part else partitions(n)
    for part in parts:

        items = G.items
        A = algebra.zero
        for g in G:
            labels = [g[item] for item in items]
            tableau = Young(G, part, labels)
            P = algebra.get_symmetrizer(tableau)
            A = A + P

        #tableau = Young(G, part)
        #A = algebra.get_symmetrizer(tableau)

        print("partition:", part)
        #print("H:")
        #print(module.action(H))
        #print("V:")
        #print(module.action(V))

        print([g * A == A * g for g in algebra.basis])

        specht = []
        for v in algebra.basis:
            u = v * A
            specht.append(u.to_array())
        hom = Space(len(G), ring).endo_hom()
        specht = Map.from_array(specht, hom)
        specht = specht.image()
        #print(specht)
        dim = specht.shape[1]
        print("S(n)-algebra dim:", dim)

        if len(part) > d:
            continue

        print("A:", A)
        P = module.action(A)
        #P = P.transpose()
        P = P.image()
        print(P.longstr())

        print(P.shape)
        return
        print("multiplicity:", P.shape[1])

        src = P.src
        for v in src.get_basis():
            u = P * v
            #print(u.longstr())
            items = []
            for g in algebra.basis:
                g = module.action(g)
                w = g * u
                #print(w.longstr())
                items.append(w)
            A = find_span(items)
            print("dimension:", A.shape[1])
Exemple #9
0
def burnside(tp):  # make it a method

    ring = tp.ring
    G = tp.G
    Hs = conjugacy_subgroups(G)
    names = {}

    letters = list(string.ascii_uppercase + string.ascii_lowercase)
    letters.remove("O")
    letters.remove("o")
    letters = letters + [l + "'"
                         for l in letters] + [l + "''" for l in letters]
    assert len(letters) >= len(Hs)
    letters = letters[:len(Hs)]

    for i, H in enumerate(Hs):
        names[H] = "%s_0" % letters[i]  # identity coset

    acts = {}
    for i, H in enumerate(Hs):
        cosets = G.left_cosets(H)
        assert len(G) == len(cosets) * len(H)

        items = [names[H]]
        letter = letters[i]
        assert H in cosets
        idx = 1
        for gH in cosets:
            if gH == H:
                continue
            name = "%s_%d" % (letter, idx)
            names[gH] = name
            items.append(name)
            idx += 1

        act = G.left_action(cosets)
        assert act.src is G
        act = act.rename(names, items)
        act.name = letter
        H.name = act.name
        acts[letter] = act
        assert len(act.components()) == 1  # transitive
        #print act.tgt.perms
        print(
            "%s subgroup order = %d, number of cosets = %d, conjugates = %d" %
            (act.name, len(H), len(cosets), len(H.conjugates)))

    #print(list(names.values()))

    reps = {}
    for act in acts.values():
        rep = Rep.mk_rep(act, tp)
        reps[act.name] = rep

    arg = argv.next() or "B*C"
    assert "*" in arg
    left, right = arg.split("*")

    act0 = acts[left]
    act1 = acts[right]

    rep0 = reps[left]
    rep1 = reps[right]

    act2 = act0.pushout(act1)
    rep = Rep.mk_rep(act2, tp)

    U0 = Space(act0.items, ring)
    U1 = Space(act1.items, ring)
    UU = U0 @ U1
    print(UU)

    one = ring.one
    hom = Hom(U0, U1)
    for act in act2.components():

        items = [((y, x), one) for (x, y) in act.items]
        f = Map(items, hom)
        print(f)

        assert tp.is_hom(rep0, rep1, f)

        print("kernel:")
        g = f.kernel()
        print(g)
        print()

        print("cokernel:")
        g = f.cokernel()
        print(g)
        print()
Exemple #10
0
    def __init__(self, n, space):
        assert n >= 2
        d = len(space)
        ring = space.ring

        items = list(range(n))
        gen1 = []
        for i in range(n - 1):
            perm = dict((item, item) for item in items)
            perm[items[i]] = items[i + 1]
            perm[items[i + 1]] = items[i]
            perm = Perm(perm, items)
            gen1.append(perm)

        perms = mulclose(gen1)
        G = Group(perms, items)

        #I = space.ident

        # tensor power of the space
        tensor = lambda x, y: x @ y
        tspace = reduce(tensor, [space] * n)

        # build action of symmetric group on the tensor power
        thom = Hom(tspace, tspace)
        gen2 = []
        for g in gen1:
            items = []
            for idxs in tspace.gen:
                jdxs = tuple(idxs[g[i]] for i in range(len(idxs)))
                items.append(((idxs, jdxs), ring.one))
                #print(idxs, "->", jdxs)
            #print()
            swap = Map(items, thom)
            gen2.append(swap)

        action = mulclose_hom(gen1, gen2)
        for g in G:
            for h in G:
                assert action[
                    g * h] == action[g] * action[h]  # check it's a group hom

        # Build the young symmetrizers
        projs = []
        parts = []
        for part in partitions(n):
            if len(part) > d:
                continue
            parts.append(part)
            t = Young(G, part)

            rowG = t.get_rowperms()
            colG = t.get_colperms()
            horiz = None
            for g in rowG:
                P = action[g]
                horiz = P if horiz is None else (horiz + P)

            vert = None
            for g in colG:
                P = action[g]
                s = g.sign()
                P = s * P
                vert = P if vert is None else (vert + P)
            A = vert * horiz + horiz * vert
            #A = horiz * vert

            assert vert * vert == len(colG) * vert
            assert horiz * horiz == len(rowG) * horiz
            #A = A.transpose()
            projs.append(A)

            #print(part)
            #print(t)
            #print(A)

        self.projs = projs
        self.parts = parts
Exemple #11
0
def main():

    d = argv.get("d", 3)
    assert d>=2

    double = argv.double

    if d==2:
        ring = CyclotomicRing(4)
        #ring = element.Z
        gamma = ring.x
        w = gamma**2
        assert w == -1
        double = True

    else:
        ring = CyclotomicRing(d**2)
        gamma = ring.x
        w = gamma**d

    I = numpy.zeros((d, d), dtype=object)
    wI = numpy.zeros((d, d), dtype=object)
    X = numpy.zeros((d, d), dtype=object)
    Z = numpy.zeros((d, d), dtype=object)
    Zdag = numpy.zeros((d, d), dtype=object)
    S = numpy.zeros((d, d), dtype=object)
    Sdag = numpy.zeros((d, d), dtype=object)
    T = numpy.zeros((d, d), dtype=object)
    Tdag = numpy.zeros((d, d), dtype=object)
    for j in range(d):
        I[j, j] = 1
        wI[j, j] = w
        X[j, (j+1)%d] = 1
        Z[j, j] = w**j
        Zdag[j, j] = w**(d-j)

        if d==2:
            val = gamma**(j**2)
            ival = gamma**(d**2 - (j**2)%(d**2))
        else:
            val = w**(j**2)
            ival = w**(d - (j**2)%d)
        assert val*ival == 1

        S[j, j] = val
        Sdag[j, j] = ival

        if d in [2, 3, 6]:
            val = gamma**(j**3)
            ival = gamma**(d**2 - (j**3)%(d**2))
        else:
            val = w**(j**3)
            ival = w**(d - (j**3)%d)
        assert val*ival == 1

        T[j, j] = val
        Tdag[j, j] = ival

    qu = Space(d, ring)
    hom = Hom(qu, qu)

    I = Map.from_array(I, hom)
    wI = Map.from_array(wI, hom)
    Xdag = Map.from_array(X.transpose(), hom)
    X = Xs = Map.from_array(X, hom)
    Z = Map.from_array(Z, hom)
    Zdag = Map.from_array(Zdag, hom)
    S = Map.from_array(S, hom)
    Sdag = Map.from_array(Sdag, hom)
    T = Map.from_array(T, hom)
    Tdag = Map.from_array(Tdag, hom)

    if d==2:
        Y = gamma*X*Z # ?
    else:
        Y = w*X*Z # ?

    assert S*Sdag == I

    assert Z*Zdag == I
    assert X*Xdag == I

    if d>2:
        for j in range(1, d+1):
            assert (j==d) == (X**j==I)
            assert (j==d) == (Z**j==I)
    else:
        assert X != I
        assert Z != I
        assert X*X == I
        assert Z*Z == I

    assert Z*X == (w**(d-1))*X*Z

    if double:
        pauli = mulclose([X, Z, gamma*I])
        names = mulclose_names([X, Z, gamma*I], "X Z i".split())

    else:
        pauli = mulclose([X, Z])
        names = mulclose_names([X, Z, Xdag, Zdag, -I], "X Z Xi Zi -I".split())

    pauli = set(pauli)
    print("pauli:", len(pauli))
    assert Zdag in pauli
    assert Xdag in pauli

    if d<6:
        # slow..
        lhs = atpow(X, d)
        rhs = atpow(Z, d)
        assert lhs * rhs == rhs * lhs
    
    lhs = X@X
    rhs = Z@Zdag
    assert lhs * rhs == rhs * lhs

    lhs = X@(X**(d-1))
    rhs = Z@Z
    assert lhs * rhs == rhs * lhs

    if 0:
        n = 5
        ops = [X, Xdag]
        lhs = []
        for op in cross([ops]*n):
            op = reduce(matmul, op)
            lhs.append(op) 
    
        ops = [Z, Zdag]
        rhs = []
        for op in cross([ops]*n):
            op = reduce(matmul, op)
            rhs.append(op) 
    
        for l in lhs:
          for r in rhs:
            if l*r == r*l:
                print("/", end=" ", flush=True)
            else:
                print(".", end=" ", flush=True)
        print()

    print("S =")
    print(S)
    print("XSX =")
    print(X*S*X)
    print("XSXS =")
    print(X*S*X*S)
    
    #print("Y =")
    #print(Y)
    #print("S*X*Sdag =")
    #print(S*X*Sdag)
    assert Y == S*X*Sdag

    def get_orbit(g, gi, v):
        orbit = [v]
        while 1:
            u = g*orbit[-1]*gi
            if u == orbit[0]:
                break
            orbit.append(u)
        return orbit

    print("S orbit:")
    for A in [X, Z]:
        print('\t', [''.join(names[op]) for op in get_orbit(S, Sdag, A)])

    U = X*S
    Ui = Sdag * Xdag
    assert U*Ui == I

    print("XS orbit:")
    for A in [X, Z]:
        print('\t', [''.join(names[op]) for op in get_orbit(U, Ui, A)])

    U = X*X*S
    Ui = Sdag * Xdag * Xdag
    assert U*Ui == I

    print("XXS orbit:")
    for A in [X, Z]:
        print('\t', [''.join(names[op]) for op in get_orbit(U, Ui, A)])

    return

    inverse = {}
    for g in pauli:
      for h in pauli:
        if g*h == I:
            inverse[g] = h
            inverse[h] = g

    def is_cliff(A, Ai):
        assert A*Ai == I
        for g in pauli:
            h = A*g*Ai
            if h not in pauli:
                return False
        return True
    print("S =")
    print(S)
    print("S**2 =")
    print(S**2)
    print("Sdag =")
    print(Sdag)
    assert is_cliff(S, Sdag)

    #print("is_cliff:", (S in pauli), is_cliff(S, Sdag))

    def is_third_level(A, Ai):
        assert A*Ai == I
        for g in pauli:
            gi = inverse[g]
            h = A*g*Ai*gi
            hi = g*A*gi*Ai
            if not is_cliff(h, hi):
                return False
        return True

    print("is_pauli(S)", S in pauli)
    print("is_cliff(S)", is_cliff(S, Sdag))
    #print("is_third_level(S)", is_third_level(S, Tdag))

    print("is_pauli(T)", T in pauli)
    print("is_cliff(T)", is_cliff(T, Tdag))
    print("is_third_level(T)", is_third_level(T, Tdag))
        

    print("OK")
Exemple #12
0
 def getdag(A):
     items = [((j, i), dag[v]) for ((i, j), v) in A.items]
     return Map(items, hom)
Exemple #13
0
def clifford():

    p = argv.get("p", 17)
    
    field = FiniteField(p)
    #ring = PolynomialRing(field)
    #x = ring.x

    for fgen in range(1, p):
        items = set()
        j = fgen
        while j not in items:
            items.add(j)
            j = (j*fgen)%p
        if len(items) == p-1:
            break
    else:
        assert 0
    finv = {}
    for i in range(1, p):
      for j in range(1, p):
        if (i*j)%p == 1:
          finv[i] = j
          finv[j] = i
    assert len(finv) == p-1

    #print("fgen:", fgen)

    items = [field.promote(i) for i in range(p)]
    has_imag = [i for i in items if i*i == -1]
    
    #print(p, has_imag)
    if not has_imag:
        assert 0

    i4 = has_imag[0]
    assert -i4 == has_imag[1]

    has_root2 = [i for i in items if i*i == 2]
    if not has_root2:
        assert 0
    r2 = has_root2[0]
    assert -r2 == has_root2[1]

    has_i8 = [i for i in items if i*i == i4]
    if not has_i8:
        assert 0
    i8 = has_i8[0]
    assert -i8 == has_i8[1]

    print("p =", p)
    #print(i4, r2, i8)
    #print(has_imag, has_root2, has_i8)
    for i in items:
        if i*i8 == 1:
            i8_dag = i
    #print(i8_dag)

    # try to take a daggar... doesn't really work tho.
    assert p==17
    dag = {
        0:0, 1:1, 2:9, 3:3, 4:13, 5:12, 6:6, 7:7, 8:15,
        9:2, 10:10, 11:11, 12:5, 13:4, 14:14, 15:8, 16:16,  
    }
    for (k, v) in list(dag.items()):
        dag[k] = field.promote(v)
        dag[field.promote(k)] = field.promote(v)

    assert dag[i4] == -i4

    qubit = Space(2, field)
    hom = Hom(qubit, qubit)

    def getdag(A):
        items = [((j, i), dag[v]) for ((i, j), v) in A.items]
        return Map(items, hom)

    I = Map.from_array([[1, 0], [0, 1]], hom)
    X = Map.from_array([[0, 1], [1, 0]], hom)
    Z = Map.from_array([[1, 0], [0, -1]], hom)
    H = (1/r2)*(X+Z)

    assert H*H == I

    S = Map.from_array([[1, 0], [0, i4]], hom)
    Sdag = Map.from_array([[1, 0], [0, dag[i4]]], hom)
    assert S*S == Z
    assert S*Sdag == I
    assert getdag(S) == Sdag

    T = Map.from_array([[1, 0], [0, i8]], hom)
    assert S*S == Z

    C1 = mulclose([X, Z])
    assert len(C1) == 8

    # C1 is Pauli group + phases
    #P = fgen*I # phase
    P = i4*I
    C1 = mulclose([X, Z, P])  # add phases
#    assert len(C1) == 64, len(C1)
    assert len(C1) == 32, len(C1)
    C1_lookup = set(C1)

    #gen = [X, Z, S, H]
    #C2 = mulclose(gen)
    #assert len(C2) == 192

    G = []
    for a in range(p):
     for b in range(p):
      for c in range(p):
       for d in range(p):
        if (a*d - b*c)%p:
            G.append(Map.from_array([[a, b], [c, d]], hom))
    G_lookup = set(G)
    print("|GL(%d, 2)|=%d" % (p, len(G)))

    U = []
    for g in G:
        if g*getdag(g) == I:
            U.append(g)
    print("|U|=", len(U))

    gen = [X, Z, S, H, P]

    # Clifford group + phases
    C2 = mulclose(gen)
#    assert len(C2) == 384, len(C2)
    assert len(C2) == 192, len(C2)
    C2_lookup = set(C2)
    print("|C2| =", len(C2))

    print(C2_lookup == set(U))

    for g in C2:
        assert g in G_lookup
        #assert g*getdag(g) == I, str(g) # FAIL

#    inv = {I:I}
#    for a in G:
#      if a in inv:
#        continue
#      for b in G:
#        ab = a*b
#        ci = inv.get(ab)
#        if ci is None:
#            continue
#        inv[a] = b*ci
#        inv[b] = ci*a
#      print(len(inv), end=" ", flush=True)
#    print()

    inv = {I:I}
    remain = set(G)
    remain.remove(I)
    while remain:
        a = iter(remain).__next__()
        assert a not in inv
        for b in G:
            ab = a*b
            ci = inv.get(ab)
            if ci is None:
                continue
            if a not in inv:
                inv[a] = b*ci
                remain.remove(a)
            if b not in inv:
                inv[b] = ci*a
                remain.remove(b)
        print(len(inv), end=" ", flush=True)
    print()

    assert len(inv) == len(G)

    if 0:
        for g2 in C2:
            for g in C1:
                assert g2 * g * inv[g2] in C1
    
        C2 = []
        for g2 in G:
            for g in C1:
                if g2*g*inv[g2] not in C1_lookup:
                    break
            else:
                C2.append(g2)
        assert len(C2) == 384 # same as above
        C2_lookup = set(C2)

    C3 = []
    for g3 in G:
        for g in C1:
            if g3*g*inv[g3] not in C2_lookup:
                break
        else:
            C3.append(g3)
    print("|C3| =", len(C3))
    C3_lookup = set(C3)

    shuffle(C3)

#    count = 0
#    for a in C3:
#      for b in C3:
#        if a*b in C3_lookup:
#            count += 1
#    print(count)

    def src(a):
        return set([b for b in C3 if a*b in C3_lookup])

    def tgt(a):
        return set([b for b in C3 if b*a in C3_lookup])

    if 0:
        items = iter(C3)
        a = items.__next__()
    
        src_a = src(a)
        print("|src_a| =", len(src_a))

    srcs = []
    for b in C3:
        src_b = src(b)
        if src_b not in srcs:
            print("|src_b| = ", len(src_b))
            srcs.append(src_b)
        if len(srcs)==4: # there is only 4 of these to be found
            break

    obs = list(srcs)
    tgts = []
    for b in C3:
        tgt_b = tgt(b)
        if tgt_b not in obs:
            obs.append(tgt_b)
        if tgt_b not in tgts:
            print("|tgt_b| = ", len(tgt_b))
            tgts.append(tgt_b)
        if len(tgts)==4: # there is only 4 of these to be found
            break

    done = False
    while not done:
        done = True
        #print("obs:", len(obs))
    
        obs.sort(key = len, reverse=True)
        obs1 = list(obs)
        for s in obs:
          for t in obs:
            st = s.intersection(t)
            a = ' '
            if st not in obs1:
                a = '*'
                obs1.append(st)
                done = False
            #print("%4d"%(len(st)), end=a)
          #print()
        obs = obs1
        obs.sort(key = len, reverse=True)

    print("obs:", len(obs), [len(ob) for ob in obs])
    for ob in obs:
        #print(len(ob), end=" ")
        iob = [inv[a] for a in ob if inv[a] in ob]
        print((len(ob), len(iob)), end=" ")
            
    print()
Exemple #14
0
def main():

    Z = element.Z
    ring = element.CyclotomicRing(8)
    x = ring.x
    r2 = x + x**7
    assert r2**2 == 2

    qubit = Space(2, ring)

    q2 = qubit @ qubit

    hom = Hom(qubit, qubit)

    I = Map.from_array([[1, 0], [0, 1]], hom)
    X = Map.from_array([[0, 1], [1, 0]], hom)
    Z = Map.from_array([[1, 0], [0, -1]], hom)
    Y = Map.from_array([[0, x**6], [x**2, 0]], hom)
    assert Y * Y == I
    assert Y == (x**2) * X * Z

    II = I @ I
    XI = X @ I
    IX = I @ X
    XX = X @ X
    ZI = Z @ I
    IZ = I @ Z

    assert XI * IX == XX
    T = Map.from_array([[1, 0], [0, x]], hom)
    Td = Map.from_array([[1, 0], [0, x**7]], hom)
    S = T * T
    Sd = Td * Td
    assert Z == S * S
    assert T * Td == I
    assert S * Sd == I
    assert S * Z == Z * S
    assert T * Z == Z * T

    assert (Z * X * Z) == -X
    assert ((Z @ Z) * (X @ X) * (Z @ Z)) == X @ X
    assert ((S @ S) * (X @ X) * (Sd @ Sd)) == atpow((S * X * Sd), 2)

    SXSd = S * X * Sd
    TXTd = T * X * Td
    lhs = r2 * TXTd
    i = x**2
    assert (lhs == X + i * X * Z)

    if 0:
        names = mulclose_names([X, Z, x * I], "X Z xI".split())
        #print("SXSd:", "*".join(names[SXSd]))

        names = mulclose_names([XI, IX, ZI, IZ], "XI IX ZI IZ".split())
        g = atpow(SXSd, 2)
        #print("*".join(names[g]))

        gen = [
            X @ I @ I @ I, I @ X @ I @ I, I @ I @ X @ I, I @ I @ I @ X,
            Z @ I @ I @ I, I @ Z @ I @ I, I @ I @ Z @ I, I @ I @ I @ Z,
            x * (I @ I @ I @ I)
        ]
        names = "XIII IXII IIXI IIIX ZIII IZII IIZI IIIZ wIIII".split()
        names = mulclose_names(gen, names)
        g = atpow(SXSd, 4)
        #print("*".join(names[g]))
        g = atpow(TXTd, 4)
        assert g not in names

    I8, X8, Z8 = atpow(I, 8), atpow(X, 8), atpow(Z, 8)
    T8 = atpow(T, 8)
    #print(T8.str(hide_zero=True, sep=""))
    Td8 = atpow(Td, 8)
    G = mulclose([X8, Z8])
    P = I8 + X8 + Z8 + X8 * Z8
    assert P * P == 4 * P
    lhs = P
    rhs = T8 * P * Td8
    assert (rhs * rhs == 4 * rhs)

    #T1 = reduce(matmul, [T, Td]*4)
    #T2 = reduce(matmul, [Td, T]*4)
    #print(T1*P*T2)
    #return

    Q = P @ P

    RM14 = """
    1111111111111111
    .1.1.1.1.1.1.1.1
    ..11..11..11..11
    ....1111....1111
    ........11111111
    """.strip().split()
    RM14.pop(0)

    def interp(row, op):
        ops = [op if s == "1" else I for s in row]
        A = reduce(matmul, ops)
        return A

    RM14 = [row[1:] for row in RM14]  # puncture
    n = len(RM14[0])
    Sx = [interp(row, X) for row in RM14]
    Sz = [interp(row, Z) for row in RM14]

    if 0:
        print("mulclose...")
        G = mulclose(Sx + Sz, maxsize=2**len(Sx + Sz))  # too slow :-(
        print(len(G))
        P = reduce(add, G)
        assert P * P == len(G) * P

        Tn = atpow(T, n)
        Tdn = atpow(Td, n)
        print(P == Tn * P * Tdn)

    #print(lhs.str(hide_zero=True, sep=""))
    #print()
    #print()
    #print()
    #print(rhs.str(hide_zero=True, sep=""))

    gen = [
        X @ I @ I @ I @ I @ I @ I @ I, I @ X @ I @ I @ I @ I @ I @ I,
        I @ I @ X @ I @ I @ I @ I @ I, I @ I @ I @ X @ I @ I @ I @ I,
        I @ I @ I @ I @ X @ I @ I @ I, I @ I @ I @ I @ I @ X @ I @ I,
        I @ I @ I @ I @ I @ I @ X @ I, I @ I @ I @ I @ I @ I @ I @ X,
        Z @ I @ I @ I @ I @ I @ I @ I, I @ Z @ I @ I @ I @ I @ I @ I,
        I @ I @ Z @ I @ I @ I @ I @ I, I @ I @ I @ Z @ I @ I @ I @ I,
        I @ I @ I @ I @ Z @ I @ I @ I, I @ I @ I @ I @ I @ Z @ I @ I,
        I @ I @ I @ I @ I @ I @ Z @ I, I @ I @ I @ I @ I @ I @ I @ Z,
        x * (I @ I @ I @ I @ I @ I @ I @ I)
    ]
    names = """
        XIIIIIII IXIIIIII IIXIIIII IIIXIIII IIIIXIII IIIIIXII IIIIIIXI IIIIIIIX 
        ZIIIIIII IZIIIIII IIZIIIII IIIZIIII IIIIZIII IIIIIZII IIIIIIZI IIIIIIIZ 
        wIIIIIIII
    """.strip().split()
    gen.pop(-1)
    names.pop(-1)

    if 0:
        g = atpow(TXTd, 8)
        for i in range(8):
            print(g == (x**i) * atpow(X * Z, 8))
        return

    if 0:
        names = mulclose_names(gen, names)
        g = atpow(TXTd, 8)
        for i in range(8):
            print(names.get((x**i) * g, "?"))

    #for i in [1, 2, 4]:
    #    print(atpow(TXTd, i))

    if 0:
        #print(Td*X*T)
        X4 = X @ X @ X @ X
        T4 = T @ T @ T @ T
        Td4 = Td @ Td @ Td @ Td
        print(Td4 * X4 * T4)

    H = X + Z
    E = Map.from_array([[0, 1], [0, 0]], hom)  # raising
    F = Map.from_array([[0, 0], [1, 0]], hom)  # lowering

    CNOT = Map.from_array(
        [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], hom @ hom)

    SWAP = Map.from_array(
        [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], hom @ hom)

    assert SWAP * SWAP == II
    assert CNOT * CNOT == II

    G = mulclose([XI, IX, CNOT])  # order 8
    G = mulclose([XI, IX, CNOT, SWAP])  # order 24.. must be S_4
    G = mulclose([CNOT, SWAP])
    #    print(len(G))
    #    for g in G:
    #        print(g)

    A = SWAP @ I
    B = I @ SWAP
    S_3 = list(mulclose([A, B]))
    assert len(S_3) == 6
    #    for g in G:
    #        print(g)
    #    print(g.hom)

    hom = A.hom
    space = hom.src
    N = 2**3
    basis = space.get_basis()
    orbits = set()
    for v in basis:
        v1 = space.zero_vector()
        for g in S_3:
            u = g * v
            v1 = v1 + u
        orbits.add(v1)
    orbits = list(orbits)
    #    for v in orbits:
    #        print(v)

    HHH = H @ H @ H
    v = basis[7]
    #print(v)
    #print(HHH * v)

    print("OK")
Exemple #15
0
def make_dicyclic(n, debug=False):
    # Binary dihedral group
    # https://people.maths.bris.ac.uk/~matyd/GroupNames/dicyclic.html

    p = cyclotomic(PolynomialRing(Z), 4 * n)
    ring = PolynomialRing(Z) / p
    rzeta = ring.x
    zeta = rzeta**2
    izeta = zeta**(2 * n - 1)  # inverse

    for k in range(1, 6 * n):
        if zeta**k == 1:
            break
    assert k == 2 * n

    if n == 3:
        assert zeta - 1 == zeta**2

    i = rzeta**n
    assert i != 1
    assert i**2 == -1
    assert i**3 == -i
    assert i**4 == 1

    assert zeta**(2 * n) == 1
    assert izeta != 1
    assert zeta * izeta == 1

    def is_real(v):  # this is a total hack
        assert ring.promote(v) is v
        x = exp(2.j * pi / (4 * n))
        s = str(v)
        v = eval(s, locals())
        return abs(v.imag) < EPSILON

    for k in range(1, 6 * n):
        assert is_real(rzeta**k) == (k % (2 * n) == 0)

    assert is_real(zeta + izeta)

    # we use the natural 2-dim representation
    GL = Linear(2, ring)
    e = GL.get([[1, 0], [0, 1]])
    r = GL.get([[zeta, 0], [0, izeta]])
    s = GL.get([[0, -1], [1, 0]])

    Di = mulclose([r, s])
    Di = list(Di)
    assert len(Di) == 4 * n

    eidx = Di.index(e)
    ridx = Di.index(r)
    sidx = Di.index(s)

    G = cayley(Di)
    e = G[eidx]
    r = G[ridx]
    s = G[sidx]

    assert r**(2 * n) == e
    assert s**2 == r**n
    assert r * s * r == s

    # complex characters ----------------------------------------------------

    # build the transpose of the character table.
    cols = []
    elems = []  # group elements with order the cols
    cgy = []  # element of each cgy class
    kidxs = range(2, n)

    desc = []

    # class: e, size 1
    elems.append(e)
    cgy.append(e)
    desc.append("e")
    cols.append([1, 1, 1, 1, 2] + [2 for k in kidxs])

    # class: s^2, size 1
    cols.append([1, 1, (-1)**n, (-1)**n, -2] + [((-1)**k) * 2 for k in kidxs])
    elems.append(s * s)
    cgy.append(s * s)
    desc.append("s^2")

    for idx in range(1, n):
        # class: r**idx, size 2
        col = [1, 1, (-1)**idx, (-1)**idx, zeta**idx + izeta**idx
               ] + [zeta**(idx * k) + izeta**(idx * k) for k in kidxs]
        cols.append(col)
        cols.append(col)
        elems.append(r**idx)
        cgy.append(r**idx)
        desc.append("r^%d" % idx)
        elems.append(r**(2 * n - idx))

    for idx in range(n):
        # class: s, size n
        cols.append([1, -1, i**n, -i**n, 0] + [0 for k in kidxs])
        elems.append(s * (r**(2 * idx)))
    cgy.append(s)
    desc.append("s")

    for idx in range(n):
        # class: s*r, size n
        cols.append([1, -1, -i**n, i**n, 0] + [0 for k in kidxs])
        elems.append(s * (r**(2 * idx + 1)))
    cgy.append(s * r)
    desc.append("sr")

    #print(i, -i, i**n, -i**n)

    assert len(set(elems)) == len(elems) == len(G)
    assert set(elems) == set(G)

    for col in cols:
        assert len(col) == n + 3, len(col)

    if debug:
        print()
        for s in desc:
            s = "%10s" % s
            print(s, end=" ")
        print()
        c_chars = []
        for k in range(n + 3):
            chi = dict((elems[i], cols[i][k]) for i in range(4 * n))
            f = CFunc(G, chi)
            for g in cgy:
                s = "%10s" % (f[g])
                print(s, end=" ")
            print()
            c_chars.append(f)
        print()

        for f in c_chars:
            for g in c_chars:
                val = f.dot(g, normalize=False)
                #assert (f == g) == (val == 1)
                print(val, end=" ")
            print()

    else:
        c_chars = []
        for k in range(n + 3):
            chi = dict((elems[i], cols[i][k]) for i in range(4 * n))
            f = CFunc(G, chi)
            c_chars.append(f)

        for f in c_chars:
            for g in c_chars:
                val = f.dot(g)
                assert (f == g) == (val == 1)

    G.c_chars = c_chars

    # complex reps ----------------------------------------------------

    c_reps = []

    e = G[eidx]
    r = G[ridx]
    s = G[sidx]

    tp = Cat(G, ring)

    def mk_rep(gen, reps):
        assert reps
        f = reps[0]
        V = f.hom.src
        send_perms = mulclose_hom(gen, reps)
        rep = Rep(send_perms, V, tp)
        return rep

    # 1-dim irreps
    V = Space(1, ring)
    hom = Hom(V, V)

    f_1 = Map.from_array([[1]], hom)
    f_n1 = Map.from_array([[-1]], hom)

    c_reps.append(mk_rep([r, s], [f_1, f_1]))  # Triv
    c_reps.append(mk_rep([r, s], [f_1, f_n1]))  # 1A

    f_r = Map.from_array([[-1]], hom)
    f_s = Map.from_array([[i**n]], hom)
    c_reps.append(mk_rep([r, s], [f_r, f_s]))  # 1B

    f_s = Map.from_array([[-i**n]], hom)
    c_reps.append(mk_rep([r, s], [f_r, f_s]))  # 1C

    # 2-dim irreps
    V = Space(2, ring)
    hom = Hom(V, V)

    for k in range(1, n):
        rho_r = Map.from_array([[zeta**k, 0], [0, izeta**k]], hom)
        rho_s = Map.from_array([[0, 1], [(-1)**k, 0]], hom)
        c_reps.append(mk_rep([r, s], [rho_r, rho_s]))  # rho_k

    for idx, rep in enumerate(c_reps):
        rep.check()
        char = c_chars[idx]
        tr = rep.trace()
        tr = CFunc(G, tr)
        #        print(tr, end=" ")
        #        val = tr.frobenius_schur()
        #        if val == -1:
        #            print("quaternionic")
        #        elif val == 0:
        #            print("complex")
        #        elif val == 1:
        #            print("real")
        #        else:
        #            assert 0, val

        for g in G:
            lhs, rhs = tr[g], char[g]
            assert lhs == rhs, "%d: %s != %s" % (idx, lhs, rhs)

    assert len(c_reps) == n + 3
    G.c_reps = c_reps

    # real characters ----------------------------------------------------

    r_chars = []

    r_chars.append(c_chars[0])  # Triv
    r_chars.append(c_chars[1])  # 1A

    if n % 2 == 0:
        assert c_chars[2].frobenius_schur() == 1  # real
        assert c_chars[3].frobenius_schur() == 1  # real
        r_chars.append(c_chars[2])  # 1B
        r_chars.append(c_chars[3])  # 1C
    else:
        assert c_chars[2].frobenius_schur() == 0  # complex
        assert c_chars[3].frobenius_schur() == 0  # complex
        r_chars.append(c_chars[2] + c_chars[3])  # 1B+1C

    for idx, rep in enumerate(c_reps):
        if idx < 4:
            continue
        char = c_chars[idx]
        val = char.frobenius_schur()
        if val == 1:
            r_chars.append(char)
        elif val == -1:
            r_chars.append(2 * char)
        else:
            assert 0

    G.r_chars = r_chars

    return G
Exemple #16
0
def main():

    d = 2

    ring = CyclotomicRing(8)
    #ring = element.Z
    e = ring.x
    gamma = e**2
    w = gamma**2
    assert w == -1

    I = numpy.zeros((d, d), dtype=object)
    wI = numpy.zeros((d, d), dtype=object)
    X = numpy.zeros((d, d), dtype=object)
    Z = numpy.zeros((d, d), dtype=object)
    Zdag = numpy.zeros((d, d), dtype=object)
    S = numpy.zeros((d, d), dtype=object)
    Sdag = numpy.zeros((d, d), dtype=object)
    T = numpy.zeros((d, d), dtype=object)
    Tdag = numpy.zeros((d, d), dtype=object)
    for j in range(d):
        I[j, j] = 1
        wI[j, j] = w
        X[j, (j + 1) % d] = 1
        Z[j, j] = w**j
        Zdag[j, j] = w**(d - j)

        val = [1, gamma][j]
        ival = [1, -gamma][j]
        assert val * ival == 1

        S[j, j] = val
        Sdag[j, j] = ival

        val = [1, e][j]
        ival = [1, e**7][j]
        assert val * ival == 1

        T[j, j] = val
        Tdag[j, j] = ival

    qu = Space(d, ring)
    hom = Hom(qu, qu)

    I = Map.from_array(I, hom)
    wI = Map.from_array(wI, hom)
    Xdag = Map.from_array(X.transpose(), hom)
    X = Xs = Map.from_array(X, hom)
    Z = Map.from_array(Z, hom)
    Zdag = Map.from_array(Zdag, hom)
    S = Map.from_array(S, hom)
    Sdag = Map.from_array(Sdag, hom)
    T = Map.from_array(T, hom)
    Tdag = Map.from_array(Tdag, hom)

    Y = w * X * Z  # ?

    assert S * Sdag == I
    assert S * S == Z
    assert T * T == S

    assert Z * Zdag == I
    assert X * Xdag == I

    if d > 2:
        for j in range(1, d + 1):
            assert (j == d) == (X**j == I)
            assert (j == d) == (Z**j == I)
    else:
        assert X != I
        assert Z != I
        assert X * X == I
        assert Z * Z == I

    assert Z * X == (w**(d - 1)) * X * Z

    pauli = mulclose([X, Z, gamma * I])
    pauli = set(pauli)
    print("pauli:", len(pauli))
    assert Zdag in pauli
    assert Xdag in pauli

    if d < 6:
        # slow..
        lhs = atpow(X, d)
        rhs = atpow(Z, d)
        assert lhs * rhs == rhs * lhs

    lhs = X @ X
    rhs = Z @ Zdag
    assert lhs * rhs == rhs * lhs

    lhs = X @ (X**(d - 1))
    rhs = Z @ Z
    assert lhs * rhs == rhs * lhs

    if 0:
        n = 5
        ops = [X, Xdag]
        lhs = []
        for op in cross([ops] * n):
            op = reduce(matmul, op)
            lhs.append(op)

        ops = [Z, Zdag]
        rhs = []
        for op in cross([ops] * n):
            op = reduce(matmul, op)
            rhs.append(op)

        for l in lhs:
            for r in rhs:
                if l * r == r * l:
                    print("/", end=" ", flush=True)
                else:
                    print(".", end=" ", flush=True)
        print()

    #print(Z@Z@Z)

    #print(Y)
    #print(S*X*Sdag)
    #print(Y == S*X*Sdag)
    if d == 3:
        assert (Y == S * X * Sdag)

    inverse = {}
    for g in pauli:
        for h in pauli:
            if g * h == I:
                inverse[g] = h
                inverse[h] = g

    def is_cliff(A, Ai):
        assert A * Ai == I
        for g in pauli:
            h = A * g * Ai
            if h not in pauli:
                return False
        return True

    print(S)
    print(Sdag)
    assert is_cliff(S, Sdag)

    #print("is_cliff:", (S in pauli), is_cliff(S, Sdag))

    def is_third_level(A, Ai):
        assert A * Ai == I
        for g in pauli:
            gi = inverse[g]
            h = A * g * Ai * gi
            hi = g * A * gi * Ai
            if not is_cliff(h, hi):
                return False
        return True

    print("is_pauli(S)", S in pauli)
    print("is_cliff(S)", is_cliff(S, Sdag))
    #print("is_third_level(S)", is_third_level(S, Tdag))

    print("is_pauli(T)", T in pauli)
    print("is_cliff(T)", is_cliff(T, Tdag))
    print("is_third_level(T)", is_third_level(T, Tdag))

    #C2 = mulclose([X, T, H])

    print("OK")
Exemple #17
0
def main():

    #ring = element.Z
    ring = element.Q

    qubit = Space(2, ring)

    q2 = qubit @ qubit

    hom = Hom(qubit, qubit)

    I = Map.from_array([[1, 0], [0, 1]], hom)
    X = Map.from_array([[0, 1], [1, 0]], hom)
    Z = Map.from_array([[1, 0], [0, -1]], hom)
    H = X + Z
    E = Map.from_array([[0, 1], [0, 0]], hom)  # raising
    F = Map.from_array([[0, 0], [1, 0]], hom)  # lowering
    II = I @ I
    XI = X @ I
    IX = I @ X
    XX = X @ X
    assert XI * IX == XX

    CNOT = Map.from_array(
        [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], hom @ hom)

    SWAP = Map.from_array(
        [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], hom @ hom)

    assert SWAP * SWAP == II
    assert CNOT * CNOT == II

    G = mulclose([XI, IX, CNOT])  # order 8
    G = mulclose([XI, IX, CNOT, SWAP])  # order 24.. must be S_4
    G = mulclose([CNOT, SWAP])
    #    print(len(G))
    #    for g in G:
    #        print(g)

    A = SWAP @ I
    B = I @ SWAP
    S_3 = list(mulclose([A, B]))
    assert len(S_3) == 6
    #    for g in G:
    #        print(g)
    #    print(g.hom)

    hom = A.hom
    space = hom.src
    N = 2**3
    basis = space.get_basis()
    orbits = set()
    for v in basis:
        v1 = space.zero_vector()
        for g in S_3:
            u = g * v
            v1 = v1 + u
        orbits.add(v1)
    orbits = list(orbits)
    #    for v in orbits:
    #        print(v)

    HHH = H @ H @ H
    v = basis[7]
    #print(v)
    #print(HHH * v)

    # ----------------------------------------------------------

    specht = Specht(4, qubit)

    for i, A in enumerate(specht.projs):
        print("part:", specht.parts[i])
        print("proj:")
        im = A.image()
        #im = A
        src, tgt = im.hom
        for i in src:
            for j in tgt:
                v = im[j, i]
                if v != ring.zero:
                    print("%s*%s" % (v, j), end=" ")
            print()

    return

    # ----------------------------------------------------------

    items = [0, 1, 2, 3]
    g1 = Perm({0: 1, 1: 0, 2: 2, 3: 3}, items)
    g2 = Perm({0: 0, 1: 2, 2: 1, 3: 3}, items)
    g3 = Perm({0: 0, 1: 1, 2: 3, 3: 2}, items)
    gen1 = [g1, g2, g3]

    s1 = SWAP @ I @ I
    s2 = I @ SWAP @ I
    s3 = I @ I @ SWAP
    gen2 = [s1, s2, s3]

    G = mulclose(gen1)
    hom = mulclose_hom(gen1, gen2)
    for g in G:
        for h in G:
            assert hom[g * h] == hom[g] * hom[h]  # check it's a group hom

    projs = []
    for part in [(4, ), (3, 1), (2, 2)]:
        t = Young(part)

        rowG = t.get_rowperms()
        colG = t.get_colperms()
        horiz = None
        for g in rowG:
            P = hom[g]
            horiz = P if horiz is None else (horiz + P)

        vert = None
        for g in colG:
            P = hom[g]
            s = g.sign()
            P = s * P
            vert = P if vert is None else (vert + P)
        A = vert * horiz
        #A = horiz * vert

        assert vert * vert == len(colG) * vert
        assert horiz * horiz == len(rowG) * horiz
        #print(t)
        #print(A)
        projs.append(A)

    for A in projs:
        for B in projs:
            assert A * B == B * A


#    print()
#    for A in projs:
#        for g in G:
#            P = hom[g]
#            if P*A != A*P:
#                print(P*A)
#                print(A*P)
#                return

    for A in projs:
        print("proj:")
        im = A.image()
        #im = A
        src, tgt = im.hom
        for i in src:
            for j in tgt:
                v = im[j, i]
                if v != ring.zero:
                    print("%s*%s" % (v, j), end=" ")
            print()