Example #1
0
File: glue.py Project: punkdit/qupy
def glue_pairs(H1, H2, pairs):

    m1, n1 = H1.shape
    m2, n2 = H2.shape
    k = len(pairs)

    A1 = Chain([H1])
    A2 = Chain([H2])
    C = Chain([identity2(k)])

    C1n = zeros2(n1, k)
    for idx, pair in enumerate(pairs):
        i, j = pair
        C1n[i, idx] = 1
    C1m = dot2(H1, C1n)
    C1 = Morphism(C, A1, [C1m, C1n])

    C2n = zeros2(n2, k)
    for idx, pair in enumerate(pairs):
        i, j = pair
        C2n[j, idx] = 1
    C2m = dot2(H2, C2n)
    C2 = Morphism(C, A2, [C2m, C2n])

    AD, BD, D, _ = chain.pushout(C1, C2)

    H = D[0]
    #print(H.shape)
    #print(H)
    return H
Example #2
0
File: glue.py Project: punkdit/qupy
def glue_self(Hx, Hz, pairs):
    mx, n = Hx.shape
    mz, _ = Hz.shape
    k = len(pairs)

    A = Chain([Hz, Hx.transpose()])
    C = Chain([identity2(k), zeros2(k, 0)])

    fn = zeros2(n, k)
    for idx, pair in enumerate(pairs):
        i1, i2 = pair
        fn[i1, idx] = 1
    fm = dot2(Hz, fn)
    f = Morphism(C, A, [fm, fn, zeros2(mx, 0)])

    gn = zeros2(n, k)
    for idx, pair in enumerate(pairs):
        i1, i2 = pair
        gn[i2, idx] = 1
    gm = dot2(Hz, gn)
    g = Morphism(C, A, [gm, gn, zeros2(mx, 0)])

    _, _, D = chain.equalizer(f, g)

    Hz, Hxt = D[0], D[1]
    return Hxt.transpose(), Hz
Example #3
0
File: glue.py Project: punkdit/qupy
def glue_quantum(Hx1, Hz1, Hx2, Hz2, pairs):

    mx1, n1 = Hx1.shape
    mx2, n2 = Hx2.shape
    mz1, _ = Hz1.shape
    mz2, _ = Hz2.shape
    k = len(pairs)

    A1 = Chain([Hz1, Hx1.transpose()])
    A2 = Chain([Hz2, Hx2.transpose()])
    C = Chain([identity2(k), zeros2(k, 0)])

    C1n = zeros2(n1, k)
    for idx, pair in enumerate(pairs):
        i, j = pair
        C1n[i, idx] = 1
    C1m = dot2(Hz1, C1n)
    C1 = Morphism(C, A1, [C1m, C1n, zeros2(mx1, 0)])

    C2n = zeros2(n2, k)
    for idx, pair in enumerate(pairs):
        i, j = pair
        C2n[j, idx] = 1
    C2m = dot2(Hz2, C2n)
    C2 = Morphism(C, A2, [C2m, C2n, zeros2(mx2, 0)])

    AD, BD, D, _ = chain.pushout(C1, C2)

    Hz, Hxt = D[0], D[1]
    #print(H.shape)
    #print(H)

    return Hz, Hxt.transpose()
Example #4
0
File: glue.py Project: punkdit/qupy
def glue_self_classical(Hz, pairs):
    mz, n = Hz.shape
    k = len(pairs)

    A = Chain([Hz])
    C = Chain([identity2(k)])

    fn = zeros2(n, k)
    for idx, pair in enumerate(pairs):
        i1, i2 = pair
        fn[i1, idx] = 1
    fm = dot2(Hz, fn)
    f = Morphism(C, A, [fm, fn])

    gn = zeros2(n, k)
    for idx, pair in enumerate(pairs):
        i1, i2 = pair
        gn[i2, idx] = 1
    gm = dot2(Hz, gn)
    g = Morphism(C, A, [gm, gn])

    _, _, D = chain.equalizer(f, g)

    Hz = D[0]
    return Hz
Example #5
0
File: glue.py Project: punkdit/qupy
def test_glue():

    m = argv.get("m", 9)
    n = argv.get("n", 10)

    d = argv.get("d", 0)
    p = argv.get("p", 0.5)
    weight = argv.weight

    H1 = rand2(m, n, p, weight)
    G1 = find_kernel(H1)
    G1t = G1.transpose()
    H1t = H1.transpose()
    A1 = Chain([G1, H1t])
    k1 = len(G1)

    print("H1")
    print(fstr(H1))
    print()
    print(fstr(G1))

    w = wenum(H1)
    print("wenum:", [len(wi) for wi in w])

    H2 = rand2(m, n, p, weight)
    H2t = H2.transpose()
    G2 = find_kernel(H2)
    G2t = G2.transpose()
    A2 = Chain([G2, H2t])
    k2 = len(G2)

    print("H2")
    print(fstr(H2))
    print()
    print(fstr(G2))

    w = wenum(H2)
    print("wenum:", [len(wi) for wi in w])

    if k1 != k2:
        return
    k = k1

    I = identity2(k)
    B = Chain([I, zeros2(k, 0)])

    a = zeros2(n, k)
    for i in range(k):
        a[i, i] = 1
    f1 = Morphism(B, A1, [dot2(G1, a), a, zeros2(m, 0)])
    f2 = Morphism(B, A2, [dot2(G2, a), a, zeros2(m, 0)])

    a, b, C, _ = chain.pushout(f1, f2)

    H = C[1].transpose()
    print("H:")
    print(fstr(H))

    w = wenum(H)
    print("wenum:", [len(wi) for wi in w])
Example #6
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
Example #7
0
    def glue(self, i1, i2):
        assert i1!=i2

        Hx = self.Hx
        Hz = self.Hz
        mx, n = Hx.shape
        mz, _ = Hz.shape
        k = 1 
    
        A = Chain([Hz, Hx.transpose()])
        C  = Chain([identity2(k), zeros2(k, 0)])
    
        fn = zeros2(n, 1)
        fn[i1, 0] = 1 
        fm = dot2(Hz, fn) 
        f = Morphism(C, A, [fm, fn, zeros2(mx, 0)])
    
        gn = zeros2(n, 1)
        gn[i2, 0] = 1 
        gm = dot2(Hz, gn) 
        g = Morphism(C, A, [gm, gn, zeros2(mx, 0)])
    
        _, _, D = equalizer(f, g)
    
        Hz, Hxt = D[0], D[1]
        Hx = Hxt.transpose()
        code = CSSCode(Hx=Hx, Hz=Hz)
        return code
Example #8
0
 def symplectic_form(cls, n):
     A = zeros2(2 * n, 2 * n)
     I = identity2(n)
     A[:n, n:] = I
     A[n:, :n] = I
     A = Matrix(A)
     return A
