예제 #1
0
def test_puncture(H):
    print("\ntest_puncture --------")
    n = H.shape[1]

    G = find_kernel(H)
    k = len(G)
    print("n = %d, k = %d" % (n, k))
    print("G =")
    print(shortstr(G))

    R = row_reduce(H)
    print("R =")
    print(shortstr(R))

    pivots = get_pivots(R)
    rows = [i for (i, j) in pivots]
    cols = [j for (i, j) in pivots]
    print("pivots:", pivots)
    A = cols[:k]
    remain = [j for j in range(n) if j not in A]
    S = R[:, remain]
    print("S =")
    print(shortstr(S))
    G1 = find_kernel(S)
    print("G1 =")
    G1 = row_reduce(G1)
    print(G1)
    S = row_reduce(S)
    print("S: rank = ", rank(S))
    print(shortstr(S))
예제 #2
0
def build_reduced():

    Gx, Gz, Hx, Hz = build()

    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)

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

    return Rx, Rz
예제 #3
0
 def __init__(self, U):
     U = row_reduce(U)
     m, n = U.shape
     self.m = m
     self.n = n
     self.U = U
     self._key = (m, n, U.tostring())
예제 #4
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
예제 #5
0
def z_weld(acode, bcode, pairs):

    for c in [acode, bcode]:
        print("Lx:")
        print(c.Lx)
        print("Lz:")
        print(c.Lz)
        print("Hx:")
        print(c.Hx)
        print("Hz:")
        print(c.Hz)
        print("-------------------")

    mx = acode.mx + bcode.mx
    #for (i, j) in pairs:
    assert len(set(pairs)) == len(pairs)  # uniq

    n = acode.n + bcode.n - len(pairs)

    #    Hx = zeros2(mx, n)
    #    Hx[:acode.mx, :acode.n] = acode.Hx
    #    Hx[acode.mx:, acode.n-len(pairs):] = bcode.Hx
    #
    #    az = acode.mz + bcode.mz + acode.k + bcode.k
    #    Az = zeros2(az, n)
    #    r0, r1 = 0, acode.mz
    #    Az[r0:r1, :acode.n] = acode.Hx; r0, r1 = r1, r1+len(acode.Hx)
    #    Az[r0:r1, acode.n-len(pairs):] = bcode.Hx; r0, r1 = r1, r1+len(bcode.Hx)
    ##    Az[r0:r1, :acode.n] = acode.Lz; r0, r1 = r1, r1+len(acode.Lz)
    ##    #assert r1 == len(Az), (r1, len(Az))
    ##    Az[r0:r1, acode.n-len(pairs):] = bcode.Lz; r0, r1 = r1, r1+len(bcode.Lz)
    #
    #    print("Az:")
    #    print(Az)

    #print(Az)
    Hz = []
    for z in span(Az):
        #print(z)
        #print( dot2(Hx, z.transpose()))
        if dot2(Hx, z.transpose()).sum() == 0:
            Hz.append(z)
    Hz = array2(Hz)
    Hz = row_reduce(Hz)

    print("Hx:")
    print(Hx)
    print("Hz:")
    print(Hz)
예제 #6
0
def test(n, k, dist=2, verbose=False):
    assert n > k

    if argv.rand:
        while 1:
            G = rand2(k, n)
            if rank(G) < k:
                continue
            dG = min_weight(G)
            if dG < dist:
                continue

            H = find_kernel(G)
            dH = min_weight(H)
            if dH < dist:
                continue

            break

    else:
        G = zeros2(k, n)
        jdx = 0
        for idx in range(k):
          for kdx in range(dist):
            G[idx,jdx+kdx] = 1
          jdx += dist-1

        dG = min_weight(G) if n < 20 else None
        assert dG is None or dG == dist

        H = find_kernel(G)

    #print(".", flush=True, end="")
    H = row_reduce(H)

    search(G, H)

    if verbose:
        print("G =")
        print(shortstr(G))
        print("weight =", dG)
        print()

        print("H =")
        print(shortstr(H))
        print()
예제 #7
0
def opticycle(m, n):

    best_d = 0

    for trial in range(4000):

        #row = '1101'
        row = [0] * n
        for i in range(18):
            row[randint(0, n-1)] = 1
        print(shortstr(row))

        Hz = build_cycle(m, n, row)

        Hz = solve.row_reduce(Hz, truncate=True)
    
        #print shortstr(Hz)
    
        code = CSSCode(Hz=Hz, build=True, check=True)
    
        Lx = code.Lx
        k = Lx.shape[0]
        ws = [Lx[i].sum() for i in range(k)]
        d = min(ws)
        print("\nd =", d)

        if d > best_d:
            d = code.find_distance(stopat=best_d)
            print("\n*d =", d)

        if d > best_d:
            best_d = d
            best = code
            print("distance <=", best_d)

    code = best

    print()
    print(code)
    #print code.weightstr()
    print(code.weightsummary())
    print("distance <=", best_d)

    return code
