Пример #1
0
 def eq(self, other):
     "Two codes are equal if their generating matrices have the same span."
     G1, G2 = self.G, other.G
     if len(G1) != len(G2):
         return False
     A = dot2(self.H, other.G.transpose())
     B = dot2(other.H, self.G.transpose())
     assert (A.sum()==0) == (B.sum()==0)
     return A.sum() == 0
Пример #2
0
def main_fail():

    print()
    print("==" * 70)

    H = """
        012345678901234
     0  YXZZ...........
     1  X..X.XX.X......
     2  ZZ..ZZ.......Z.
     3  .X..Y....XZ....
     4  .ZX....Y.Z.....
     5  .....ZZZ.Z....Z
     6  ..Z...ZZ....ZZ.
     7  ...Z....Y.XX...
     8  ..XX.......ZY..
     9  .........ZXX..Y
    10  .....X.....XXXX
    11  ....X.X.X.X..X.
    """
    H = syparse(H)
    print()
    print(shortstr(H))

    m = len(H)
    n = H.shape[1] // 2
    assert n == 15
    F = symplectic(n)

    C = dot2(H, dot2(F, H.transpose()))

    print(C.shape)

    for i in range(m):
        for j in range(i + 1, m):
            if C[i, j]:
                print("fail:", i, j)

    print(rank(H))
    H = linear_independent(H)
    print("H=", H.shape)
    print(shortstr(H))

    HF = dot2(H, F)
    K = array2(find_kernel(HF))
    print("K=", K.shape)
    print(shortstr(K))

    HK = numpy.concatenate((H, K))
    L = linear_independent(HK)
    print()
    print(shortstr(L))
Пример #3
0
def gen():
    r = argv.get("r", None) # degree
    m = argv.get("m", None)

    if r is not None and m is not None:
        code = reed_muller(r, m)
    
        #print(code)
        #print("d =", code.get_distance())
        #code.dump()
    
        #code = code.puncture(3)
    
        #print(code)
        code = code.puncture(0)
        print(code)
        for g in code.G:
            print(shortstr(g), g.sum())
        print()
        #code.dump()
        #print("d =", code.get_distance())
    
        return

    for m in range(2, 8):
      for r in range(0, m+1):
        code = reed_muller(r, m)
        print(code, end=" ")
        if code.is_selfdual():
            print("is_selfdual", end=" ")
        if code.is_morthogonal(2):
            print("is_biorthogonal", end=" ")
        if code.is_morthogonal(3):
            print("is_triorthogonal", end=" ")
        if dot2(code.H, code.H.transpose()).sum()==0:
            print("***", end=" ")
        p = code.puncture(0)
        if p.is_morthogonal(3):
            print("puncture.is_triorthogonal", end=" ")
        if p.is_selfdual():
            print("puncture.is_selfdual", end=" ")
        if dot2(p.H, p.H.transpose()).sum()==0:
            print("***", end=" ")
        print()

        if p.is_triorthogonal() and p.k < 20:
            G = p.G
            #print(shortstr(G))
            A = list(span(G))
            A = array2(A)
            print(is_morthogonal(A, 3))
Пример #4
0
def main_torus():

    n = 8

    #   ZZZZZZZZ|XXXXXXXX
    #   12345678|12345678
    H = parse("""
    111..1..|........
    1..1....|1.1.....
    ........|11.11...
    .1..1...|.1...1..
    ..1...1.|...1..1.
    ...11.11|........
    .....1.1|....1..1
    ........|..1..111
    """.replace("|", ""))

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

    F = symplectic(n)
    C = dot2(H, dot2(F, H.transpose()))

    for i in range(n):
        for j in range(i + 1, n):
            if C[i, j]:
                print("fail:", i + 1, j + 1)

    print(rank(H))
    H = linear_independent(H)
    print("H=")
    print(shortstr(H))

    HF = dot2(H, F)
    K = array2(find_kernel(HF))
    print("K=")
    print(shortstr(K))

    HK = numpy.concatenate((H, K))
    L = linear_independent(HK)
    print()
    print(shortstr(L))
