Example #1
0
def pushout(a, b, _amorph=None, _bmorph=None, _chain=None, check=True):
    """
        Construct pushout of Morphism's a, b.
        If supplied with another cocone over a, b then
        also construct unique Morphism to that cocone.
    """
    assert isinstance(a, Morphism)
    assert isinstance(b, Morphism)
    assert a.src == b.src

    src = a.src
    n = len(src)
    amorph = []
    bmorph = []
    chain = []
    aprev = None
    bprev = None
    for i in range(n + 1):
        a1, b1, c1 = solve.pushout(a[i], b[i], aprev, bprev)
        amorph.append(a1)
        bmorph.append(b1)
        chain.append(c1)
        aprev = compose2(a.tgt[i], a1)
        bprev = compose2(b.tgt[i], b1)
        #_a1, _b1, _ = solve.pushout(a[i], b[i])
        #assert eq2(a1, _a1)
        #assert eq2(b1, _b1)
    chain = Chain(chain[1:])
    amorph = Morphism(a.tgt, chain, amorph)
    bmorph = Morphism(b.tgt, chain, bmorph)
    if check:
        assert amorph * a == bmorph * b
    assert (_amorph is None) == (_bmorph is None) == (_chain is None)
    morph = None
    if _amorph is not None:
        assert amorph.tgt == bmorph.tgt
        assert _amorph * a == _bmorph * b, "not a cocone!"
        Ds = []
        for i in range(n + 1):
            a1, b1, d = solve.pushout(a[i], b[i], _amorph[i], _bmorph[i])
            Ds.append(d)
            assert eq2(dot2(d, a1), _amorph[i])
            assert eq2(dot2(d, b1), _bmorph[i])
            assert eq2(a1, amorph[i])
            assert eq2(b1, bmorph[i])
        morph = Morphism(chain, _chain, Ds)
        if check:
            #lhs = morph * amorph
            #rhs = _amorph
            #print(lhs.shape)
            #print(rhs.shape)
            assert morph * amorph == _amorph
            assert morph * bmorph == _bmorph

    return amorph, bmorph, chain, morph
Example #2
0
File: glue.py Project: punkdit/qupy
def test_colimit():

    n = 4
    m = n - 1
    H = zeros2(m, n)
    for i in range(m):
        H[i, i] = 1
        H[i, i + 1] = 1

    A = Chain([H])
    B = Chain([zeros2(0, 0)])
    C = Chain([array2([[1]])])

    CAm = zeros2(m, 1)
    CAm[0, 0] = 1
    CAm[m - 1, 0] = 1
    CAn = zeros2(n, 1)
    CAn[0, 0] = 1
    CAn[n - 1, 0] = 1
    CA = Morphism(C, A, [CAm, CAn])

    CBm = zeros2(0, 1)
    CBn = zeros2(0, 1)
    CB = Morphism(C, B, [CBm, CBn])

    AD, BD, D, _ = chain.pushout(CA, CB)
    assert eq2(D[0], array2([[1, 1, 1], [0, 1,
                                         1]]))  # glue two checks at a bit

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

    A = Chain([H.transpose()])
    B = Chain([zeros2(0, 0)])
    C = Chain([zeros2(1, 0)])

    CAn = zeros2(n, 1)
    CAn[0, 0] = 1
    CAn[n - 1, 0] = 1
    CAm = zeros2(m, 0)
    CA = Morphism(C, A, [CAn, CAm])

    CBn = zeros2(0, 1)
    CBm = zeros2(0, 0)
    CB = Morphism(C, B, [CBn, CBm])

    AD, BD, D, _ = chain.pushout(CA, CB)
    D = D[0]
    #print(D)
    assert eq2(D, array2([[1, 0, 1], [1, 1, 0], [0, 1, 1]]))  # glue two bits
Example #3
0
    def is_stab(self, v):
        write('/')
        Hx_t = self.Hx.transpose()