Example #9
0
    def get_logops(idxs_C, idxs_Ct, idxs_D, idxs_Dt):

        # Lx --------------------------------------------------------------

        Ic1 = identity2(c1)[idxs_C, :]
        Lx_h = kron(Ic1,
                    CokerD), zeros2(len(idxs_C) * CokerD.shape[0], c0 * d1)
        Lx_h = numpy.concatenate(Lx_h, axis=1)
        assert dot2(Lx_h, Hz.transpose()).sum() == 0

        Id1 = identity2(d1)[idxs_D, :]
        Lx_v = zeros2(CokerC.shape[0] * len(idxs_D),
                      c1 * d0), kron(CokerC, Id1)
        Lx_v = numpy.concatenate(Lx_v, axis=1)
        Lxi = numpy.concatenate((Lx_h, Lx_v), axis=0)

        # Lz --------------------------------------------------------------

        KerCt = KerC.transpose()
        Id0 = identity2(d0)[:, idxs_Dt]
        Lzt_h = kron(KerCt, Id0), zeros2(c0 * d1,
                                         KerCt.shape[1] * len(idxs_Dt))
        Lzt_h = numpy.concatenate(Lzt_h, axis=0)
        assert dot2(Hx, Lzt_h).sum() == 0

        KerDt = KerD.transpose()
        assert KerDt.shape[0] == d1
        Ic0 = identity2(c0)[:, idxs_Ct]
        Lzt_v = zeros2(c1 * d0,
                       len(idxs_Ct) * KerDt.shape[1]), kron(Ic0, KerDt)
        Lzt_v = numpy.concatenate(Lzt_v, axis=0)
        assert dot2(Hx, Lzt_v).sum() == 0

        Lzti = numpy.concatenate((Lzt_h, Lzt_v), axis=1)
        Lzi = Lzti.transpose()

        # checking ---------------------------------------------------------

        assert dot2(Hx, Lzti).sum() == 0

        assert rank(Lxi) == len(Lxi)  # full rank
        assert rank(Lzi) == len(Lzi)  # full rank

        assert eq_span(numpy.concatenate((Lxi, Hx)), LxiHx)
        assert eq_span(numpy.concatenate((Lzi, Hz)), LziHz)

        return Lxi, Lzi
Example #10
0
def main():

    n = argv.get("n", 8)
    k = argv.get("k", 4)
    kt = argv.get("kt", 4)
    d = argv.get("d", 1) # distance
    na = argv.get("na", n)
    nb = argv.get("nb", n)
    ka = argv.get("ka", k)
    kat = argv.get("kat", kt)
    kb = argv.get("kb", k)
    kbt = argv.get("kbt", kt)
    A = random_code(na, ka, kat, d)
    B = random_code(nb, kb, kbt, d)
    #assert A.shape == (na-ka, na), (A.shape,)
    #assert B.shape == (nb-kb, nb), (B.shape,)

    print("A, B:")
    print(shortstrx(A, B))

    if 1:
        # A tensor B
        kw = hypergraph_product(A, B)
        test_puncture(**kw)

    else:
        # --------------------------------------
        #B, Bt = Bt, B
    
        KerA = find_kernel(A).transpose()
        ma = na-ka
        mb = nb-kb
    
        print("KerA:")
        print(shortstrx(KerA))
        print()
    #    print(shortstrx(kron(KerA, identity2(mb))))
    
        
        print(shortstrx(
            kron(identity2(mb), KerA), 
            kron(B, identity2(na))))
Example #11
0
def rand_codes(m, n, trials=10000):
    assert 0<=m<=n
    k = n-m
    I = identity2(m)
    count = 0
    while count < trials:
        H = zeros2(m, n)
        A = rand2(m, k)
        H[:, :k] = A
        H[:, k:] = I
        yield H
        count += 1
Example #12
0
def in_support(H, keep_idxs):
    # find span of H contained within idxs support
    n = H.shape[1]
    remove_idxs = [i for i in range(n) if i not in keep_idxs]
    A = identity2(n)
    A = A[remove_idxs]
    #print("in_support", remove_idxs)
    P = get_reductor(A)
    PH = dot2(H, P.transpose())
    PH = row_reduce(PH)
    #print(shortstr(PH))
    return PH
Example #13
0
def in_support(H, keep_idxs, check=False):  # copied from classical.py
    # find span of H contained within idxs support
    n = H.shape[1]
    remove_idxs = [i for i in range(n) if i not in keep_idxs]
    A = identity2(n)
    A = A[keep_idxs]
    H1 = intersect(A, H)

    if check:
        lhs = set(str(x) for x in span(A))
        rhs = set(str(x) for x in span(H))
        meet = lhs.intersection(rhs)
        assert meet == set(str(x) for x in span(H1))

    return H1
Example #14
0
def get_puncture(M, k):
    "k-puncture the rowspace of M"
    m, n = M.shape

    assert 0<=k<=n
    mask = [1]*k + [0]*(n-k)
    I = identity2(n)

    while 1:
        shuffle(mask)
        A = I[list(idx for idx in range(n) if mask[idx])]
        assert A.shape == (k, n)
        AM = intersect(A, M)
        if len(AM) == 0:
            break
    #print("get_puncture:", mask)
    #print(M, k)
    idxs = [i for i in range(n) if mask[i]]
    return idxs