Пример #5
0
def check_toric():
    global toric  # arff !
    import qupy.ldpc.solve
    import bruhat.solve
    qupy.ldpc.solve.int_scalar = bruhat.solve.int_scalar
    from bruhat.solve import shortstr, zeros2, dot2, array2, solve
    from numpy import alltrue, zeros, dot
    l = argv.get("l", 2)
    from qupy.ldpc.toric import Toric2D
    toric = Toric2D(l)
    Hx, Hz = toric.Hx, toric.Hz
    assert alltrue(dot2(Hx, Hz.transpose()) == 0)

    from qupy.condmat.isomorph import Tanner, search
    src = Tanner.build2(Hx, Hz)
    #tgt = Tanner.build2(Hx, Hz)
    tgt = Tanner.build2(Hz, Hx)  # weak duality

    mx, n = Hx.shape
    mz, n = Hz.shape

    fns = []
    perms = []
    for fn in search(src, tgt):
        assert len(fn) == mx + mz + n
        bitmap = []
        for i in range(n):
            bitmap.append(fn[i + mx + mz] - mx - mz)
        perm = tuple(bitmap)
        #print(bitmap)
        fixed = [i for i in range(n) if bitmap[i] == i]
        print("perm:", perm)
        print("fixed:", fixed)

        g = Perm(perm, list(range(n)))
        assert g.order() == 2

        perms.append(perm)

    for hx in Hx:
        print(toric.strop(hx))
        print("--->")
        hx = array2([hx[i] for i in perm])
        print(toric.strop(hx))
        print("--->")
        hx = array2([hx[i] for i in perm])
        print(toric.strop(hx))
        print()

    check_dualities(Hz, Hx.transpose(), perms)
Пример #6
0
def test_rm():
    params = [(r, m) for m in range(2, 8) for r in range(1, m)]
    r = argv.get("r", None) # degree
    m = argv.get("m", None)
    if r is not None and m is not None:
        params = [(r, m)]
    
    for (r, m) in params:
        #code = reed_muller(r, m)
#      for code in [ reed_muller(r, m), reed_muller(r, m).puncture(0) ]:
      for code in [reed_muller(r, m)]:
        if argv.puncture:
            print(code, end=" ", flush=True)
            code = code.puncture(0)
            code = code.get_even()
            if argv.puncture==2:
                code = code.puncture(0)
                code = code.get_even()
            G = code.G
            k, n = G.shape
            #code = Code(G)
            #d = code.get_distance()
            d = "."
            print("puncture [%d, %d, %s]" % (n, k, d), end=" ", flush=True)
        else:
            G = code.G
            print(code, end=" ", flush=True)
        i = 1
        while i<8:
            if (is_morthogonal(G, i)):
                print("(%d)"%i, end="", flush=True)
                i += 1
            else:
                break
            if i > code.k:
                print("*", end="")
                break
        print()
        if argv.show:
            print(G.shape)
            print(shortstr(G))
            print(dot2(G, G.transpose()).sum())
        if len(G) >= 14:
            continue
        A = array2(list(span(G)))
        for i in [1, 2, 3]:
            assert strong_morthogonal(G, i) == strong_morthogonal(A, i)
Пример #7
0
def test():
    for idx, H in enumerate(items):
        H = array2(H)
        #print(H.shape)

        print(names[idx])
        print(shortstr(H))
        assert (dot2(H, H.transpose()).sum()) == 0  # orthogonal code
        G = H
        for genus in range(1, 4):
            print(strong_morthogonal(G, genus), end=" ")
        print()

        keys = [0, 4, 8, 12, 16, 20, 24]
        counts = {0: 0, 4: 0, 8: 0, 12: 0, 16: 0, 20: 0, 24: 0}

        for v in span(G):
            counts[v.sum()] += 1
        print([counts[k] for k in keys])
        print()
Пример #8
0
def intersect(G1, G2):
    G = numpy.concatenate((G1, G2))
    #print("intersect")
    #print(G1, G2)
    #print(G)
    G = G.transpose()
    #print("find_kernel", G.shape)
    K = find_kernel(G)
    if not K:
        K = numpy.array(K)
        K.shape = 0, G.shape[1]
    else:
        K = numpy.array(K)
    #print("K:")
    #print(K, K.shape)
    G = dot2(K[:, :len(G1)], G1)
    #print("G:")
    #print(G, G.shape)
    #print()
    G = normal_form(G)
    return G