#        # Hx_t u = v
#        # u = Hx_t^-1 v
#        if self.Hx_t_inv is None:
#            Hx_t_inv = solve.pseudo_inverse(Hx_t)
#            self.Hx_t_inv = Hx_t_inv
#        Hx_t_inv = self.Hx_t_inv
#        u = dot2(Hx_t_inv, v)

        u = dot2(self.Tz, v)

        #u = solve.solve(Hx_t, v)
        #if u is not None:
        if eq2(dot2(Hx_t, u), v):
            #print "[%s]"%u.sum(),
            v1 = dot2(Hx_t, u)
            assert ((v+v1)%2).max() == 0
#            assert self.is_stab_0(v) # double check
        else:
#            assert not self.is_stab_0(v) # double check
            u = None
        write('\\')
        return u is not None
Example #4
0
 def show_stabx(self, sx):
     gxs = []
     for gx in self.Gx:
         if eq2(gx * sx, gx):
             gxs.append(gx)
     Gx = array2(gxs)
     #print "Gx:", Gx.shape
     #print shortstr(Gx)
     print("sx.sum() =", sx.sum(), end=' ')
     Gxt = Gx.transpose()
     K = find_kernel(Gxt)
     #print "kernel:", K
     K = array2(K)
     #print "kernel:", len(K)
     #print shortstr(K)
     #print
     best = None
     ubest = None
     u = solve(Gxt, sx)
     for w in enum2(len(K)):
         u2 = (u + dot2(w, K)) % 2
         if best is None or u2.sum() < best:
             best = u2.sum()
             ubest = u2
         print("u.sum() =", u2.sum(), end=' ')
     print()
Example #5
0
File: glue.py Project: punkdit/qupy
def test_equalizer():

    n = 4
    m = n - 1
    H = zeros2(m, n)
    for i in range(m):
        H[i, i] = 1
        H[i, i + 1] = 1

    A = Chain([H])
    C = Chain([array2([[1]])])

    fm = zeros2(m, 1)
    fm[m - 1, 0] = 1
    fn = zeros2(n, 1)
    fn[n - 1, 0] = 1
    f = Morphism(C, A, [fm, fn])

    gm = zeros2(m, 1)
    gm[0, 0] = 1
    gn = zeros2(n, 1)
    gn[0, 0] = 1
    g = Morphism(C, A, [gm, gn])

    AD, BD, D = chain.equalizer(f, g)
    assert eq2(D[0], array2([[1, 1, 1], [0, 1,
                                         1]]))  # glue two checks at a bit

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

    A = Chain([H.transpose()])
    C = Chain([zeros2(1, 0)])

    fn = zeros2(n, 1)
    fn[0, 0] = 1
    fm = zeros2(m, 0)
    f = Morphism(C, A, [fn, fm])

    gn = zeros2(n, 1)
    gn[n - 1, 0] = 1
    gm = zeros2(m, 0)
    g = Morphism(C, A, [gn, gm])

    AD, BD, D = chain.equalizer(f, g)
    D = D[0]
    #print(D)
    assert eq2(D, array2([[1, 0, 1], [1, 1, 0], [0, 1, 1]]))  # glue two bits
Example #6
0
 def __eq__(self, other):
     assert len(self) == len(other)
     if len(self) != len(other):
         return False
     n = len(self)
     for i in range(n):
         if not eq2(self.Hs[i], other.Hs[i]):
             return False
     return True
Example #7
0
 def __eq__(self, other):
     assert isinstance(other, Morphism)
     assert self.shape == other.shape
     if self.shape != other.shape:
         return False
     n = len(self)
     for i in range(n):
         if not eq2(self[i], other[i]):
             return False
     return True
Example #8
0
def independent_logops(L, H):
    m = len(H)
    LH = numpy.concatenate((L, H), axis=0)
    keep, remove = dependent_rows(LH)
    LH = LH[keep]

    assert rank(LH) == len(LH)
    assert len(LH) >= m
    assert eq2(LH[-len(H):], H)
    L = LH[:-m]

    return L
Example #9
0
 def check(self):
     src, tgt = self.src, self.tgt
     Ds = self.Ds
     for i in range(len(src)):
         D0, D1 = Ds[i], Ds[i + 1]
         if D0 is None or D1 is None:
             continue
         lhs, rhs = compose2(src[i], D0), compose2(D1, tgt[i])
         if not eq2(lhs, rhs):
             print("!!!!! Not a chain map !!!!!")
             print("lhs =", lhs)
             print("rhs =", rhs)
             raise Exception
