Пример #1
0
    def __init__(self, U, q=2):
        m, n = U.shape
        #scalars = list(range(1, q))
        #print(scalars, U)
        #vecs = list(((r*v)) for v in span(U) for r in scalars)
        #print(vecs)
        #vecs = list(((r*v)%q) for v in span(U) for r in scalars)
        #print(vecs)
        #print()
        #vecs = set(((r*v)%q).tostring() for v in span(U) for r in scalars)

        vecs = set()
        vals = list(range(q))
        for u in cross((vals, ) * m):
            vec = numpy.dot(u, U) % q
            vecs.add(vec.tostring())

        vecs = list(vecs)
        vecs.sort()
        vecs = tuple(vecs)
        #assert len(vecs) == len(set(vecs))
        self.n = n
        self.U = U
        self._key = vecs
        N = len(vecs)
        m = int(round(log2(N) / log2(q)))
        assert q**m == N
        self.m = m  # rank of U
Пример #2
0
def find_alpha(g):
    # alpha is determined by its values on the basis elements
    # (no it's not linear!) but here we search through all functions
    # (dict's) space -> 2Z/4Z . There are always N solutions .
    n = g.n
    space = vecspace(2 * n)
    lhs = {}
    pairs = [(v, w) for v in space for w in space]
    for (v, w) in pairs:
        lhs[v, w] = (beta(g(v), g(w)) - beta(v, w)) % 4

    N = 2**(2 * n)
    for value in cross([(0, 1)] * N):
        alpha = {}
        for idx, v in enumerate(space):
            alpha[v] = 2 * value[idx]
        #print(alpha)

        for (v, w) in pairs:
            #if alpha[v] + alpha[w] != alpha[v+w]:
            #    break
            #lhs = (beta(g(v), g(w)) - beta(v, w)) % 4
            rhs = (alpha[v + w] - alpha[v] - alpha[w]) % 4
            if lhs[v, w] != rhs:
                break
        else:
            yield alpha
Пример #3
0
def get_cell(row, col, p=2):
    """
        return all matrices in bruhat cell at (row, col)
        These have shape (col, col+row).
    """

    if col == 0:
        yield zeros2(0, row)
        return

    if row == 0:
        yield identity2(col)
        return

    # recursive steps:
    m, n = col, col + row
    for left in get_cell(row, col - 1, p):
        A = zeros2(m, n)
        A[:m - 1, :n - 1] = left
        A[m - 1, n - 1] = 1
        yield A

    els = list(range(p))
    vecs = list(cross((els, ) * m))
    for right in get_cell(row - 1, col, p):
        for v in vecs:
            A = zeros2(m, n)
            A[:, :n - 1] = right
            A[:, n - 1] = v
            yield A
Пример #4
0
def all_codes_3(pauli, n):
    I = pauli.I
    X = pauli.X
    Y = pauli.Y
    Z = pauli.Z

    In = reduce(matmul, [I] * n)
    all_ops = [reduce(matmul, op) for op in cross([[I, X, Y, Z]] * n)]
    assert all_ops[0] == In
    all_ops.pop(0)

    N = len(all_ops)
    print("all_ops:", N)

    for i in range(N):
        opi = all_ops[i]
        for j in range(i + 1, N):
            opj = all_ops[j]
            if opi * opj != opj * opi:
                continue
            for k in range(j + 1, N):
                opk = all_ops[k]
                if opi * opk != opk * opi:
                    continue
                if opj * opk != opk * opj:
                    continue
                yield [opi, opj, opk]
Пример #5
0
 def get_basis(self):
     count = 0
     for decl in cross(["IXZY"] * self.n):
         decl = ''.join(decl)
         op = parse(decl)
         yield decl, op
         count += 1
     assert count == 4**self.n
Пример #6
0
def search():

    CX = X.control(0, 1)  # target, source

    assert CZ == Z.control(0, 1)
    assert CZ == Z.control(1, 0)
    #print(CZ.flat().v)

    #print(X.control(0, 1).flat().v)
    #print(X.control(1, 0).flat().v)

    #chi = (I @ CX @ I) * (bell @ bell) # looking to teleport a CX gate
    #B = (H @ H) * CZ

    chi = (I @ CZ @ I) * (bell @ bell)  # looking to teleport a CZ gate
    B = CZ

    start = (B @ I @ I @ B) * (I @ chi @ I)

    for idxs in cross([(0, 1, 2)] * 6):

        ops = [(I, X, Z)[i] for i in idxs]

        # IXX XIX

        lhs = ops[0].control(2, 4, rank=6) * start
        lhs = ops[1].control(3, 4, rank=6) * lhs
        lhs = ops[2].control(2, 5, rank=6) * lhs

        lhs = ops[3].control(2, 0, rank=6) * lhs
        lhs = ops[4].control(3, 0, rank=6) * lhs
        lhs = ops[5].control(3, 1, rank=6) * lhs

        lhs0 = lhs

        x = plus
        #x = one
        lhs = (~x @ ~x @ I @ I @ ~x @ ~x) * lhs
        #print(lhs.valence)
        #print(lhs.valence, lhs.shortstr(), lhs[0,0,0,0])
        r = lhs[0, 0, 0, 0]

        if abs(r) < EPSILON:
            continue

        lhs /= r

        if lhs == CZ:
            print("FOUND " * 10)
            print(lhs.shortstr())
            print(['IXZ'[i] for i in idxs])

            #break

    if 0:
        print(lhs0.shortstr())
        op = (Z.control(0, 5) * (I @ plus @ plus @ plus @ plus @ I))
        print(op.shortstr())