Пример #9
0
def make_bring():

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

    # Bring's curve rotation group
    ngens = 2
    a, ai, b, bi = range(2 * ngens)
    rels = [(ai, a), (bi, b), (a, ) * 5, (b, ) * 2]
    rels += [(a, a, a, b) * 3]
    graph = Schreier(2 * ngens, rels)
    #graph.DEBUG = True
    graph.build()
    assert len(graph) == 60  # == 12 * 5

    # --------------- Group ------------------
    G = graph.get_group()
    #burnside(G)
    assert len(G.gens) == 4
    ai, a, bi, b = G.gens
    assert a == ~ai
    assert b == ~bi

    assert a.order() == 5
    assert b.order() == 2
    H = Group.generate([a])

    faces = G.left_cosets(H)
    assert len(faces) == 12
    #hom = G.left_action(faces)

    ab = a * b
    K = Group.generate([ab])
    vertices = G.left_cosets(K)
    assert len(vertices) == 12

    J = Group.generate([b])
    edges = G.left_cosets(J)
    assert len(edges) == 30

    from bruhat.solve import shortstr, zeros2, dot2
    from numpy import alltrue, zeros, dot

    def get_adj(left, right):
        A = zeros2((len(left), len(right)))
        for i, l in enumerate(left):
            for j, r in enumerate(right):
                lr = l.intersect(r)
                A[i, j] = len(lr)
        return A

    Hz = get_adj(faces, edges)
    Hxt = get_adj(edges, vertices)
    #print(shortstr(Hz))
    #print()
    #print(shortstr(Hxt))
    #print()

    assert alltrue(dot2(Hz, Hxt) == 0)

    # ------------ _oriented version ---------------

    # Bring's curve reflection group
    ngens = 3
    a, ai, b, bi, c, ci = range(2 * ngens)
    rels = [
        (ai, a),
        (bi, b),
        (ci, c),
        (a, ) * 2,
        (b, ) * 2,
        (c, ) * 2,
        (a, b) * 5,
        (b, c) * 5,
        (a, c) * 2,
    ]
    a1 = (b, a)
    b1 = (a, c)
    rels += [(3 * a1 + b1) * 3]
    graph = Schreier(2 * ngens, rels)
    graph.build()
    assert len(graph) == 120  # == 12 * 10

    # --------------- Group ------------------
    G = graph.get_group()
    assert len(G) == 120

    a, ai, b, bi, c, ci = G.gens
    a1 = b * a
    b1 = a * c

    assert a1.order() == 5
    assert b1.order() == 2

    bc = b * c
    ba = b * a
    assert bc.order() == 5
    assert ba.order() == 5
    L = Group.generate([a1, b1])
    assert len(L) == 60, len(L)
    orients = G.left_cosets(L)
    assert len(orients) == 2
    #L, gL = orients
    orients = list(orients)

    H = Group.generate([a, b])
    assert len([g for g in H if g in L]) == 5
    faces = G.left_cosets(H)
    assert len(faces) == 12  # unoriented faces
    #hom = G.left_action(faces)
    o_faces = [face.intersect(orients[0]) for face in faces]  # oriented faces
    r_faces = [face.intersect(orients[1])
               for face in faces]  # reverse oriented faces

    K = Group.generate([b, c])
    vertices = G.left_cosets(K)
    assert len(vertices) == 12  # unoriented vertices
    o_vertices = [vertex.intersect(orients[0])
                  for vertex in vertices]  # oriented vertices

    J = Group.generate([a, c])
    u_edges = G.left_cosets(J)
    assert len(u_edges) == 30  # unoriented edges

    J = Group.generate([c])
    edges = G.left_cosets(J)
    assert len(edges) == 60, len(edges)  # oriented edges ?

    # Here we choose an orientation on each edge:
    pairs = {}
    for e in u_edges:
        pairs[e] = []
        for e1 in edges:
            if e.intersect(e1):
                pairs[e].append(e1)
        assert len(pairs[e]) == 2

    def shortstr(A):
        s = str(A)
        s = s.replace("0", '.')
        return s

    Hz = zeros((len(o_faces), len(u_edges)), dtype=int)
    for i, l in enumerate(o_faces):
        for j, e in enumerate(u_edges):
            le = l.intersect(e)
            if not le:
                continue
            e1, e2 = pairs[e]
            if e1.intersect(le):
                Hz[i, j] = 1
            elif e2.intersect(le):
                Hz[i, j] = -1
            else:
                assert 0

    Hxt = zeros((len(u_edges), len(o_vertices)), dtype=int)
    for i, e in enumerate(u_edges):
        for j, v in enumerate(o_vertices):
            ev = e.intersect(v)
            if not ev:
                continue
            e1, e2 = pairs[e]
            if e1.intersect(ev):
                Hxt[i, j] = 1
            elif e2.intersect(ev):
                Hxt[i, j] = -1
            else:
                assert 0

    #print(shortstr(Hz))
    #print()
    #print(shortstr(Hxt))
    #print()

    assert alltrue(dot(Hz, Hxt) == 0)