Example #10
0
def independent_logops(L, H, verbose=False):
    m = len(H)
    LH = numpy.concatenate((L, H), axis=0)
    keep, remove = dependent_rows(LH)
    if verbose:
        print(keep, remove)
    LH = LH[keep]
    
    assert rank(LH) == len(LH)
    assert len(LH) >= m
    assert eq2(LH[-len(H):], H), "H not linearly independent ?"
    L = LH[:-m]

    return L
Example #11
0
    def mk_disjoint_logops(L, H):
        m = len(H)
        #print("L:", len(L))

        L0 = L  # save this
        LH = numpy.concatenate((L, H), axis=0)

        #LH = remove_dependent(LH)
        keep, remove = dependent_rows(LH)
        #print("dependent_rows:", len(keep), len(remove))

        LH = LH[keep]

        assert rank(LH) == len(LH)
        assert len(LH) >= m
        assert eq2(LH[-len(H):], H)
        L = LH[:-m]
        #print("L:", len(L))

        # find disjoint set of L ops
        keep = set([idx for idx in keep if idx < len(L0)])
        assert len(keep) == len(L)

        idxs = list(range(len(L0)))
        idxs.sort(key=lambda idx: -int(idx in keep))
        assert idxs[0] in keep
        L1 = L0[idxs]
        assert L1.shape == L0.shape

        LH = numpy.concatenate((L1, H), axis=0)
        LH = remove_dependent(LH)
        L1 = LH[:-m]
        assert len(L) == len(L1), (L.shape, L1.shape)

        #print(shortstr(L))
        #print("--")
        #print(shortstr(L1))

        #print("--")
        A = numpy.dot(L, L1.transpose())
        #assert A.sum() == 0, "found overlap"
        if A.sum():
            print("*" * 79)
            print("WARNING: A.sum() =", A.sum())
            print("failed to find disjoint logops")
            print("*" * 79)
            return L, None

        return L, L1
Example #12
0
    def find_encoding(A, code):
        Lx = [Clifford.make_op(l, Clifford.x) for l in code.Lx]
        Lz = [Clifford.make_op(l, Clifford.z) for l in code.Lz]
        Hx = [Clifford.make_op(l, Clifford.x) for l in code.Hx]
        Hz = [Clifford.make_op(l, Clifford.z) for l in code.Hz]
        assert len(Lx) == len(Lz)
        Ai = A.inverse()
        rows = []
        for l in Lz + Lx:
            B = A * l * Ai
            assert B.is_translation()
            v = B.get_translation()
            rows.append(v)
        B = numpy.array(rows)
        #B = B[:8, :]
        #print(B.shape)
        #print(shortstr(B))
        U = numpy.array([l.get_translation() for l in Lz + Lx + Hz + Hx])
        #print(U.shape)
        #print(shortstr(U))
        Ut = U.transpose()
        V = solve(Ut, B.transpose())
        if V is None:
            return None
        V = V[:2 * code.k]
        #print(V.shape)
        #print(shortstr(V))

        # check that V is symplectic
        n = len(V) // 2
        F = symplectic_form(n)
        lhs = dot2(V.transpose(), dot2(F, V))
        assert eq2(lhs, F)

        #print(A.get_translation())
        u = solve(Ut, A.get_translation())
        u = u[:2 * code.k]
        #print(shortstr(u))

        return Clifford.from_symplectic_and_translation(V, u)
Example #13
0
    def decode(self, p, err_op, verbose=False, **kw):

        code = self.code
        xs, ys = self.xs, self.ys

        x = dot2(code.Hz, err_op)
        x.shape = (1, code.mz)
        a = (self.xs + x) % 2
        #print shortstr(a)

        a = a.sum(1)

        a = list(enumerate(a))
        a.sort(key=lambda item: item[1])
        #        print a

        #        print shortstr(y)
        #        print shortstr(x)

        for idxs in self.search:
            #print idxs
            y1 = ys[a[idxs[0]][0]]
            for idx in idxs[1:]:
                y1 = y1 + ys[a[idx][0]]