Пример #7
0
def vecspace(n):
    if n in _vec_cache:
        return _vec_cache[n]
    items = [(0, 1)] * n
    space = []
    for v in cross(items):
        space.append(Vector(v))
    _vec_cache[n] = space
    return space
Пример #8
0
 def generate(self, q):
     A = self.A
     stars = self.stars
     q = range(q)
     for vals in cross((q, ) * len(stars)):
         B = A.copy()
         for i, val in enumerate(vals):
             B[stars[i]] = val
         yield B
Пример #9
0
def borel_gl(n, q):
    "Borel subgroup of GL(n, q)"

    A = numpy.zeros((n, n), dtype=int)

    stars = [(i, j) for i in range(0, n - 1) for j in range(i + 1, n)]

    nz = list(range(1, q))
    diags = [diag for diag in cross((nz, ) * n)]
    #print(len(diags), len(stars))

    N = len(stars)
    for vals in cross((range(q), ) * N):
        for diag in diags:
            X = A.copy()
            for i, val in enumerate(vals):
                X[stars[i]] = val
            for i in range(n):
                X[i, i] = diag[i]
            yield X
Пример #10
0
 def get_reflects(G, I):
     reflects = []
     count = 0
     for ops in cross((G, ) * degree):
         op = reduce(matmul, ops)
         if op * op == I:
             count += 1
             reflects.append(op)
     reflects.remove(I)
     reflects.remove(nI)
     return reflects
Пример #11
0
def borel_sp(n, q):
    "Borel subgroup of Sp(n, q)"

    assert n % 2 == 0
    n2 = n // 2

    J = mk_form(n, q)

    mul = list(range(1, q))
    inv = {}
    for i in mul:
        for j in mul:
            if (i * j) % q == 1:
                inv[i] = j
                break
        else:
            assert 0

    diags = []
    for diag0 in cross((mul, ) * n2):
        diag1 = tuple(inv[i] for i in diag0)
        diags.append(diag0 + diag1)
        #print(diag0 + diag1)

    stars = [(i, j) for i in range(0, n2) for j in range(n2, n)]

    J = mk_form(n, q)
    N = len(stars)
    X = numpy.zeros((n, n), dtype=int)
    for vals in cross((range(q), ) * N):
        for i, star in enumerate(stars):
            X[star] = vals[i]
        for diag in diags:
            for i in range(n):
                X[i, i] = diag[i]
            XtJX = numpy.dot(X.transpose(), numpy.dot(J, X)) % q
            if XtJX.tostring() == J.tostring():
                yield X.copy()
Пример #12
0
def make_relators(I, gen, names=None, depth=5):
    # make some gap code for generators and relators
    n = len(gen)
    rels = set()

    def addword(word):
        i = min(word)
        idx = word.index(i)
        n = len(word)
        word = tuple(word[(i + idx) % n] for i in range(n))
        rels.add(word)

    for width in range(2, depth):
        itemss = [tuple(range(n))] * width
        for word in cross(itemss):
            gword = [gen[i] for i in word]
            g = reduce(mul, gword)
            if g == I:
                for h in rels:
                    if contains(h, word + word):
                        break
                else:
                    addword(word)
    print("rels:", len(rels))
    if names is None:
        names = string.ascii_letters[:n]
    if len(names) < n:
        names = [
            "%s%s" % (a, b) for a in string.ascii_letters
            for b in string.ascii_letters
        ]
    assert len(names) == len(set(names)) == n, repr(names)
    print()
    print("F := FreeGroup(%s);;" % (",".join('"%s"' % l for l in names)))
    for idx, name in enumerate(names):
        print("%s := F.%s;;" % (name, idx + 1))
    items = []
    rels = list(rels)
    rels.sort()
    for rel in rels:
        rel = [names[idx] for idx in rel]
        rel = "*".join(rel)
        items.append(rel)
    print("G := F / [%s];;" % (','.join(items)))
    print("Order(G);")