Пример #10
0
def check_dualities(Hz, Hxt, dualities):
    from bruhat.solve import shortstr, zeros2, dot2, array2, solve, span
    from numpy import alltrue, zeros, dot

    import qupy.ldpc.solve
    import bruhat.solve
    qupy.ldpc.solve.int_scalar = bruhat.solve.int_scalar
    from qupy.ldpc.css import CSSCode
    Hz = Hz % 2
    Hx = Hxt.transpose() % 2
    code = CSSCode(Hz=Hz, Hx=Hx)
    print(code)
    n = code.n

    Lx, Lz = code.Lx, code.Lz

    # check we really do have weak dualities here:
    for perm in dualities:
        Hz1 = Hz[:, perm]
        Hxt1 = Hxt[perm, :]
        assert solve(Hxt, Hz1.transpose()) is not None
        assert solve(Hz1.transpose(), Hxt) is not None

        Lz1 = Lz[:, perm]
        Lx1 = Lx[:, perm]
        find_xz = solve(concatenate((Lx, Hx)).transpose(),
                        Lz1.transpose()) is not None
        find_zx = solve(concatenate((Lz1, Hz1)).transpose(),
                        Lx.transpose()) is not None
        #print(find_xz, find_zx)
        assert find_xz
        assert find_zx

        # the fixed points live simultaneously in the homology & the cohomology
        fixed = [i for i in range(n) if perm[i] == i]
        if len(fixed) == 0:
            continue
        v = array2([0] * n)
        v[fixed] = 1
        v.shape = (n, 1)
        find_xz = solve(concatenate((Lx, Hx)).transpose(), v) is not None
        find_zx = solve(concatenate((Lz, Hz)).transpose(), v) is not None
        #print(find_xz, find_zx)
        assert find_xz
        assert find_zx

    from qupy.ldpc.asymplectic import Stim as Clifford
    s_gates = []
    h_gates = []
    s_names = []
    for idx, swap in enumerate(dualities):

        fixed = [i for i in range(n) if swap[i] == i]
        print(idx, fixed)
        for signs in cross([(-1, 1)] *
                           len(fixed)):  # <------- does not scale !!! XXX
            v = [0] * n
            for i, sign in enumerate(signs):
                v[fixed[i]] = sign
            ux = numpy.dot(Hx, v)
            uz = numpy.dot(Hz, v)
            if numpy.alltrue(ux == 0) and numpy.alltrue(uz == 0):
                #print("*", end=" ")
                break
        #else:
        #    assert 0
        #print(v)
        #print()

        # transversal S/CZ
        g = Clifford.identity(n)
        name = []
        for i in range(n):
            j = swap[i]
            if j < i:
                continue
            if j == i:
                assert v[i] in [1, -1]
                if v[i] == 1:
                    op = Clifford.s_gate(n, i)
                    name.append("S_%d" % (i, ))
                else:
                    op = Clifford.s_gate(n, i).inverse()
                    name.append("Si_%d" % (i, ))
            else:
                op = Clifford.cz_gate(n, i, j)
                name.append("CZ_%d_%d" % (i, j))
            g = op * g
        name = "*".join(reversed(name))
        s_names.append(name)
        #print(g)
        #print()
        #assert g.is_transversal(code)

        s_gates.append(g)

        h = Clifford.identity(n)
        for i in range(n):
            h = h * Clifford.h_gate(n, i)

        for i in range(n):
            j = swap[i]
            if j <= i:
                continue
            h = h * Clifford.swap_gate(n, i, j)
        #print(g)
        #print()
        #assert h.is_transversal(code)
        h_gates.append(h)

    if 0:
        print()
        print("CZ:")
        CZ = Clifford.cz_gate(2, 0, 1)
        op = (1., [0, 0], [1, 1])
        for i in range(4):
            print(op)
            op = CZ(*op)
        return

    for idx, sop in enumerate(s_gates):
        print("idx =", idx)
        #for hx in Hx:
        perm = dualities[idx]
        #for hx in span(Hx):
        for hx in Hx:
            #print("hx =", hx)
            #print(s_names[idx])
            phase, zop, xop = sop(1., None, hx)
            assert numpy.alltrue(xop == hx)  # fixes x component
            print(phase, zop, xop, dot2(zop, xop))
            for (i, j) in enumerate(perm):
                if xop[i] and xop[j] and i < j:
                    print("pair", (i, j))
            if toric is None:
                continue
            print("xop =")
            print(toric.strop(xop))
            print("zop =")
            print(toric.strop(zop))
            print()