#            print shortstr(y1)
            x1 = dot2(code.Hz, y1)
            #print shortstr(x1)
            if eq2(x1, x):
                #                print "OK", idxs
                break
        else:
            return None

        return y1
Example #14
0
def check_conjugate(A, B):
    if A is None or B is None:
        return
    assert A.shape == B.shape
    I = numpy.identity(A.shape[0], dtype=numpy.int32)
    assert eq2(dot2(A, B.transpose()), I)
Example #15
0
def build_model(Gx=None, Gz=None, Hx=None, Hz=None):

    if Gx is None:
        Gx, Gz, Hx, Hz = build()

    n = Gx.shape[1]

    if Hx is None:
        Hx = find_stabilizers(Gz, Gx)
    if Hz is None:
        Hz = find_stabilizers(Gx, Gz)

    check_commute(Hx, Hz)
    check_commute(Gx, Hz)
    check_commute(Hx, Gz)

    #Px = get_reductor(concatenate((Lx, Hx)))
    #Pz = get_reductor(concatenate((Lz, Hz)))
    Px = get_reductor(Hx)
    Pz = get_reductor(Hz)

    # Lz = find_logops( Hx            , Hz            )
    #      find_logops( ............. , ............. )
    #                 ( commutes with , orthogonal to )
    #                 ( ............. , ............. )

    Lz = find_logops(Gx, Hz)
    assert Lz.shape[1] == n

    if 0:
        PGz = get_reductor(Gz)
        Lz = dot2(Lz, PGz.transpose())
        Lz = row_reduce(Lz)

        print(shortstrx(Lz, Gz, Hz))

    if len(Lz):
        #print Lz.shape, Hz.shape
        assert len(row_reduce(concatenate((Lz, Hz)))) == len(Lz) + len(Hz)
        assert len(row_reduce(concatenate(
            (Lz, Gz)))) == len(Lz) + len(row_reduce(Gz))

    # Tz = find_errors( Hx            , Lx            )
    #      find_errors( ............. , ............. )
    #                 ( conjugate to  , commutes with )
    #                 ( ............. , ............. )

    Lx = find_errors(Lz, Gz)  # invert Lz, commuting with Gz

    check_commute(Lx, Gz)
    check_commute(Lx, Hz)
    check_conjugate(Lx, Lz)
    check_commute(Lz, Gx)
    check_commute(Lz, Hx)

    # Lx | Lz
    # Hx | ?
    # ?  | Hz
    # ?  | ?
    #Rz = find_logops(concatenate((Lx, Hx)), Hz)
    Rz = dot2(Gz, Pz.transpose())
    Rz = row_reduce(Rz)

    check_commute(Rz, Lx)
    check_commute(Rz, Hx)

    Rx = dot2(Gx, Px.transpose())
    Rx = row_reduce(Rx)

    check_commute(Rx, Lz)
    check_commute(Rx, Hz)

    # Lx | Lz
    # Hx | ?
    # ?  | Hz
    # Rx'| Rz'

    Tz = find_errors(Hx, concatenate((Lx, Rx)))
    Tx = find_errors(Hz, concatenate((Lz, Rz, Tz)))

    assert len((concatenate((Lx, Hx, Tx, Rx)))) == n
    assert len((concatenate((Lz, Hz, Tz, Rz)))) == n
    assert len(row_reduce(concatenate((Lx, Hx, Tx, Rx)))) == n
    assert len(row_reduce(concatenate((Lz, Hz, Tz, Rz)))) == n

    check_commute(Rz, Tx)

    Rx = find_errors(Rz, concatenate((Lz, Hz, Tz)))

    check_conjugate(Rx, Rz)
    check_commute(Rx, Hz)
    check_commute(Rx, Tz)
    check_commute(Rx, Lz)

    Rxt = Rx.transpose()
    Rzt = Rz.transpose()

    Pxt = Px.transpose()
    Pzt = Pz.transpose()

    check_sy(Lx, Hx, Tx, Rx, Lz, Hz, Tz, Rz)

    assert eq2(dot2(Gz, Rxt), dot2(Gz, Pzt, Rxt))
    assert eq2(dot2(Gx, Rzt), dot2(Gx, Pxt, Rzt))

    #    print shortstrx(dot2(Rx, Pz), Rx)

    assert eq2(dot2(Rx, Pz), Rx)
    assert eq2(dot2(Rz, Px), Rz)

    assert len(find_kernel(dot2(Gz, Rx.transpose()))) == 0

    model = Model(locals())

    if argv.dual:
        model = model.get_dual()
        argv.dual = False  # HACK !!

    return model