Пример #13
0
def find_triorth(m, k):
    # Bravyi, Haah, 1209.2426v1 sec IX.
    # https://arxiv.org/pdf/1209.2426.pdf

    verbose = argv.get("verbose")
    #m = argv.get("m", 6) # _number of rows
    #k = argv.get("k", None) # _number of odd-weight rows

    # these are the variables N_x
    xs = list(cross([(0, 1)] * m))

    maxweight = argv.maxweight
    minweight = argv.get("minweight", 1)

    xs = [x for x in xs if minweight <= sum(x)]
    if maxweight:
        xs = [x for x in xs if sum(x) <= maxweight]

    N = len(xs)

    lhs = []
    rhs = []

    # bi-orthogonality
    for a in range(m):
        for b in range(a + 1, m):
            v = zeros2(N)
            for i, x in enumerate(xs):
                if x[a] == x[b] == 1:
                    v[i] = 1
            if v.sum():
                lhs.append(v)
                rhs.append(0)

    # tri-orthogonality
    for a in range(m):
        for b in range(a + 1, m):
            for c in range(b + 1, m):
                v = zeros2(N)
                for i, x in enumerate(xs):
                    if x[a] == x[b] == x[c] == 1:
                        v[i] = 1
                if v.sum():
                    lhs.append(v)
                    rhs.append(0)

#    # dissallow columns with weight <= 1
#    for i, x in enumerate(xs):
#        if sum(x)<=1:
#            v = zeros2(N)
#            v[i] = 1
#            lhs.append(v)
#            rhs.append(0)

    if k is not None:
        # constrain to k _number of odd-weight rows
        assert 0 <= k < m
        for a in range(m):
            v = zeros2(N)
            for i, x in enumerate(xs):
                if x[a] == 1:
                    v[i] = 1
            lhs.append(v)
            if a < k:
                rhs.append(1)
            else:
                rhs.append(0)

    A = array2(lhs)
    rhs = array2(rhs)
    #print(shortstr(A))

    B = pseudo_inverse(A)
    soln = dot2(B, rhs)
    if not eq2(dot2(A, soln), rhs):
        print("no solution")
        return
    if verbose:
        print("soln:")
        print(shortstr(soln))

    soln.shape = (N, 1)
    rhs.shape = A.shape[0], 1

    K = array2(list(find_kernel(A)))
    #print(K)
    #print( dot2(A, K.transpose()))
    #sols = []
    #for v in span(K):
    best = None
    density = 1.0
    size = 99 * N
    trials = argv.get("trials", 1024)
    count = 0
    for trial in range(trials):
        u = rand2(len(K), 1)
        v = dot2(K.transpose(), u)
        #print(v)
        v = (v + soln) % 2
        assert eq2(dot2(A, v), rhs)

        if v.sum() > size:
            continue
        size = v.sum()

        Gt = []
        for i, x in enumerate(xs):
            if v[i]:
                Gt.append(x)
        if not Gt:
            continue
        Gt = array2(Gt)
        G = Gt.transpose()
        assert is_morthogonal(G, 3)
        if G.shape[1] < m:
            continue

        if 0 in G.sum(1):
            continue

        if argv.strong_morthogonal and not strong_morthogonal(G, 3):
            continue

        #print(shortstr(G))


#        for g in G:
#            print(shortstr(g), g.sum())
#        print()

        _density = float(G.sum()) / (G.shape[0] * G.shape[1])
        #if best is None or _density < density:
        if best is None or G.shape[1] <= size:
            best = G
            size = G.shape[1]
            density = _density

        if 0:
            #sols.append(G)
            Gx = even_rows(G)
            assert is_morthogonal(Gx, 3)
            if len(Gx) == 0:
                continue
            GGx = array2(list(span(Gx)))
            assert is_morthogonal(GGx, 3)

        count += 1

    print("found %d solutions" % count)
    if best is None:
        return

    G = best
    #print(shortstr(G))

    for g in G:
        print(shortstr(g), g.sum())
    print()
    print("density:", density)
    print("shape:", G.shape)

    G = linear_independent(G)

    if 0:
        A = list(span(G))
        print(strong_morthogonal(A, 1))
        print(strong_morthogonal(A, 2))
        print(strong_morthogonal(A, 3))

    G = [row for row in G if row.sum() % 2 == 0]
    return array2(G)

    #print(shortstr(dot2(G, G.transpose())))

    if 0:
        B = pseudo_inverse(A)
        v = dot2(B, rhs)
        print("B:")
        print(shortstr(B))
        print("v:")
        print(shortstr(v))
        assert eq2(dot2(B, v), rhs)