Пример #11
0
def is_422_cat_selfdual(Hz, Hx, perm):
    "concatenate with the [[4,2,2]] code and see if we get a self-dual code"
    from numpy import alltrue, zeros, dot
    import qupy.ldpc.solve
    import bruhat.solve
    qupy.ldpc.solve.int_scalar = bruhat.solve.int_scalar
    from bruhat.solve import shortstrx, zeros2, dot2, array2, solve
    from qupy.ldpc.css import CSSCode
    Cout = CSSCode(Hz=Hz, Hx=Hx)
    #print(Cout)
    #Cin = CSSCode(Hz=array2([[1,1,1,1]]), Hx=array2([[1,1,1,1]]))
    #print(Cin)

    pairs = []
    singles = []
    for i in range(Cout.n):
        j = perm[i]
        if j < i:
            continue
        if i == j:
            singles.append(i)
        else:
            pairs.append((i, j))
    #print(singles, pairs)
    M = len(singles) + 4 * len(pairs)

    # encoding matrices
    enc_z = zeros2(M, Cout.n)
    enc_x = zeros2(M, Cout.n)

    row = 0
    for col in singles:
        enc_z[row, col] = 1
        enc_x[row, col] = 1
        row += 1
    H = []
    for (i, j) in pairs:
        enc_z[row, i] = 1  # 1010
        enc_z[row + 2, i] = 1
        enc_z[row, j] = 1  # 1100
        enc_z[row + 1, j] = 1

        enc_x[row, i] = 1  # 1100
        enc_x[row + 1, i] = 1
        enc_x[row, j] = 1  # 1010
        enc_x[row + 2, j] = 1
        h = array2([0] * M)
        h[row:row + 4] = 1
        H.append(h)

        row += 4
    assert row == M

    #print(shortstrx(enc_z, enc_x))

    Hz = dot2(enc_z, Cout.Hz.transpose()).transpose()
    Hx = dot2(enc_x, Cout.Hx.transpose()).transpose()
    assert alltrue(dot2(Hz, Hx.transpose()) == 0)

    Hz = numpy.concatenate((Hz, H))
    Hx = numpy.concatenate((Hx, H))
    assert alltrue(dot2(Hz, Hx.transpose()) == 0)

    C = CSSCode(Hz=Hz, Hx=Hx)
    assert C.k == Cout.k
    #print(C)

    lhs = (solve(Hz.transpose(), Hx.transpose()) is not None)
    rhs = (solve(Hx.transpose(), Hz.transpose()) is not None)
    return lhs and rhs