Example #15
0
def make_gallagher(r, n, l, m, distance=0, verbose=False):
    assert r % l == 0
    assert n % m == 0
    assert r * m == n * l
    if verbose:
        print("make_gallagher", r, n, l, m, distance)
    H = zeros2(r, n)
    H1 = zeros2(r // l, n)
    H11 = identity2(r // l)
    #print(H1)
    #print(H11)
    for i in range(m):
        H1[:, (n // m) * i:(n // m) * (i + 1)] = H11
    #print(shortstrx(H1))

    while 1:
        H2 = H1.copy()
        idxs = list(range(n))
        for i in range(l):
            H[(r // l) * i:(r // l) * (i + 1), :] = H2
            shuffle(idxs)
            H2 = H2[:, idxs]
        #print(H.shape)
        Hli = linear_independent(H)
        k = Hli.shape[0] - Hli.shape[1]
        assert k <= 24, "ummm, too big? k = %d" % k
        if distance is None:
            break
        if verbose:
            write("/")
        dist = classical_distance(Hli, distance)
        if dist >= distance:
            break
        if verbose:
            write(".")
    if verbose:
        write("\n")
    return Hli
Example #16
0
File: glue.py Project: punkdit/qupy
def glue1_quantum(Hx, Hz, i1, i2):
    assert i1 != i2

    mx, n = Hx.shape
    mz, _ = Hz.shape
    k = 1

    A = Chain([Hz, Hx.transpose()])
    C = Chain([identity2(k), zeros2(k, 0)])

    fn = zeros2(n, 1)
    fn[i1, 0] = 1
    fm = dot2(Hz, fn)
    f = Morphism(C, A, [fm, fn, zeros2(mx, 0)])

    gn = zeros2(n, 1)
    gn[i2, 0] = 1
    gm = dot2(Hz, gn)
    g = Morphism(C, A, [gm, gn, zeros2(mx, 0)])

    _, _, D = chain.equalizer(f, g)

    Hz, Hxt = D[0], D[1]
    return Hxt.transpose(), Hz
Example #17
0
def is_correctable(idxs, n, LxiHx, LziHz, Hx, Hz, Lx, Lz, **kw):
    #print("len(idxs) =", len(idxs))
    #Ax = in_support(LxiHx, idxs)
    #print(Ax.shape)

    A = identity2(n)[idxs]
    Ax = intersect(LxiHx, A)
    Az = intersect(LziHz, A)

    assert dot2(Ax, Hz.transpose()).sum() == 0
    assert dot2(Az, Hx.transpose()).sum() == 0

    if dot2(Ax, Lz.transpose()).sum() == 0 and dot2(Az,
                                                    Lx.transpose()).sum() == 0:
        return True

    if 0:
        #draw.mark_zop(Az[0])
        print("Ax:")
        print(shortstr(Ax))
        print("Az:")
        print(shortstr(Az))

    return False
Example #18
0
def main():

    import models

    assert not argv.orbiham, "it's called orbigraph now"

    if argv.find_ideals:
        find_ideals()
        return

    Gx, Gz, Hx, Hz = models.build()

    if argv.chainmap:
        do_chainmap(Gx, Gz)

    if argv.symmetry:
        do_symmetry(Gx, Gz, Hx, Hz)
        return
    
    #print shortstrx(Gx, Gz)
    if argv.report:
        print("Hz:")
        for i, h in enumerate(Hz):
            print(i, shortstr(h), h.sum())
    #print shortstr(find_stabilizers(Gx, Gz))

    Lz = find_logops(Gx, Hz)
    Lx = find_logops(Gz, Hx)
    #print "Lz:", shortstr(Lz)

    if Lz.shape[0]*Lz.shape[1]:
        print(Lz.shape, Gx.shape)
        check_commute(Lz, Gx)
        check_commute(Lz, Hx)

    Px = get_reductor(Hx) # projector onto complement of rowspan of Hx
    Pz = get_reductor(Hz) 

    Rz = [dot2(Pz, g) for g in Gz]
    Rz = array2(Rz)
    Rz = row_reduce(Rz, truncate=True)
    rz = len(Rz)

    n = Gx.shape[1]
    print("n =", n)
    if len(Lx):
        print("Lx Lz:")
        print(shortstrx(Lx, Lz))
    print("Hx:", len(Hx), "Hz:", len(Hz))
    print("Gx:", len(Gx), "Gz:", len(Gz))

    Rx = [dot2(Px, g) for g in Gx]
    Rx = array2(Rx)

    Rx = row_reduce(Rx, truncate=True)
    rx = len(Rx)
    print("Rx:", rx, "Rz:", rz)
    if argv.show:
        print(shortstrx(Rx, Rz))

    Qx = u_inverse(Rx)
    Pxt = Px.transpose()
    assert eq2(dot2(Rx, Qx), identity2(rx))
    assert eq2(dot2(Rx, Pxt), Rx)

    #print shortstr(dot2(Pxt, Qx))
    PxtQx = dot2(Pxt, Qx)
    lines = [shortstr(dot2(g, PxtQx)) for g in Gx]
    lines.sort()
    #print "PxtQx:"
    #for s in lines:
    #    print s
    #print "RzRxt"
    #print shortstr(dot2(Rz, Rx.transpose()))

    offset = argv.offset

    if len(Hz):
        Tx = find_errors(Hz, Lz, Rz)
    else:
        Tx = zeros2(0, n)

    if argv.dense:
        dense(**locals())
        return

    if argv.dense_full:
        dense_full(**locals())
        return

    if argv.show_delta:
        show_delta(**locals())
        return

    if argv.slepc:
        slepc(**locals())
        return

#    if argv.orbigraph:
#        from linear import orbigraph
#        orbigraph(**locals())
#        return

    v0 = None

#    excite = argv.excite
#    if excite is not None:
#        v0 = zeros2(n)
#        v0[excite] = 1

    verts = []
    lookup = {}
    for i, v in enumerate(span(Rx)): # XXX does not scale well
        if v0 is not None:
            v = (v+v0)%2
            v = dot2(Px, v)
        lookup[v.tobytes()] = i
        verts.append(v)
    print("span:", len(verts))
    assert len(lookup) == len(verts)

    mz = len(Gz)
    n = len(verts)

    if argv.lie:
        U = []
        for i, v in enumerate(verts):
            count = dot2(Gz, v).sum()
            Pxv = dot2(Px, v)
            assert count == dot2(Gz, Pxv).sum()
            U.append(mz - 2*count)
        uniq = list(set(U))
        uniq.sort(reverse=True)
        s = ', '.join("%d(%d)"%(val, U.count(val)) for val in uniq)
        print(s)
        print("sum:", sum(U))
        return
        

    if n <= 1024 and argv.solve:
        H = numpy.zeros((n, n))
        syndromes = []
        for i, v in enumerate(verts):
            syndromes.append(dot2(Gz, v))
            count = dot2(Gz, v).sum()
            Pxv = dot2(Px, v)
            assert count == dot2(Gz, Pxv).sum()
            H[i, i] = mz - 2*count
            for g in Gx:
                v1 = (g+v)%2
                v1 = dot2(Px, v1)
                j = lookup[v1.tobytes()]
                H[i, j] += 1
    
        if argv.showham:
            s = lstr2(H, 0).replace(',  ', ' ')
            s = s.replace(' 0', ' .')
            s = s.replace(', -', '-')
            print(s)
    
        vals, vecs = numpy.linalg.eigh(H)
        show_eigs(vals)

        if argv.show_partition:
            beta = argv.get("beta", 1.0)
            show_partition(vals, beta)

        if argv.orbigraph:
            if argv.symplectic:
                H1 = build_orbigraph(H, syndromes)
            else:
                H1 = build_orbigraph(H)
            print("orbigraph:")
            print(H1)
            vals, vecs = numpy.linalg.eig(H1)
            show_eigs(vals)

    elif argv.sparse:
        print("building H", end=' ')
        A = {} # adjacency
        U = [] # potential

        if offset is None:
            offset = mz + 1 # make H positive definite

        for i, v in enumerate(verts):
            if i%1000==0:
                write('.')
            count = dot2(Gz, v).sum()
            #H[i, i] = mz - 2*count
            U.append(offset + mz - 2*count)
            for g in Gx:
                v1 = (g+v)%2
                v1 = dot2(Px, v1)
                j = lookup[v1.tobytes()]
                A[i, j] = A.get((i, j), 0) + 1
    
        print("\nnnz:", len(A))

        if argv.lanczos:
            vals, vecs = do_lanczos(A, U)

        elif argv.orbigraph:
            vals, vecs = do_orbigraph(A, U)

        else:
            return

        vals -= offset # offset doesn't change vecs

        show_eigs(vals)

    elif argv.orbigraph:

        assert n<=1024

        H = numpy.zeros((n, n))
        syndromes = []
        for i, v in enumerate(verts):
            syndromes.append(dot2(Gz, v))
            count = dot2(Gz, v).sum()
            Pxv = dot2(Px, v)
            assert count == dot2(Gz, Pxv).sum()
            H[i, i] = mz - 2*count
            for g in Gx:
                v1 = (g+v)%2
                v1 = dot2(Px, v1)
                j = lookup[v1.tobytes()]
                H[i, j] += 1
    
        if argv.showham:
            s = lstr2(H, 0).replace(',  ', ' ')
            s = s.replace(' 0', ' .')
            s = s.replace(', -', '-')
            print(s)
    
        if argv.symplectic:
            H1 = build_orbigraph(H, syndromes)
        else:
            H1 = build_orbigraph(H)
Example #19
0
def hpack(n, j=4, k=1, check=True, verbose=False):

    write("hpack...")

    U = identity2(n) # upper triangular
    L = identity2(n) # lower triangular
    I = identity2(n)

    for count in range(j*n):

        i = randint(0, n-1)
        j = randint(0, n-1)
        if i==j:
            continue

        U[i] = (U[i] + U[j])%2
        L[j] = (L[j] - L[i])%2

    assert solve.rank(U) == n
    assert solve.rank(L) == n

    assert eq2(dot2(U, L.transpose()), I)

    if verbose:
        print()
        print(shortstrx(U, L))
        print()

    ws = [n] * n
    ws = stabweights(U, L)

    for i in range(n):
        w = min(U[i].sum(), L[i].sum())
        ws[i] = min(ws[i], w)
    ws = list(enumerate(ws))
    ws.sort(key = lambda item : -item[1])

    idxs = [ws[i][0] for i in range(k)]
    idxs.sort()

    Lx, Lz = zeros2(0, n), zeros2(0, n)

    for idx in reversed(idxs):

        Lz = append2(Lz, U[idx:idx+1])
        Lx = append2(Lx, L[idx:idx+1])
        U = pop2(U, idx)
        L = pop2(L, idx)

    m = (n-k)//2
    Hz, Tz = U[:m], U[m:]
    Tx, Hx = L[:m], L[m:]

    if verbose:
        print()
        print(shortstrx(Hx, Hz))

    write("done.\n")

    code = CSSCode(Lx, Lz, Hx, Tz, Hz, Tx, check=check, verbose=verbose)

    return code
Example #20
0
    def build_from_gauge(self, check=True, verbose=False):

        write("build_from_gauge:")

        Gx, Gz = self.Gx, self.Gz
        Hx, Hz = self.Hx, self.Hz
        Lx, Lz = self.Lx, self.Lz

        #print "build_stab"
        #print shortstr(Gx)
        #vs = solve.find_kernel(Gx)
        #vs = list(vs)
        #print "kernel Gx:", len(vs)
    
        n = Gx.shape[1]
    
        if Hz is None:
            A = dot2(Gx, Gz.transpose())
            vs = solve.find_kernel(A)
            vs = list(vs)
            #print "kernel GxGz^T:", len(vs)
            Hz = zeros2(len(vs), n)
            for i, v in enumerate(vs):
                Hz[i] = dot2(v.transpose(), Gz) 
        Hz = solve.linear_independent(Hz)
    
        if Hx is None:
            A = dot2(Gz, Gx.transpose())
            vs = solve.find_kernel(A)
            vs = list(vs)
            Hx = zeros2(len(vs), n)
            for i, v in enumerate(vs):
                Hx[i] = dot2(v.transpose(), Gx)
        Hx = solve.linear_independent(Hx)

        if check:
            check_commute(Hz, Hx)
            check_commute(Hz, Gx)
            check_commute(Hx, Gz)

        #Gxr = numpy.concatenate((Hx, Gx))
        #Gxr = solve.linear_independent(Gxr)
        #print(Hx.shape)
        #assert rank(Hx) == len(Hx)
        #assert eq2(Gxr[:len(Hx)], Hx)
        #Gxr = Gxr[len(Hx):]

        Px = solve.get_reductor(Hx).transpose()
        Gxr = dot2(Gx, Px)
        Gxr = solve.linear_independent(Gxr)
    
        #Gzr = numpy.concatenate((Hz, Gz))
        #Gzr = solve.linear_independent(Gzr)
        #assert eq2(Gzr[:len(Hz)], Hz)
        #Gzr = Gzr[len(Hz):]

        Pz = solve.get_reductor(Hz).transpose()
        Gzr = dot2(Gz, Pz)
        Gzr = solve.linear_independent(Gzr)
    
        if Lx is None:
            Lx = solve.find_logops(Gz, Hx)
        if Lz is None:
            Lz = solve.find_logops(Gx, Hz)

        write('\n')

        print("Gxr", Gxr.shape)
        print("Gzr", Gzr.shape)
        assert len(Gxr)==len(Gzr)
        kr = len(Gxr)
        V = dot2(Gxr, Gzr.transpose())
        U = solve.solve(V, identity2(kr))
        assert U is not None
        Gzr = dot2(U.transpose(), Gzr)

        if check:
            check_conjugate(Gxr, Gzr)
            check_commute(Hz, Gxr)
            check_commute(Hx, Gzr)
            check_commute(Lz, Gxr)
            check_commute(Lx, Gzr)

        assert len(Lx)+len(Hx)+len(Hz)+len(Gxr)==n

        self.Lx, self.Lz = Lx, Lz
        self.Hx, self.Hz = Hx, Hz
        self.Gxr, self.Gzr = Gxr, Gzr
Example #21
0
def test():

    n = 3
    F = symplectic_form(n)
    I = identity2(2 * n)
    assert numpy.alltrue(I == dot2(F, F))

    # --------------------------------------------
    # Clifford group order is 24

    n = 1
    I = Clifford.identity(n)

    X = Clifford.x(n, 0)
    Z = Clifford.z(n, 0)
    S = Clifford.s(n, 0)
    Si = S.inverse()
    H = Clifford.hadamard(n, 0)
    Y = X * Z

    print("X =")
    print(X)
    print("Z =")
    print(Z)
    print("S =")
    print(S)
    print("Si =")
    print(Si)
    print()

    assert X != I
    assert Z != I
    assert X * X == I
    assert Z * Z == I
    assert Z * X == X * Z  # looses the phase

    assert Si * S == S * Si == I
    assert Si * Si == Z
    assert S * Z == Z * S
    assert S * X == Y * S
    assert S * Y * Si == X
    assert S * S == Z
    assert S * X != X * S
    assert S * S * S * S == I
    assert S * S * S == Si

    assert H * H == I
    assert H * X * H == Z
    assert H * Z * H == X

    assert S * H * S * H * S * H == I

    G = mulclose_fast([S, H])
    assert len(G) == 24

    #    # --------------------------------------------
    #    # Look for group central extension
    #
    #    G = list(G)
    #    G.sort()
    #    P = [g for g in G if g.is_translation()] # Pauli group
    #    N = len(G)
    #    lookup = dict((g, idx) for (idx, g) in enumerate(G))
    #    coord = lambda g, h : lookup[h] + N*lookup[g]
    #    #phi = numpy.zeros((N, N), dtype=int)
    #
    #    phi = {}
    #    for g in P:
    #      for h in P:
    #        phi[g, h] = 0
    #
    #    pairs = [(g, h) for g in G for h in G]
    #    triples = [(g, h, k) for g in G for h in G for k in G]
    #    done = False
    #    while not done:
    #      done = True
    #      print(len([phi.get(k) for k in pairs if phi.get(k) is None]))
    #      for (g, h, k) in triples:
    #        vals = [
    #            phi.get((g, h)),
    #            phi.get((h, k)),
    #            phi.get((g, h*k)),
    #            phi.get((g*h, k))]
    #        if vals.count(None) == 1:
    #            phi[g, h] = 0
    #            phi[h, k] = 0
    #            phi[g, h*k] = 0
    #            phi[g*h, k] = 0
    #            done = False
    #    print(len([phi.get(k) for k in pairs if phi.get(k) is None]))
    #    print(len(phi))
    #    print(len(pairs))
    #
    #    return

    # --------------------------------------------
    # Clifford group order is 11520

    n = 2
    II = Clifford.identity(n)

    XI = Clifford.x(n, 0)
    IX = Clifford.x(n, 1)
    ZI = Clifford.z(n, 0)
    IZ = Clifford.z(n, 1)
    SI = Clifford.s(n, 0)
    IS = Clifford.s(n, 1)
    SS = SI * IS
    HI = Clifford.hadamard(n, 0)
    IH = Clifford.hadamard(n, 1)
    XX = XI * IX
    ZZ = ZI * IZ
    XZ = XI * IZ
    ZX = IX * ZI
    YI = XI * ZI
    IY = IX * IZ
    YY = YI * IY
    XY = XI * IY
    YX = IX * YI
    ZY = ZI * IY
    YZ = IZ * YI

    CX = Clifford.cnot(n, 0, 1)
    CX1 = Clifford.cnot(n, 1, 0)
    CZ = Clifford.cz(n, 0, 1)
    CZ1 = Clifford.cz(n, 1, 0)

    print("CZ =")
    print(CZ)

    print("CX =")
    print(CX)

    assert SI * SI == ZI

    assert SI * ZI == ZI * SI
    assert SI * XI != XI * SI
    assert SI * SI * SI * SI == II

    assert CX * CX == II
    assert CZ * CZ == II
    assert CZ1 == CZ

    assert CX * IX == IX * CX
    assert CX * XI * CX == XX

    assert CX * ZI == ZI * CX
    assert CX * IZ * CX == ZZ

    SWAP = Clifford.swap(n, 0, 1)
    assert SWAP * ZI == IZ * SWAP
    assert SWAP * XI == IX * SWAP

    assert CX * CX1 * CX == SWAP

    assert CZ == IH * CX * IH

    assert CZ * ZI == ZI * CZ
    assert CZ * IZ == IZ * CZ

    assert CZ * XI * CZ == XI * IZ
    assert CZ * IX * CZ == IX * ZI

    assert CX * IZ * CX == ZZ
    assert CX * ZZ * CX == IZ
    assert CX * XI * CX == XX
    assert CZ * XX * CZ == YY
    assert CX * XZ * CX == YY

    assert CX * CZ == CZ * CX
    print("CX * CZ =")
    print(CX * CZ)

    #print(CX*CX1)
    #print()
    #print(SWAP)

    G = mulclose_fast([SI, IS, CX, HI, IH])
    assert len(G) == 11520

    for g in G:
        assert g.check()
        h = g.inverse()
        assert h.check()
        assert g * h == II

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

    n = 5
    I = Clifford.identity(n)
    CZ = Clifford.cz(n, 0, 1)
    SWAP = Clifford.swap(n, 0, 1)
    assert CZ * CZ == I
    assert SWAP * CZ == CZ * SWAP
Example #22
0
def hypergraph_product(C, D, check=False):
    print("hypergraph_product: C=%s, D=%s" % (C.shape, D.shape))

    c0, c1 = C.shape
    d0, d1 = D.shape

    Ic0 = identity2(c0)
    Id0 = identity2(d0)
    Ic1 = identity2(c1)
    Id1 = identity2(d1)

    Hz0 = kron(Ic1, D.transpose()), kron(C.transpose(), Id1)
    Hz = numpy.concatenate(Hz0, axis=1)  # horizontal concatenate

    Hx0 = kron(C, Id0), kron(Ic0, D)
    #print("Hx0:", Hx0[0].shape, Hx0[1].shape)
    Hx = numpy.concatenate(Hx0, axis=1)  # horizontal concatenate

    assert dot2(Hx, Hz.transpose()).sum() == 0

    n = Hz.shape[1]
    assert Hx.shape[1] == n

    # ---------------------------------------------------
    # Build Lz

    KerC = find_kernel(C)
    #KerC = min_span(KerC) # does not seem to matter... ??
    KerC = rand_span(KerC)  # ??
    KerC = row_reduce(KerC)

    assert KerC.shape[1] == c1
    K = KerC.transpose()
    #K = min_span(K)
    #K = rand_span(K)
    #E = identity2(d0)

    #print("c0,c1,d0,d1=", c0, c1, d0, d1)

    Lzt0 = kron(K, Id0), zeros2(c0 * d1, K.shape[1] * d0)
    Lzt0 = numpy.concatenate(Lzt0, axis=0)
    assert dot2(Hx, Lzt0).sum() == 0

    KerD = find_kernel(D)
    K = KerD.transpose()
    assert K.shape[0] == d1

    Lzt1 = zeros2(c1 * d0, K.shape[1] * c0), kron(Ic0, K)
    Lzt1 = numpy.concatenate(Lzt1, axis=0)
    assert dot2(Hx, Lzt1).sum() == 0

    Lzt = numpy.concatenate((Lzt0, Lzt1), axis=1)  # horizontal concatenate
    Lz = Lzt.transpose()

    assert dot2(Hx, Lzt).sum() == 0

    # These are linearly independent among themselves, but
    # once we add stabilixers it will be reduced:
    assert rank(Lz) == len(Lz)

    # ---------------------------------------------------
    # Build Lx

    counit = lambda n: unit2(n).transpose()

    CokerD = find_cokernel(D)  # matrix of row vectors
    #CokerD = min_span(CokerD)
    CokerD = rand_span(CokerD)

    Lx0 = kron(Ic1, CokerD), zeros2(CokerD.shape[0] * c1, c0 * d1)
    Lx0 = numpy.concatenate(Lx0, axis=1)  # horizontal concatenate

    assert dot2(Lx0, Hz.transpose()).sum() == 0

    CokerC = find_cokernel(C)
    Lx1 = zeros2(CokerC.shape[0] * d1, c1 * d0), kron(CokerC, Id1)
    Lx1 = numpy.concatenate(Lx1, axis=1)  # horizontal concatenate

    Lx = numpy.concatenate((Lx0, Lx1), axis=0)

    assert dot2(Lx, Hz.transpose()).sum() == 0

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

    overlap = 0
    for lz in Lz:
        for lx in Lx:
            w = (lz * lx).sum()
            overlap = max(overlap, w)
    assert overlap <= 1, overlap
    #print("max overlap:", overlap)

    if 0:
        # here we assume that Hz/Hx are full rank
        Hzi = Hz
        Hxi = Hx
        assert rank(Hz) == len(Hz)
        assert rank(Hx) == len(Hx)
        mz = len(Hz)
        mx = len(Hx)
    else:
        Hzi = remove_dependent(Hz)
        Hxi = remove_dependent(Hx)
        mz = rank(Hz)
        mx = rank(Hx)
        assert len(Hzi) == mz
        assert len(Hxi) == mx

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

    Lz0, Lz1 = Lzt0.transpose(), Lzt1.transpose()

    Lzi = independent_logops(Lz, Hzi)
    Lxi = independent_logops(Lx, Hxi)

    print("Lzi:", len(Lzi))
    print("Lxi:", len(Lxi))

    k = len(Lzi)
    assert len(Lxi) == k
    assert mz + mx + k == n

    LziHz = numpy.concatenate((Lzi, Hzi))
    assert rank(LziHz) == k + mz
    LxiHx = numpy.concatenate((Lxi, Hxi))
    assert rank(LxiHx) == k + mx

    return locals()
Example #23
0
 def is_translation(self):
     n = self.n
     A = self.A
     A = A[:n - 1, :n - 1]
     return numpy.alltrue(A == identity2(n - 1))
Example #24
0
def hypergraph_product(A, B, check=False):
    #print("hypergraph_product: A=%s, B=%s"%(A.shape, B.shape))

    ma, na = A.shape
    mb, nb = B.shape

    Ima = identity2(ma)
    Imb = identity2(mb)
    Ina = identity2(na)
    Inb = identity2(nb)

    Hz0 = kron(Ina, B.transpose()), kron(A.transpose(), Inb)
    Hz = numpy.concatenate(Hz0, axis=1) # horizontal concatenate

    Hx0 = kron(A, Imb), kron(Ima, B)
    #print("Hx0:", Hx0[0].shape, Hx0[1].shape)
    Hx = numpy.concatenate(Hx0, axis=1) # horizontal concatenate

    assert dot2(Hx, Hz.transpose()).sum() == 0

    n = Hz.shape[1]
    assert Hx.shape[1] == n

    # ---------------------------------------------------
    # Build Lz 

    KerA = find_kernel(A)
    #KerA = rand_rowspan(KerA) # ??
    KerA = row_reduce(KerA)
    ka = len(KerA)

    assert KerA.shape[1] == na
    K = KerA.transpose()
    #K = rand_rowspan(K)
    #E = identity2(mb)

    #print("ma,na,mb,nb=", ma, na, mb, nb)

    Lzt0 = kron(K, Imb), zeros2(ma*nb, K.shape[1]*mb)
    Lzt0 = numpy.concatenate(Lzt0, axis=0)
    assert dot2(Hx, Lzt0).sum() == 0

    KerB = find_kernel(B)
    KerB = row_reduce(KerB)
    kb = len(KerB)
    K = KerB.transpose()
    assert K.shape[0] == nb

    Lzt1 = zeros2(na*mb, K.shape[1]*ma), kron(Ima, K)
    Lzt1 = numpy.concatenate(Lzt1, axis=0)
    assert dot2(Hx, Lzt1).sum() == 0

    Lzt = numpy.concatenate((Lzt0, Lzt1), axis=1) # horizontal concatenate
    Lz = Lzt.transpose()

    assert dot2(Hx, Lzt).sum() == 0

    # These are linearly independent among themselves, but 
    # once we add stabilizers it will be reduced:
    assert rank(Lz) == len(Lz)

    # ---------------------------------------------------
    # Build Lx 

    counit = lambda n : unit2(n).transpose()

    CokerB = find_cokernel(B) # matrix of row vectors
    #CokerB = rand_rowspan(CokerB)
    assert rank(CokerB)==len(CokerB)
    kbt = len(CokerB)

    Lx0 = kron(Ina, CokerB), zeros2(CokerB.shape[0]*na, ma*nb)
    Lx0 = numpy.concatenate(Lx0, axis=1) # horizontal concatenate

    assert dot2(Lx0, Hz.transpose()).sum() == 0

    CokerA = find_cokernel(A)
    assert rank(CokerA)==len(CokerA)
    kat = len(CokerA)

    Lx1 = zeros2(CokerA.shape[0]*nb, na*mb), kron(CokerA, Inb)
    Lx1 = numpy.concatenate(Lx1, axis=1) # horizontal concatenate

    Lx = numpy.concatenate((Lx0, Lx1), axis=0)

    assert dot2(Lx, Hz.transpose()).sum() == 0

    #print(ka, kat, kb, kbt)

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

    overlap = 0
    for lz in Lz:
      for lx in Lx:
        w = (lz*lx).sum()
        overlap = max(overlap, w)
    assert overlap <= 1, overlap
    #print("max overlap:", overlap)

    if 0:
        # here we assume that Hz/Hx are full rank
        Hzi = Hz
        Hxi = Hx
        assert rank(Hz) == len(Hz)
        assert rank(Hx) == len(Hx)
        mz = len(Hz)
        mx = len(Hx)
    else:
        Hzi = remove_dependent(Hz)
        Hxi = remove_dependent(Hx)
        mz = rank(Hz)
        mx = rank(Hx)
        assert len(Hzi) == mz
        assert len(Hxi) == mx


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

    Lz0, Lz1 = Lzt0.transpose(), Lzt1.transpose()

    Lzi = independent_logops(Lz, Hzi)
    Lxi = independent_logops(Lx, Hxi)

    #print("Lzi:", len(Lzi))
    #print("Lxi:", len(Lxi))

    k = len(Lzi)
    assert len(Lxi) == k
    assert mz + mx + k == n

    LziHz = numpy.concatenate((Lzi, Hzi))
    assert rank(LziHz) == k+mz
    LxiHx = numpy.concatenate((Lxi, Hxi))
    assert rank(LxiHx) == k+mx

    return locals()
Example #25
0
    def build(self, logops_only=False, check=True, verbose=False):
    
        Hx, Hz = self.Hx, self.Hz
        Lx, Lz = self.Lx, self.Lz
        Tx, Tz = self.Tx, self.Tz

        if verbose:
            _write = write
        else:
            _write = lambda *args : None
    
        _write('li:')
        self.Hx = Hx = solve.linear_independent(Hx)
        self.Hz = Hz = solve.linear_independent(Hz)
    
        mz, n = Hz.shape
        mx, nx = Hx.shape
        assert n==nx
        assert mz+mx<=n, (mz, mx, n)
    
        _write('build:')
    
        if check:
            # check kernel of Hx contains image of Hz^t
            check_commute(Hx, Hz)
    
        if Lz is None:
            _write('find_logops(Lz):')
            Lz = solve.find_logops(Hx, Hz, verbose=verbose)
            #print shortstr(Lz)
            #_write(len(Lz))

        k = len(Lz)
        assert n-mz-mx==k, "_should be %d logops, found %d. Is Hx/z degenerate?"%(
            n-mx-mz, k)

        _write("n=%d, mx=%d, mz=%d, k=%d\n" % (n, mx, mz, k))
    
        # Find Lx --------------------------
        if Lx is None:
            _write('find_logops(Lx):')
            Lx = solve.find_logops(Hz, Hx, verbose=verbose)

        assert len(Lx)==k

        if check:
            check_commute(Lx, Hz)
            check_commute(Lz, Hx)


        U = dot2(Lz, Lx.transpose())
        I = identity2(k)
        A = solve.solve(U, I)
        assert A is not None, "problem with logops: %s"%(U,)
        #assert eq2(dot2(U, A), I)
        #assert eq2(dot2(Lz, Lx.transpose(), A), I)

        Lx = dot2(A.transpose(), Lx)

        if check:
            check_conjugate(Lz, Lx)

        if not logops_only:

            # Find Tz --------------------------
            _write('Find(Tz):')
            U = zeros2(mx+k, n)
            U[:mx] = Hx
            U[mx:] = Lx
            B = zeros2(mx+k, mx)
            B[:mx] = identity2(mx)
    
            Tz_t = solve.solve(U, B)
            Tz = Tz_t.transpose()
            assert len(Tz) == mx
    
            check_conjugate(Hx, Tz)
            check_commute(Lx, Tz)
    
            # Find Tx --------------------------
            _write('Find(Tx):')
            U = zeros2(n, n)
            U[:mz] = Hz
            U[mz:mz+k] = Lz
            U[mz+k:] = Tz
    
            B = zeros2(n, mz)
            B[:mz] = identity2(mz)
            Tx_t = solve.solve(U, B)
            Tx = Tx_t.transpose()
    
            _write('\n')
        
            if check:
                check_conjugate(Hz, Tx)
                check_commute(Lz, Tx)
                check_commute(Tz, Tx)

        self.k = k
        self.Lx = Lx
        self.Lz = Lz
        self.Tz = Tz
        self.Tx = Tx
Example #26
0
def hypergraph_product(C, D, check=False):
    print("hypergraph_product:", C.shape, D.shape)
    print("distance:", classical_distance(C))

    c0, c1 = C.shape
    d0, d1 = D.shape

    E1 = identity2(c0)
    E2 = identity2(d0)
    M1 = identity2(c1)
    M2 = identity2(d1)

    Hx0 = kron(M1, D.transpose()), kron(C.transpose(), M2)
    Hx = numpy.concatenate(Hx0, axis=1)  # horizontal concatenate

    Hz0 = kron(C, E2), kron(E1, D)
    #print("Hz0:", Hz0[0].shape, Hz0[1].shape)
    Hz = numpy.concatenate(Hz0, axis=1)  # horizontal concatenate

    assert dot2(Hz, Hx.transpose()).sum() == 0

    n = Hx.shape[1]
    assert Hz.shape[1] == n

    # ---------------------------------------------------
    # Build Lx

    KerC = find_kernel(C)
    #KerC = min_span(KerC) # does not seem to matter... ??
    assert KerC.shape[1] == c1
    K = KerC.transpose()
    E = identity2(d0)

    print(shortstr(KerC))
    print()

    Lxt0 = kron(K, E), zeros2(c0 * d1, K.shape[1] * d0)
    Lxt0 = numpy.concatenate(Lxt0, axis=0)
    assert dot2(Hz, Lxt0).sum() == 0

    K = find_kernel(D).transpose()
    assert K.shape[0] == d1
    E = identity2(c0)

    Lxt1 = zeros2(c1 * d0, K.shape[1] * c0), kron(E, K)
    Lxt1 = numpy.concatenate(Lxt1, axis=0)
    assert dot2(Hz, Lxt1).sum() == 0

    Lxt = numpy.concatenate((Lxt0, Lxt1), axis=1)  # horizontal concatenate
    Lx = Lxt.transpose()

    assert dot2(Hz, Lxt).sum() == 0

    # These are linearly dependent, but
    # once we add stabilizers it will be reduced:
    assert rank(Lx) == len(Lx)

    if 0:
        # ---------------------------------------------------

        print(shortstr(Lx))
        k = get_k(Lx, Hx)
        print("k =", k)

        left, right = [], []

        draw = Draw(c0, c1, d0, d1)
        cols = []
        for j in range(d0):  # col
            col = []
            for i in range(len(KerC)):  # logical
                op = Lx[i * d0 + j]
                col.append(op)
                if j == i:
                    draw.mark_xop(op)
                if j < d0 / 2:
                    left.append(op)
                else:
                    right.append(op)
            cols.append(col)

        draw.save("output.2")

        left = array2(left)
        right = array2(right)

        print(get_k(left, Hx))
        print(get_k(right, Hx))

        return

    # ---------------------------------------------------
    # Build Lz

    counit = lambda n: unit2(n).transpose()

    K = find_cokernel(D)  # matrix of row vectors
    #E = counit(c1)
    E = identity2(c1)
    Lz0 = kron(E, K), zeros2(K.shape[0] * c1, c0 * d1)
    Lz0 = numpy.concatenate(Lz0, axis=1)  # horizontal concatenate

    assert dot2(Lz0, Hx.transpose()).sum() == 0

    K = find_cokernel(C)
    #E = counit(d1)
    E = identity2(d1)
    Lz1 = zeros2(K.shape[0] * d1, c1 * d0), kron(K, E)
    Lz1 = numpy.concatenate(Lz1, axis=1)  # horizontal concatenate

    Lz = numpy.concatenate((Lz0, Lz1), axis=0)

    assert dot2(Lz, Hx.transpose()).sum() == 0

    overlap = 0
    for lx in Lx:
        for lz in Lz:
            w = (lx * lz).sum()
            overlap = max(overlap, w)
    assert overlap <= 1, overlap
    #print("max overlap:", overlap)

    assert rank(Hx) == len(Hx)
    assert rank(Hz) == len(Hz)
    mx = len(Hx)
    mz = len(Hz)

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

    Lxs = []
    for op in Lx:
        op = (op + Hx) % 2
        Lxs.append(op)
    LxHx = numpy.concatenate(Lxs)
    LxHx = row_reduce(LxHx)
    print("LxHx:", len(LxHx))
    assert LxHx.shape[1] == n
    print(len(intersect(LxHx, Hx)), mx)
    assert len(intersect(LxHx, Hx)) == mx

    Lzs = []
    for op in Lz:
        op = (op + Hz) % 2
        Lzs.append(op)
    LzHz = numpy.concatenate(Lzs)
    LzHz = row_reduce(LzHz)
    print("LzHz:", len(LzHz))
    assert LzHz.shape[1] == n

    # ---------------------------------------------------
    # Remove excess logops.

    #    print("remove_dependent")
    #
    #    # -------- Lx
    #
    #    Lx, Lx1 = mk_disjoint_logops(Lx, Hx)
    #
    #    # -------- Lz
    #
    #    Lz, Lz1 = mk_disjoint_logops(Lz, Hz)

    # --------------------------------
    # independent_logops for Lx

    k = get_k(Lx, Hx)

    idxs0, idxs1 = [], []

    for j in range(d0):  # col
        for i in range(c1):
            idx = j + i * d0
            if j < d0 // 2:
                idxs0.append(idx)
            else:
                idxs1.append(idx)

    Lx0 = in_support(LxHx, idxs0)
    Lx0 = independent_logops(Lx0, Hx)
    k0 = (len(Lx0))

    Lx1 = in_support(LxHx, idxs1)
    Lx1 = independent_logops(Lx1, Hx)
    k1 = (len(Lx1))
    assert k0 == k1 == k, (k0, k1, k)

    # --------------------------------
    # independent_logops for Lz

    idxs0, idxs1 = [], []

    for j in range(d0):  # col
        for i in range(c1):
            idx = j + i * d0
            if i < c1 // 2:
                idxs0.append(idx)
            else:
                idxs1.append(idx)

    Lz0 = in_support(LzHz, idxs0)
    Lz0 = independent_logops(Lz0, Hz)
    k0 = (len(Lz0))

    Lz1 = in_support(LzHz, idxs1)
    Lz1 = independent_logops(Lz1, Hz)
    k1 = (len(Lz1))
    assert k0 == k1 == k, (k0, k1, k)

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

    #assert eq2(dot2(Lz, Lxt), identity2(k))
    assert mx + mz + k == n

    print("mx = %d, mz = %d, k = %d : n = %d" % (mx, mz, k, n))

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

    #    if Lx1 is None:
    #        return
    #
    #    if Lz1 is None:
    #        return

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

    op = zeros2(n)
    for lx in Lx0:
        for lz in Lz0:
            lxz = lx * lz
            #print(lxz)
            #print(op.shape, lxz.shape)
            op += lxz

    for lx in Lx1:
        for lz in Lz1:
            lxz = lx * lz
            #print(lxz)
            #print(op.shape, lxz.shape)
            op += lxz

    idxs = numpy.where(op)[0]
    print("correctable region size = %d" % len(idxs))
    #print(op)
    #print(idxs)

    Lx, Lz = Lx0, Lz0

    Lxs = []
    for op in Lx:
        op = (op + Hx) % 2
        Lxs.append(op)
    LxHx = numpy.concatenate(Lxs)
    LxHx = row_reduce(LxHx)
    assert LxHx.shape[1] == n

    Lzs = []
    for op in Lz:
        op = (op + Hz) % 2
        Lzs.append(op)
    LzHz = numpy.concatenate(Lzs)
    LzHz = row_reduce(LzHz)
    assert LzHz.shape[1] == n

    if argv.draw:
        do_draw(**locals())

    good = is_correctable(n, idxs, LxHx, LzHz)
    assert good

    print("good")

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

    if argv.code:
        print("code = CSSCode()")
        code = CSSCode(Hx=Hx,
                       Hz=Hz,
                       Lx=Lx,
                       Lz=Lz,
                       check=True,
                       verbose=False,
                       build=True)
        print(code)
        #print(code.weightstr())

        if check:
            U = solve(Lx.transpose(), code.Lx.transpose())
            assert U is not None
            #print(U.shape)
            assert eq2(dot2(U.transpose(), Lx), code.Lx)
            #print(shortstr(U))

        if 0:
            Lx, Lz = code.Lx, code.Lz
            print("Lx:", Lx.shape)
            print(shortstr(Lx))
            print("Lz:", Lz.shape)
            print(shortstr(Lz))
Example #27
0
def test(A, B, ma, na, mb, nb, Ina, Ima, Inb, Imb, ka, kb, kat, kbt, k,
    KerA, KerB, CokerA, CokerB,
    Lzi, Lxi, Hzi, Hxi,
    **kw):

    #print("ka=%s, kat=%s, kb=%s, kbt=%s"%(ka, kat, kb, kbt))
    assert k == ka*kbt + kat*kb == len(Lzi) == len(Lxi)

    KerA = KerA.transpose() # use convention in paper
    KerB = KerB.transpose() # use convention in paper
    CokerA = CokerA.transpose() # use convention in paper
    CokerB = CokerB.transpose() # use convention in paper

    blocks = [
        [kron(KerA, Imb), zeros2(na*mb, ma*kb), kron(Ina, B)],
        [zeros2(ma*nb, ka*mb), kron(Ima, KerB), kron(A,Inb)],
    ]
    print("blocks:", [[X.shape for X in row] for row in blocks])

    #print(shortstrx(*blocks[0]))
    #print()
    #print(shortstrx(*blocks[1]))

    Hzt = cat((blocks[0][2], blocks[1][2]), axis=0)
    K = find_kernel(Hzt)
    assert len(K) == ka*kb # see proof of Lemma 3

    Lzv = cat((blocks[0][0], blocks[1][0])).transpose()
    Lzh = cat((blocks[0][1], blocks[1][1])).transpose()
    assert dot2(Hxi, Lzv.transpose()).sum() == 0

#    Hz = Hzt.transpose()
#    Hzi = linear_independent(Hz)
#    Lzhi = independent_logops(Lzh, Hzi, verbose=True)
#    print("Lzhi:", Lzhi.shape)

    # --------------------------------------------------------
    # basis for all logops, including stabilizers
    lz = find_kernel(Hxi) # returns transpose of kernel
    #lz = rand_rowspan(lz)
    #print("lz:", lz.shape)
    assert len(lz) == k+len(Hzi)

    # vertical qubits
    Iv = cat((identity2(na*mb), zeros2(ma*nb, na*mb)), axis=0).transpose()
    # horizontal qubits
    Ih = cat((zeros2(na*mb, ma*nb), identity2(ma*nb)), axis=0).transpose()
    assert len(intersect(Iv, Ih))==0 # sanity check

    # now restrict these logops to vertical qubits
    #print("Iv:", Iv.shape)
    lzv = intersect(Iv, lz)
    #print("lzv:", lzv.shape)

    J = intersect(lzv, Lzv)
    assert len(J) == len(lzv)

    # --------------------------------------------------------
    # now we manually build _lz supported on vertical qubits
    x = rand2(ka*mb, ka*nb)
    y = kron(KerA, Inb)
    assert eq2(dot2(blocks[0][2], y), kron(KerA, B))
    v = (dot2(blocks[0][0], x) + dot2(blocks[0][2], y)) % 2
    h = zeros2(ma*nb, v.shape[1])
    _lzt = cat((v, h))
    assert dot2(Hxi, _lzt).sum() == 0
    #print(shortstr(_lzt))
    _lz = _lzt.transpose()
    _lz = linear_independent(_lz)

    #print("*"*(na*mb))
    #print(shortstr(_lz))
    assert len(intersect(_lz, Ih)) == 0
    assert len(intersect(_lz, Iv)) == len(_lz)

    J = intersect(_lz, lz)
    assert len(J) == len(_lz)

    J = intersect(_lz, Lzv)
    #print(J.shape, _lz.shape, Lzv.shape)
    assert len(J) == len(_lz)

    if 0:
        V = cat(blocks[0][:2], axis=1)
        H = cat(blocks[1][:2], axis=1)
        X = cat((V, H), axis=0)
        K = find_kernel(X)
        print(K.shape)
    
        V = cat(blocks[0], axis=1)
        H = cat(blocks[1], axis=1)
        X = cat((V, H), axis=0)
        K = find_kernel(X)
        print(K.shape)
    
        #print("-"*(ka*mb+ma*kb))
        I = cat((identity2(ka*mb+ma*kb), zeros2(ka*mb+ma*kb, na*nb)), axis=1)
        J = intersect(K, I)
        print("J:", J.shape)