Пример #14
0
def bruhat():

    n = argv.get("n", 4)
    assert n % 2 == 0, repr(n)
    m = argv.get("m", 2)
    q = argv.get("q", 2)

    # symplectic form
    A = mk_form(n, q)

    # all non-zero vectors
    vals = list(range(q))
    vecs = list(cross((vals, ) * n))
    assert sum(vecs[0]) == 0
    vecs.pop(0)

    # find unique spaces
    spaces = set()
    for U in cross_upper(vecs, m):
        U = numpy.array(U)
        U.shape = m, n
        B = numpy.dot(U, numpy.dot(A, U.transpose())) % q
        if B.max():
            continue

        space = Space(U, q)
        if space.m != m:
            continue
        spaces.add(space)

        if 0:
            #space = [str(v) for v in span(U)] # SLOW
            space = [v.tostring() for v in span(U)]  # q==2 only
            if len(space) != q**m:
                continue
            space.sort()
            #space = ''.join(space)
            #print(space)
            space = tuple(space)
            spaces.add(space)

    N = len(spaces)
    print("points:", N)
    if argv.verbose:
        for X in spaces:
            print(X)

    B = list(borel_sp(n, q))
    print("borel:", len(B))
    assert len(B)

    spaces = list(spaces)
    lookup = dict((space, i) for (i, space) in enumerate(spaces))

    orbits = list(set([space]) for space in spaces)

    perms = []
    for g in B:
        perm = []
        for i, space in enumerate(spaces):
            U = numpy.dot(space.U, g) % q
            t = Space(U, q)
            #if t not in lookup:
            #    print(space)
            #    print(t)
            perm.append(lookup[t])
        perms.append(perm)
        print(".", end=" ", flush=True)
    print()

    remain = set(range(N))
    orbits = []
    while remain:
        i = iter(remain).__next__()
        remain.remove(i)
        orbit = [i]
        for perm in perms:
            j = perm[i]
            if j in remain:
                remain.remove(j)
                orbit.append(j)
        orbits.append(orbit)

    orbits.sort(key=len)
    print("%d orbits:" % len(orbits))
    for orbit in orbits:
        print("size =", len(orbit))
        for idx in orbit:
            space = spaces[idx]
            U = space.U
            if q == 2:
                U = row_reduce(U)
Пример #15
0
def main():

    #pauli = build_algebra("IXZY", "X*X=I Z*Z=I Y*Y=-I X*Z=Y Z*X=-Y X*Y=Z Y*X=-Z Z*Y=-X Y*Z=X")
    pauli = build_algebra(
        "IXZY",
        "X*X=I Z*Z=I Y*Y=I X*Z=-iY Z*X=iY X*Y=iZ Y*X=-iZ Z*Y=-iX Y*Z=iX")

    I = pauli.I
    X = pauli.X
    Y = pauli.Y
    Z = pauli.Z

    n = argv.get("n", 4)

    #all_ops = [reduce(matmul, op) for op in cross([[I, X, Y, Z]]*n)]

    if 0:
        code = StabilizerCode(pauli, "XXXI ZZIZ IYYY")
        #code = StabilizerCode(pauli, "XYZI IXYZ ZIXY")
        #code = StabilizerCode(pauli, "XZZXI IXZZX XIXZZ ZXIXZ")
        n = code.n

        P = code.get_projector()
        print(P)

    I = Gate.I
    X = Gate.X
    Z = Gate.Z
    Y = Gate.Y
    S = Gate.S
    Sd = S.dag()
    ns = {"I": I, "X": X, "Z": Z, "Y": Y, "S": S}

    Xt = reduce(matmul, [X] * n)
    Zt = reduce(matmul, [Z] * n)
    Yt = reduce(matmul, [Y] * n)
    St = reduce(matmul, [S] * n)

    if 0:
        for g in all_ops:
            desc = str(g)
            g = get_dense(g)
            if g * St != St * g:
                continue

                print(desc)
        return

    #code = StabilizerCode(pauli, "XZZXI IXZZX XIXZZ ZXIXZ") # S is not transversal

    count = 0
    for P in uniq_codes(pauli, n):

        desc = str(P)
        P = get_dense(P)
        if P * Xt != Xt * P:
            continue
        if P * Zt != Zt * P:
            continue
        if P * St != St * P:
            continue
        if P * Xt == P or P * Xt == -P:
            continue
        if P * Zt == P or P * Zt == -P:
            continue
        if P * Yt == P or P * Yt == -P:
            continue
        print(desc)
        count += 1
    print("count:", count)

    if 0:
        for ops in cross([["I", "S", "X", "Z", "Y"]] * n):
            s = "".join(ops)
            ops = [ns[op] for op in ops]
            op = reduce(matmul, ops)
            if P * op == op * P:
                print(s)