Пример #12
0
def make_surface_54(G_0):
    "find Z/2 chain complex"

    from bruhat.solve import shortstr, zeros2, dot2
    from numpy import alltrue, zeros, dot

    print("|G_0| =", len(G_0))

    a, ai, b, bi, c, ci, d, di = G_0.gens

    # 5,5 coxeter subgroup
    G_1 = Group.generate([a, b, c])
    assert G_0.is_subgroup(G_1)

    # orientation subgroup
    L_0 = Group.generate([a * b, a * d])
    assert G_0.is_subgroup(L_0)
    orients = G_0.left_cosets(L_0)
    assert len(orients) == 2

    H_1 = Group.generate([a, b])
    faces = G_1.left_cosets(H_1)
    #face_vertices = G_0.left_cosets(H_1) # G_0 swaps faces & vertices

    K_1 = Group.generate([b, c])
    vertices = G_1.left_cosets(K_1)

    J_1 = Group.generate([a, c])
    edges_1 = G_1.left_cosets(J_1)

    print("faces: %d, edges: %d, vertices: %d" %
          (len(faces), len(edges_1), len(vertices)))

    J_0 = Group.generate([a, d])
    assert len(J_0) == 8

    edges_0 = G_0.left_cosets(J_0)
    print("edges_0:", len(edges_0))

    assert G_0.is_subgroup(J_0)
    act_edges_0 = G_0.action_subgroup(J_0)
    #print("here")
    #while 1:
    #    sleep(1)

    from bruhat.solve import shortstr, zeros2, dot2, array2, solve
    from numpy import alltrue, zeros, dot

    def get_adj(left, right):
        A = zeros2((len(left), len(right)))
        for i, l in enumerate(left):
            for j, r in enumerate(right):
                lr = l.intersect(r)
                A[i, j] = len(lr) > 0
        return A

    Hz = get_adj(faces, edges_0)
    Hxt = get_adj(edges_0, vertices)
    Hx = Hxt.transpose()

    #print(shortstr(Hz))
    #print()
    #print(shortstr(Hxt))
    #print()

    assert alltrue(dot2(Hz, Hxt) == 0)

    #    act_fold_faces = G_0.action_subgroup(H_1)

    dualities = []
    idx = 0
    for i, g in enumerate(G_0):
        assert g in G_0
        h_edge_0 = act_edges_0[g]
        n_edge = len(h_edge_0.fixed())

        #        h_fold_faces = act_fold_faces[g]
        #        n_fold_faces = len(h_fold_faces.fixed())
        count = 0
        #perms = [] # extract action on the fixed edges
        for e0 in edges_0:
            e1 = g * e0
            if e0 != e1:
                continue
            count += 1
        #    perm = e0.left_mul_perm(g)
        #    #print(perm, end=" ")
        #    perms.append(perm)
        assert count == n_edge

        if g in G_1:
            continue
        elif g.order() != 2:
            continue
        #elif g in L_0:
        #    continue
        #elif g.order() == 2 and g not in G_1 and g not in L_0:

        perm = h_edge_0.get_idxs()
        dualities.append(perm)
        #if g not in L_0:
        #    check_432(Hz, Hx, perm)
        #    return
        result = is_422_cat_selfdual(Hz, Hx, perm)

        print(
            "%d: [|g|=%s,%s.%s.%s.%s]" % (
                len(dualities),
                g.order(),
                n_edge or ' ',  # num fixed edges
                #            n_fold_faces or ' ',  # num fixed faces+vertexes
                ["    ", "pres"
                 ][int(g in G_1)],  # preserves face/vertex distinction
                ["refl", "rot "][int(g in L_0)],  # oriented or un-oriented
                ["        ", "selfdual"][result],
            ),
            end=" ",
            flush=True)
        print()

    print()
Пример #13
0
def search():
    # 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)
    A = list(span(G))
    print(strong_morthogonal(A, 1))
    print(strong_morthogonal(A, 2))
    print(strong_morthogonal(A, 3))
    
    #print(shortstr(dot2(G, G.transpose())))

    if 0:
        B = pseudo_inverse(A)
        v = dot2(B, rhs)
        print("B:")
        print(shortstr(B))
        print("v:")
        print(shortstr(v))
        assert eq2(dot2(B, v), rhs) 
Пример #14
0
 def check(self):
     G, H = self.G, self.H
     assert rank(G) == len(G)
     A = dot2(H, G.transpose())
     assert A.sum()==0