Example #16
0
 def __eq__(self, other):
     if self.w != other.w:
         return False  # that was easy
     return eq2(self.T, other.T)
Example #17
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 #18
0
 def __eq__(self, other):
     return eq2(self.Hx, other.Hx) and eq2(self.Hz, other.Hz)
Example #19
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)
Example #20
0
def process(G, H):

    m, n = G.shape
    row = 0
    while row < m:

        col = 0
        while G[row, col] == 0:
            col += 1
        assert col >= row
        swap_col(G, row, col)
        swap_col(H, row, col)
        echelon(G, row, row)

        row += 1

    col = row
    row = 0
    m, n = H.shape
    while row < m:
        j = col
        while H[row, j] == 0:
            j += 1
        swap_col(G, col, j)
        swap_col(H, col, j)
        echelon(H, row, col)

        row += 1
        col += 1

    k = n-m

    print("G =")
    print(shortstr(G))
    print("H =")
    print(shortstr(H))
    print()

    A = G[:, k:]
    B = H[:, :k]
    assert eq2(A.transpose(), B)

    if 0:
        for size in range(2, k):
            result = search(G, H, size=size, verbose=True)
            print("search(size=%d): %s"%(size, result))

    wd = weight_dist(H)
    print("H:", wd, sum(wd))
    wd = weight_dist(G)
    print("G:", wd, sum(wd))

    r = rank(A)
    print("rank deficit:", k-r)

    if r == k:

        idxs = list(range(k))
        jdxs = list(range(k, 2*k))

        C = cokernel(B)[0]
        C = row_reduce(C)
        rows, cols = C.shape
        assert rows == n-2*k
        assert cols == n-k

        jdxs = list(range(m))
        pivots = []
        for i in range(rows):
            for j in range(i, cols):
                if C[i, j] != 0:
                    pivots.append(j)
                    jdxs.remove(j)
                    break
        print("C:", pivots)
        print(shortstr(C))
        assert len(jdxs) == k

        jdxs = [k+i for i in jdxs]
        assert len( in_support(G, idxs) ) == 0
        assert len( in_support(G, jdxs) ) == 0
        assert len( in_support(H, idxs) ) == 0
        for row in in_support(H, jdxs):
            print("in_support:", row)
        assert len( in_support(H, jdxs) ) == 0
        print("OK")
Example #21
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 #22
0
def find_ideals():
    import networkx as nx
    from models import build_model

    model = build_model()
    if argv.verbose:
        print(model)
        print()
    #print(shortstrx(Hx, Hz))

    Gx, Gz = model.Gx, model.Gz
    Hx, Hz = model.Hx, model.Hz
    #print shortstrx(Gx, Gz)

    Rx, Rz = model.Rx, model.Rz
    Rxt = Rx.transpose()
    Rzt = Rz.transpose()

    Px, Pz = model.Px, model.Pz
    Pxt = Px.transpose()
    Pzt = Pz.transpose()

    r, n = Rx.shape

    assert eq2(dot2(Rx, Pxt), Rx)

#    print shortstrx(Gx, Gz)
#    print

    PGx = dot2(Gx, Pxt)
    PGz = dot2(Gz, Pzt)
    