예제 #8
0
파일: symplectic.py 프로젝트: punkdit/qupy
 def normal_form(self):
     A = self.A
     #print("normal_form")
     #print(A)
     A = row_reduce(A)
     #print(A)
     m, n = A.shape
     j = 0
     for i in range(m):
         while A[i, j] == 0:
             j += 1
         i0 = i - 1
         while i0 >= 0:
             r = A[i0, j]
             if r != 0:
                 A[i0, :] += A[i, :]
                 A %= 2
             i0 -= 1
         j += 1
     #print(A)
     A = Matrix(A)
     return A
예제 #9
0
def dependent_rows(H):
    "find dependent rows of H, first to last"
    idxs = set(range(len(H)))
    #print(H)
    K = find_kernel(H.transpose())
    #print("K:")
    #print(K)
    K = row_reduce(K, truncate=True)
    #print("K:")
    #print(K)
    assert dot2(K, H).sum() == 0
    deps = []
    for row in K:
        #print(row)
        idx = numpy.where(row != 0)[0][0]
        deps.append(idx)
        idxs.remove(idx)
    assert len(set(deps)) == len(K)
    idxs = list(idxs)
    idxs.sort()
    deps.sort()
    return idxs, deps
예제 #10
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
예제 #11
0
def main():

    if argv.ldpc:
        # LDPC
        l = argv.get("l", 3)  # column weight
        m = argv.get("m", 4)  # row weight
        n = argv.get("n", 8)  # cols
        r = argv.get("r", n * l // m)  # rows
        d = argv.get("d", 1)  # distance
        print("make_gallagher%s" % ((r, n, l, m, d), ))
        C = make_gallagher(r, n, l, m, d)
        print(shortstr(C))
        print()
        print(shortstr(C))
        print("rank(C) = ", rank(C), "kernel(C) = ", len(find_kernel(C)))
        if argv.same:
            D = C
        else:
            D = make_gallagher(r, n, l, m, d)
            assert rank(C) == len(C)
            assert rank(D) == len(D)
            print("rank(D)", rank(D), "kernel(D)", len(find_kernel(D)))

    elif argv.hrand:
        #C = random_code(16, 8, 0, 3)
        C = random_code(8, 4, 0, 3)
        D = random_code(8, 4, 1, 3)

    elif argv.hvrand:
        #C = random_code(16, 8, 8, 3)
        C = random_code(8, 4, 4, 3)
        D = random_code(8, 4, 4, 3)

    elif argv.hvrandsmall:
        #C = random_code(16, 8, 8, 3)
        C = random_code(7, 1, 1, 2)  # n, k, kt, d
        D = random_code(7, 1, 1, 2)

    elif argv.samerand:
        C = random_code(12, 6, 0, 4)
        D = C

    elif argv.smallrand:
        # make some vertical logops from rank degenerate parity check matrices
        C = random_code(8, 4, 0, 3)
        D = random_code(6, 3, 0, 2)

    elif argv.cookup:
        # [12,6,4] example that has no k-bipuncture
        C = parse("""
        .1..1111....
        111.11111111
        11.111...11.
        1..11...1.11
        .11...1...11
        ..11.11.111.
        """)
        D = C
        R = row_reduce(C)
        print(shortstr(R))

    elif argv.cookup2:
        # [12,6,4] example that has no k-bipuncture
        C = parse("""
        .11..1.11..1
        11...1111...
        1....1.11111
        ..1.1111..1.
        111....1.11.
        1111.11...11
        .1.1.1....1.
        1111111.1111
        ....1..111..
        .1..1.111.11
        11.11......1
        11..1111.1..
        """)
        D = C

    elif argv.pair:
        #C = make_gallagher(9, 12, 3, 4, 4) # big
        C = make_gallagher(15, 20, 3, 4, 4)  # big
        D = make_gallagher(6, 8, 3, 4, 1)  # small

    elif argv.torus:
        # Torus
        C = parse("""
        11..
        .11.
        ..11
        1..1
        """)
        D = C

    elif argv.hamming:
        C = parse("""
        ...1111
        .11..11
        1.1.1.1
        111....
        """)
        D = C

    elif argv.surf or argv.surface:
        # Surface
        C = parse("""
        11....
        .11...
        ..11..
        ...11.
        ....11
        """)
        D = parse("""
        11..
        .11.
        ..11
        """)

    elif argv.small:
        C = parse("""1111""")
        D = parse("""1111""")

    else:
        print("please specify a code")
        return

    print("C: shape=%s, rank=%d, dist=%d" %
          (C.shape, rank(C), classical_distance(C)))
    print("C.t: dist=%d" % (classical_distance(C.transpose()), ))
    print(shortstr(C))
    print("D: shape=%s, rank=%d, dist=%d" %
          (D.shape, rank(D), classical_distance(D)))
    print("D.t: dist=%d" % (classical_distance(D.transpose()), ))
    print(shortstr(D))
    Ct = C.transpose()
    Dt = D.transpose()

    if argv.dual:
        C, Ct = Ct, C
        D, Dt = Dt, D

    if argv.test_puncture:
        test_puncture(C)
        return  # <--------- return

    if argv.test_indep:
        kw = hypergraph_product(C, Dt)
        test_indep(**kw)
        return  # <--------- return

    if argv.test_code:
        kw = hypergraph_product(C, Dt)
        test_code(**kw)
        return  # <--------- return

    if argv.test_overlap:

        #while 1:
        kw = hypergraph_product(C, Dt)
        success = test_overlap(**kw)

        print("success:", success)
        if argv.success:
            assert success

        #if success:
        #    break

        #else:
        #    sys.exit(0)
        C = shuff22(C)
        if argv.same:
            D = C
            Dt = D.transpose()
        else:
            Dt = shuff22(Dt)
예제 #12
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()
예제 #13
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")
예제 #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 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))
예제 #16
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)
예제 #17
0
def dense_full(Gx, Gz, Hx, Hz, Rx, Pxt, Qx, Pz, Tx, **kw):
    " find orbigraph for hamiltonian component Gamma "

    gz, n = Gz.shape

    if argv.excite:
        excites = [argv.excite]

    else:
        excites = genidx((2,)*len(Tx))

    for excite in excites:

        print("excite:", excite)
        assert len(excite)==len(Tx)

        t = zeros2(n)
        for i, ex in enumerate(excite):
            if ex:
                t = (t + Tx[i])%2
        #print "t:", shortstr(t)
        Gzt = dot2(Gz, t)
        #print "Gzt:", shortstr(Gzt)

        # This is our basis
        Bx = array2([v+t for v in Rx] + [v+t for v in Hx])
        Bx %= 2
        r = len(Bx)
        N = 2**r
        Bx = row_reduce(Bx, truncate=True)
        assert len(Bx)==r # linearly independent rows
        Cx = u_inverse(Bx)

        if N<=1024:
            H = numpy.zeros((N, N))
        else:
            H = None
        A = {}
        U = []

        #for i in range(N):
        pos = neg = 0
        for i, v in enumerate(genidx((2,)*r)):
            v = array2(v)
            syndrome = dot2(Gz, Bx.transpose(), v)
            value = gz - 2*syndrome.sum()
            #print shortstr(dot2(Rx.transpose(), v)), value
            if H is not None:
                H[i, i] = value
            U.append(value)

        for i, v in enumerate(genidx((2,)*r)):
            v = array2(v)
            u0 = dot2(Bx.transpose(), v)
            #print shortstr(v),
            for g in Gx:
                u1 = (u0 + g) % 2
                v1 = dot2(Cx.transpose(), u1)
                assert v1.shape == v.shape
                j = eval('0b'+shortstr(v1, zero='0'))
                if H is not None:
                    H[i, j] += 1
                A[i, j] = A.get((i, j), 0) + 1

        #print H

        if argv.orbistab:
            hx = Hx[0]
            do_orbistab(Bx, Cx, H, hx)

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

        if argv.solve:
            assert N <= 1024
            assert numpy.allclose(H, H.transpose())
            vals, vecs = numpy.linalg.eigh(H)
            if argv.show_eigs:
                show_eigs(vals)
            #print vals
            vals = list(vals)
            vals.sort()
            val0 = vals[-1] # top one is last
            vec0 = vecs[:,-1]
            if vec0[0] < 0:
                vec0 = -vec0
            assert vals[-2] < val0 - 1e-4
            print("excite:", excite, end=' ')
            print("eigval:", val0)
예제 #18
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()