Пример #15
0
def search_selfdual():

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


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

    # these are the variables N_x
    print("building xs...")

    if 0:
        xs = cross([(0, 1)]*m)
        xs = [x for x in xs if minweight <= sum(x) <= maxweight]
    
        prune = argv.get("prune", 0.5)
        xs = [x for x in xs if random() < prune]

    xs = []
    N = argv.get("N", m*100)
    colweight = argv.get("colweight", maxweight)
    assert colweight <= m
    for i in range(N):
        x = [0]*m
        total = 0
        while total < colweight:
            idx = randint(0, m-1)
            if x[idx] == 0:
                x[idx] = 1
                total += 1
        xs.append(x)

    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)

    k = 0 # all rows must have even weight
    # 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)

    logops = argv.logops

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

    print("solve...")
    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("kernel:", K.shape)
    if len(K)==0:
        return
    #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
    print("trials...")
    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

        if v.sum() < m:
            continue

        if v.sum():
            print(v.sum(), end=" ", flush=True)

        size = v.sum()

        if logops is not None and size != 2*m+logops:
            continue

        Gt = []
        for i, x in enumerate(xs):
            if v[i]:
                Gt.append(x)

        Gt = array2(Gt)
        G = Gt.transpose()
        if dot2(G, Gt).sum() != 0:
            # not self-dual
            print(shortstr(dot2(G, Gt)))
            assert 0
            return

        #if G.shape[1]<m:
        #    continue

        if 0 in G.sum(1):
            print(".", end="", flush=True)
            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))
    f = open("selfdual.ldpc", "w")
    for spec in ["Hx =", "Hz ="]:
        print(spec, file=f)
        for g in G:
            print(shortstr(g), file=f)
    f.close()

    print()
    print("density:", density)
    print("shape:", G.shape)
    

    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) 
Пример #16
0
def search_extend():
    # Extend the checks of a random code to make it triorthogonal.
    # Based on the search function above.

    verbose = argv.get("verbose")

    m = argv.get("m", 6)
    n = argv.get("n", m+2)
    k = argv.get("k") # odd _numbered rows ( logical operators)
    code = argv.get("code", "rand")

    if code == "rand":
        while 1:
            G0 = rand2(m, n)
            counts = G0.sum(0)
            if min(counts)==2 and rank(G0) == m:
                cols = set()
                for i in range(n):
                    cols.add(tuple(G0[:, i]))
                if len(cols) == n: # no repeated cols
                    break

    elif code == "toric":
        G0 = parse("""
        11.11...
        .111..1.
        1...11.1
        """) # l=2 toric code X logops + X stabs 

        l = argv.get("l", 3)
        G0 = build_toric(l)

        m, n = G0.shape
    else:
        return

    code = Code(G0, check=False)
    print(shortstr(G0))
    print("is_triorthogonal:", code.is_triorthogonal())

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

    lookup = {}
    for i, x in enumerate(xs):
        lookup[x] = i

    lhs = []
    rhs = []

    taken = set()
    for i in range(n):
        x = G0[:, i]
        idx = lookup[tuple(x)]
        assert idx not in taken
        taken.add(idx)

    if verbose:
        for idx in range(N):
            print(idx, xs[idx], "*" if idx in taken else "")

    for idx in taken:
        v = zeros2(N)
        v[idx] = 1
        lhs.append(v)
        rhs.append(1)

    # 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
        assert 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
        assert 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)

    if verbose:
        print("lhs:")
        print(shortstr(A))
    
        print("rhs:")
        print(shortstr(rhs))

    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)))

    best = None
    density = 1.0
    size = 9999*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)
        assert dot2(A, v).sum()==0
        #if v.sum() != n:
        #    continue
        assert v[0]==0
        v = (v+soln)%2
        assert eq2(dot2(A, v), rhs)

        Gt = list(G0.transpose())
        for i, x in enumerate(xs):
            if v[i] and not i in taken:
                Gt.append(x)
        if not Gt:
            continue
        Gt = array2(Gt)
        G = Gt.transpose()
        if verbose:
            print("G0")
            print(shortstr(G0))
            print("solution:")
            print(shortstr(G))
        assert is_morthogonal(G, 3)
        if G.shape[1]<m:
            continue

        if 0 in G.sum(1):
            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
            density = _density
            size = G.shape[1]

        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)

    G = best
    #print(shortstr(G))
    for g in G:
        print(shortstr(g), g.sum())
    print()
    print("density:", density)