#    print shortstrx(PGx, PGz)
#    print

    if 0:
        ng = len(PGx)

        graph = nx.Graph()
        for i in range(ng):
            graph.add_node(i)
    
        for i, gi in enumerate(PGx):
            for j, gj in enumerate(PGz):
                if (gi*gj).sum()%2:
                    graph.add_edge(i, j)

    mx = len(Gx)
    mz = len(Gz)
    graph = nx.Graph()
    for i in range(mx+mz):
        graph.add_node(i)

    for ix in range(mx):
        for iz in range(mz):
            if (Gx[ix]*Gz[iz]).sum()%2:
                graph.add_edge(ix, mx+iz)

#    excite = argv.excite
#    if type(excite) is int: 
#        _excite = [0]*len(model.Tx)
#        _excite[excite] = 1
#        excite = tuple(_excite)
#    #elif excite is None:
#    print("excite:", excite)

    equs = nx.connected_components(graph)
    equs = list(equs)

    print(model)
    print(("find_ideals:", len(equs)))

    models = []
    for equ in equs:
        equ = list(equ)
        equ.sort()
        #print(equ)
        gxs = []
        gzs = []
        for i in equ:
            if i<mx:
                gxs.append(Gx[i])
            else:
                gzs.append(Gz[i-mx])
        _model = build_model(array2(gxs), array2(gzs))
        print(_model)
        #print(shortstrx(_model.Gx))
        basis = find_kernel(_model.Gx.transpose())
        print(("kernel:", len(basis), [v.sum() for v in basis]))
        models.append(_model)

    idx = argv.dumpc
    if idx is not None:
        model = models[idx]
        #model = model.get_sector(compress=True)
        print(model)
        #print(shortstrx(model.Gx))
        basis = find_kernel(model.Gx.transpose())
        print(("kernel:", len(basis), [v.sum() for v in basis]))
        models.append(_model)
    
        model.dumpc()
        return

    if not argv.solve:
        return

    if argv.excite or argv.exciteall or argv.minweightall:
        if argv.minweightall:
            excites = minweightall(Hz)
            #print("excite", excite)
        elif argv.exciteall:
            excites = list(enum2(len(Hz)))[1:]
        else:
            assert len(Hz), Hz
            excites = []
            for i in range(len(Hz)):
                excite = array2([0]*len(Hz))
                excite[i] = 1
                excites.append(excite)
        print(("excites", len(excites)))
    else:
        excites = [None]

    if eq2(model.Hx, model.Hz):
        print("self dual stabilizers")

    _excite = None
    top = None
    for excite in excites:
        #if excite is not None:
        #    print "excite:", (excite)
        #    g = dot2(model.Hx.transpose(), excite)
        #    model.show_stabx(g)
        if excite is not None:
            tx = dot2(excite, model.Tx)

        total = 0.
        gaps = []

        for _model in models:
            #print(_model)
            if excite is not None:
                _tx = dot2(tx, _model.Hz.transpose(), _model.Tx)
                _excite = dot2(_tx, _model.Hz.transpose())
                #print(shortstrx(_excite))
                #print _excite
    
            r = len(_model.Rx)
            if r <= 12 and not argv.slepc and not argv.sparse:

                H = _model.build_ham(_excite) #weights=weights1)
                if argv.orbigraph:
                    H1 = build_orbigraph(H)
                
                vals, vecs = numpy.linalg.eigh(H)

            elif argv.sparse and r <= 19:

                vals = _model.sparse_ham_eigs(_excite) #weights=weights1)

            elif r <= 27:
                #for i in range(len(_excite)):
                #    _excite[i] = 1
                #print("excite:", tuple(_excite))
                #vals = slepc(excite=tuple(_excite), **_model.__dict__)
                if _excite is not None:
                    _excite = tuple(_excite)
                #vals = slepc(excite=_excite, **_model.__dict__)
                vals = _model.do_slepc(excite=_excite)
                #vals = [0, 0]

            else:
                assert 0, "r=%d too big"%r
            vals = list(vals)
            vals.sort(reverse=True)

            print(("total +=", vals[0]))
            total += vals[0]
            gaps.append(vals[0]-vals[1])
    
        if top is None or total > top:
            top = total
        print(("eval_1:", total))
        print(("eval_2:", total-min(gaps)))
    print(("top:", top))
Example #23
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 #24
0
File: glue.py Project: punkdit/qupy
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)