示例#1
0
文件: glue.py 项目: punkdit/qupy
def test_universal():

    for trial in range(100):

        m, n = 3, 4
        J = rand2(m, n)
        K = rand2(m, n)

        a = Chain([J])
        b = Chain([K])
        amorph = a.from_zero()
        bmorph = b.from_zero()

        am, bm, c, u = chain.pushout(amorph, bmorph)
        assert u is None

        C = c[0]
        mm, nn = C.shape

        f = rand_full_rank(nn - 2, nn)
        g, H, _ = solve.pushout(C, f)

        _c = Chain([H])
        m = Morphism(c, _c, [g, f])
        assert m * am is not None
        assert m * bm is not None

        _, _, _, u = chain.pushout(amorph, bmorph, m * am, m * bm, _c)
        assert u is not None
        assert u == m
示例#2
0
文件: glue.py 项目: punkdit/qupy
def test_glue():

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

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

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

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

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

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

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

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

    if k1 != k2:
        return
    k = k1

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

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

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

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

    w = wenum(H)
    print("wenum:", [len(wi) for wi in w])
示例#3
0
def build_random(n):

    weight = argv.get("weight", 3)
    coweight = argv.get("coweight")

    p = argv.get("p", 0.3)
    m = argv.get("m", n)
    mx = argv.get("mx", m)
    mz = argv.get("mz", m)

    if coweight is not None:
        Gx = rand2(n, mx, weight=coweight).transpose()
        Gz = rand2(n, mz, weight=coweight).transpose()

    else:
        Gx = rand2(mx, n, p=p, weight=weight)
        Gz = rand2(mz, n, p=p, weight=weight)

    Hx = Hz = None

    Gx = Gx[[i for i in range(m) if Gx[i].sum()], :]
    Gz = Gz[[i for i in range(m) if Gz[i].sum()], :]

    li = argv.get("li", True)

    if li:
        Gx = linear_independent(Gx)
        Gz = linear_independent(Gz)

    return Gx, Gz, Hx, Hz
示例#4
0
文件: glue.py 项目: punkdit/qupy
def make_q(n, m, weight=None):
    k = n - 2 * m
    assert k >= 0

    assert m > 0
    Hx = [rand2(1, n, weight=weight)[0]]
    Hz = []
    while 1:
        _Hx = array2(Hx)
        while 1:
            v = rand2(1, n, weight=weight)
            if dot2(Hx, v.transpose()).sum() == 0:
                break
        Hz.append(v[0])
        if len(Hz) == m:
            break
        while 1:
            v = rand2(1, n, weight=weight)
            if dot2(Hz, v.transpose()).sum() == 0:
                break
        Hx.append(v[0])
    Hx = array2(Hx)
    Hz = array2(Hz)
    assert dot2(Hx, Hz.transpose()).sum() == 0

    return Hx, Hz
示例#5
0
def sparsecss_FAIL(n, mx, mz, weight=3, **kw):

    print("sparsecss", n, mx, mz)
    k = n-mx-mz
    assert k>=0

    Hz = rand2(mz, n, weight=weight)

    #print shortstrx(Hx)

    kern = numpy.array(solve.find_kernel(Hz))
    mkern = kern.shape[0]
    print("kern:")
    print(shortstr(kern))
    print()


    kern1 = zeros2(mkern, n)
    for i in range(mkern):
        v = rand2(1, mkern)
        kern1[i] = dot2(v, kern)
    print("kern1:")
    print(shortstr(kern1))
    print()

    kern = kern1

    Hx = []
    for i in range(mx):
        j = randint(0, mkern-1)
        v = kern[j].copy()

        count = 0
        while 1:

            v += kern[randint(0, mkern-1)]
            v %= 2

            w = v.sum()

            if w==weight and count > 100:
                break

            count += 1

        Hx.append(v)
    Hx = array2(Hx)
    print(shortstrx(Hx))

    C = CSSCode(Hx=Hx, Hz=Hz, **kw)
    return C
示例#6
0
def build_random_selfdual(n):

    weight = argv.get("weight", 3)
    m = argv.get("m", n)
    h = argv.get("h", 0)

    while 1:
        Gx = rand2(m, n, weight=weight)
        Gz = Gx.copy()

        Hx = Hz = None

        Gx = Gx[[i for i in range(m) if Gx[i].sum()], :]
        Gx = linear_independent(Gx)

        if len(Gx) < m:
            write("m")
            continue

        Gz = Gx.copy()

        Hx = find_stabilizers(Gz, Gx)
        Hz = find_stabilizers(Gx, Gz)

        if len(Hx) == h and len(Hz) == h:
            break

        write("H(%d,%d)" % (len(Hx), len(Hz)))

    print()
    return Gx, Gz, Hx, Hz
示例#7
0
文件: glue.py 项目: punkdit/qupy
def make_morthogonal(m, n, genus):
    while 1:
        G = rand2(m, n)
        if strong_morthogonal(G, genus) and rank(G) == m and numpy.min(
                G.sum(0)):
            break
    return G
示例#8
0
def rand_codes_slow(m, n, trials=10000):
    count = 0
    while count < trials:
        H = rand2(m, n)
        if rank(H) == m:
            yield H
            count += 1
示例#9
0
文件: glue.py 项目: punkdit/qupy
def make_ldpc(m, n, p=0.5, weight=None, dist=0):
    while 1:
        H = rand2(m, n, p, weight)
        d = classical_distance(H, dist)
        if d >= dist:
            break
    return H
示例#10
0
def sparsecss_SLOWSLOW(n, mx, mz, weight=3, **kw):

    print("sparsecss", n, mx, mz)
    k = n-mx-mz
    assert k>=0

    Hz = rand2(mz, n, weight=weight)
    Hx = rand2(mx, n, weight=weight)

    while 1:

        A = dot2(Hz, Hx.transpose())
        A %= 2

        rows = list(range(mz))
        cols = list(range(mx))

        if not A.max():
            break

        #print A.sum(),

        while A.max() and rows and cols:

            i = choice(rows)
            j = choice(cols)

            v = rand2(1, n, weight=weight)

            if random()<=0.5:

                A[i, :] = 0
                Hz[i] = v

                rows.remove(i)

            else:

                A[:, j] = 0
                Hx[j] = v

                cols.remove(j)

    C = CSSCode(Hx=Hx, Hz=Hz, **kw)
    return C
示例#11
0
文件: glue.py 项目: punkdit/qupy
def rand_full_rank(m, n=None):
    if n is None:
        n = m
    assert n >= m
    while 1:
        f = rand2(m, n)
        if rank(f) == m:
            break
    return f
示例#12
0
def rand_span(A):
    while 1:
        m, n = A.shape
        v = rand2(m, m)
        A1 = dot2(v, A)
        assert A1.shape == A.shape
        if rank(A) == rank(A1):
            break
    assert rank(intersect(A, A1)) == rank(A)
    return A1
示例#13
0
def sparsecss(n, mx, mz, weight=8, **kw):

    print("sparsecss", n, mx, mz)
    k = n-mx-mz
    assert k>=0

    vec = lambda n=n, weight=weight : rand2(1, n, weight=weight)

    Hz = zeros2(0, n)
    Hx = zeros2(0, n)

    Hx = append2(Hx, vec())

    while len(Hz)<mz or len(Hx)<mx:

        # append2 Hz
        rows = shortstr(Hz).split()
        #print rows
        while Hz.shape[0]<mz:
            v = vec()
            u = dot2(Hx, v.transpose())
            if u.sum() == 0 and shortstr(v) not in rows:
                Hz = append2(Hz, v)
                break
            
        # append2 Hx
        rows = shortstr(Hx).split()
        #print rows
        while Hx.shape[0]<mx:
            v = vec()
            u = dot2(Hz, v.transpose())
            if u.sum() == 0 and shortstr(v) not in rows:
                Hx = append2(Hx, v)
                break

        print(shortstrx(Hz, Hx))
        print()

    bits = []
    for i in range(n):
        if Hx[:, i].sum() == 0:
            bits.append(i)
        elif Hz[:, i].sum() == 0:
            bits.append(i)

    for i in reversed(bits):
        Hx = numpy.concatenate(
            (Hx[:, :i], Hx[:, i+1:]), axis=1)
        Hz = numpy.concatenate(
            (Hz[:, :i], Hz[:, i+1:]), axis=1)

    #print shortstrx(Hx, Hz)

    C = CSSCode(Hx=Hx, Hz=Hz, **kw)
    return C
示例#14
0
文件: glue.py 项目: punkdit/qupy
def glue_gcolor():
    from qupy.ldpc.gcolor import Lattice
    l = argv.get('l', 1)
    lattice = Lattice(l)
    #code = lattice.build_code()
    H = lattice.Hx
    print("H:", H.shape)
    print(shortstr(H))
    m, n = H.shape
    H1 = zeros2(m + 1, n + 1)
    H1[1:, 1:] = H
    H1[0, :] = 1
    #    print()
    #    print(shortstr(H1))
    #    for genus in range(1, 5):
    #        print(genus, strong_morthogonal(H1, genus))

    H = H1

    genus = argv.get("genus", 3)

    H = H.astype(numpy.int32)
    n = H.shape[1]

    if argv.scramble:
        R = rand2(m, m)
        H = dot2(R, H)

    print("H:", H.shape)
    print(shortstrx(H))
    assert dot2(H, H.transpose()).sum() == 0

    i0 = argv.get("i0", 0)
    i1 = argv.get("i1", i0)
    i2 = argv.get("i2", n)
    i3 = argv.get("i3", i2 + 1)
    # glue i0<-->i2 and i1<-->i3

    H2 = direct_sum(H, H)
    print(H2.shape)
    print(shortstrx(H2))
    assert strong_morthogonal(H2, genus)
    print()

    H3 = glue_self_classical(H2, [(i0, i2), (i1, i3)])
    print(H3.shape)
    print(shortstrx(H3))
    assert strong_morthogonal(H3, genus)

    print()
    print(shortstr((H2[:m, 1:n] + H3[:m, 1:n]) % 2))
    #print(eq2(H2[m+2:, i1+2:], H3[m:, i1:]))

    #print(classical_distance(H3))
    return H3
示例#15
0
def randcss(n, mx, mz, distance=None, **kw):
    """
    http://arxiv.org/abs/quant-ph/9512032
    Quantum error-correcting codes exist
    with asymptotic rate:
    k/n = 1 - 2H(2t/n) where 
    H(p) = -p log p - (1-p) log (1-p) and
    t = floor((d-1)/2).
    """

    while 1:
        k = n-mx-mz
        assert k>=0
    
        #print "rate:", 1.*k//n
        #H = lambda p: -p*log(p) - (1-p)*log(1-p)
        #d = 56 
        #print 1-2*H(1.*d//n) # works!
    
        Hz = rand2(mz, n)
    
        #print shortstrx(Hx)
    
        kern = numpy.array(solve.find_kernel(Hz))
    
        Hx = zeros2(mx, n)
        for i in range(mx):
            v = rand2(1, n-mx)
            Hx[i] = dot2(v, kern)
        C = CSSCode(Hx=Hx, Hz=Hz, **kw)

        if distance is None:
            break
        d = lookup_distance(C)
        if d < distance:
            continue
        d = lookup_distance(C.dual())
        if d < distance:
            continue
        break

    return C
示例#16
0
def random_code(n, k, kt, distance=1):
    "code length n, dimension k, transpose dimension kt"
    d = 0
    while d < distance:
        H = rand2(n - k, n)
        if rank(H) < n - k:
            continue
        d = classical_distance(H, distance)

    K = H
    dt = 0
    while dt < distance:
        R = rand2(kt, n - k)
        J = dot2(R, H)
        K = numpy.concatenate((H, J))
        if rank(K) < n - k:
            continue
        dt = classical_distance(K.transpose())

    return K
示例#17
0
def randselfdual(m, n, rw):

    assert rw%2 == 0
    H = solve.rand2(1, n, weight=rw)

    while len(H) < m:

        while 1:
            h = solve.rand2(1, n, weight=rw)
            if dot2(H, h.transpose()).sum() == 0:
                break
        H = numpy.concatenate((H, h))

    print(H)
    idxs = numpy.where(H.sum(0)!=0)[0]
    H = H[:, idxs]
    print(H)
    code = CSSCode(Hz=H, Hx=H)

    return code
示例#18
0
def rand_codes(m, n, trials=10000):
    assert 0<=m<=n
    k = n-m
    I = identity2(m)
    count = 0
    while count < trials:
        H = zeros2(m, n)
        A = rand2(m, k)
        H[:, :k] = A
        H[:, k:] = I
        yield H
        count += 1
示例#19
0
def get_codes(m, n):
    while 1:
        H = rand2(m, n)
        #H[0:2, :] = 0
        H[:, 0] = 0
        H[0, 0] = 1
        #H[0:2, 0:3] = A
        #print(shortstr(H))
        #print()
        if rank(H) < m:
            continue
        yield H
示例#20
0
def random_code(n, k, kt, distance=1):
    "return parity check for code of length n, dimension k, transpose dimension kt"
    d = 0
    while d<distance:
        H = rand2(n-k, n)
        if rank(H) < n-k:
            continue
        d = classical_distance(H, distance)

    K = H
    dt = 0
    while dt<distance:
        R = rand2(kt, n-k)
        J = dot2(R, H)
        K = numpy.concatenate((H, J))
        if rank(K) < n-k:
            continue
        dt = classical_distance(K.transpose())

    m = len(K)
    assert k - n + m - kt == 0 

    return K
示例#21
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()
示例#22
0
文件: glue.py 项目: punkdit/qupy
def glue_classical():

    from bruhat.triply_even import build

    genus = argv.get("genus", 3)

    m = argv.get("dim", 7)
    idx = argv.get("idx", 144)
    H = build.get(m, idx)
    H = H.astype(numpy.int32)
    n = H.shape[1]

    if argv.scramble:
        R = rand2(m, m)
        H = dot2(R, H)

    print(shortstrx(H))
    assert dot2(H, H.transpose()).sum() == 0

    i0 = argv.get("i0", 0)
    i1 = argv.get("i1", i0)
    i2 = argv.get("i2", n)
    i3 = argv.get("i3", i2 + 1)
    # glue i0<-->i2 and i1<-->i3

    #H2 = direct_sum(H, H)
    H2 = H
    #print(shortstrx(H2))
    assert strong_morthogonal(H2, genus)
    print()

    H3 = glue_self_classical(H2, [(i0, i2), (i1, i3)])
    print(shortstrx(H3))
    assert strong_morthogonal(H3, genus)

    print()
    print(shortstr((H2[:m, 1:n] + H3[:m, 1:n]) % 2))
    #print(eq2(H2[m+2:, i1+2:], H3[m:, i1:]))

    #print(classical_distance(H3))
    return H3
示例#23
0
def rand_span(H):
    op = dot2(rand2(1, len(H)), H)[0]
    return op
示例#24
0
文件: glue.py 项目: punkdit/qupy
def glue_classical_self():

    from bruhat.triply_even import build
    from bruhat.triply_even import codes24

    genus = argv.get("genus", 3)

    if argv.golay:
        H = codes24.get("g_{24}")
    else:
        m = argv.get("dim", 7)
        idx = argv.get("idx", 144)
        H = build.get(m, idx)

    H = shorten(H, 0)
    return

    H = H.astype(numpy.int32)
    count = argv.get("count", 1)
    if count == 0:
        print(H.shape)
        print(shortstrx(H))

    print("distance:", classical_distance(H))
    for ii in range(count):
        m, n = H.shape
        R = rand2(m, m)
        H = dot2(R, H)
        if ii == 0:
            print(H.shape)
            print(shortstrx(H))

        assert dot2(H, H.transpose()).sum() == 0

        #        i0 = argv.get("i0", 0)
        #        i1 = argv.get("i1", i0)
        #        i2 = argv.get("i2", 1)
        #        i3 = argv.get("i3", i2+1)

        items = list(range(n))
        i0 = random.choice(items)
        items.remove(i0)
        i1 = i0
        i2 = random.choice(items)
        items.remove(i2)
        i3 = random.choice(items)
        items.remove(i3)
        # glue i0<-->i2 and i1<-->i3

        print("strong_morthogonal(%d) = %s" %
              (genus, strong_morthogonal(H, genus)))
        print()

        H3 = glue_self_classical(H, [(i0, i2), (i1, i3)])
        print(H3.shape)
        print(shortstrx(H3))
        print("strong_morthogonal(%d) = %s" %
              (genus, strong_morthogonal(H3, genus)))
        H = H3

    print("distance:", classical_distance(H))
    return H
示例#25
0
def do_draw(c0, c1, d0, d1, Lx, Lz, Hx, Hz, idxs, LxHx, LzHz, **kw):

    draw = Draw(c0, c1, d0, d1)

    mark_xop = draw.mark_xop
    mark_zop = draw.mark_zop
    mark_idx = draw.mark_idx

    m, n = LxHx.shape

    assert rank(LxHx) == len(LxHx)
    assert rank(Hx) == len(Hx)
    assert rank(Lx) == len(Lx)
    #print(rank(LxHx))
    #print(rank(Hx))
    #print(rank(Lx))
    assert rank(Lx) + rank(Hx) == len(LxHx) + 1

    if 0:
        w = n
        best = None
        for i in range(10000):
            v = rand2(1, m)
            lop = dot2(v, LxHx)[0]
            #print(lop)
            if lop.sum() < w:
                best = lop
                w = lop.sum()
                print(w)

        mark_xop(best)

    all_idxs = list(range(c1 * d0 + c0 * d1))
    h_idxs, v_idxs = all_idxs[:c1 * d0], all_idxs[c1 * d0:]
    if 0:
        # find Hx stabilizers with horizontal support
        #for idx in h_idxs:
        #    mark_idx(idx)
        PHx = in_support(Hx, h_idxs)
        op = rand_span(PHx)
        mark_xop(op)
        # plenty...

    if 0:
        left = [draw.get_hidx(row, 0) for row in range(d0)]
        right = [draw.get_hidx(row, 5) for row in range(d0)]
        for idx in left + right:
            mark_idx(idx)
        PLx = in_support(LxHx, left + right)
        lop = rand_span(PLx)
        mark_xop(lop)

        PLx_left = in_support(LxHx, left)
        PLx_right = in_support(LxHx, right)

        PLx = numpy.concatenate((PLx_left, PLx_right))
        assert rank(PLx) == rank(PLx_left) + rank(PLx_right)

        U = solve(PLx.transpose(), lop)
        assert U is not None
        #print(U)

        draw.save("output.logop")

        return

    for op in Lx:
        #cl = color.rgb(0.2*random(), 0.2*random(), random(), 0.5)
        draw.mark_op(op, st_qubit=[blue] + st_thick, r=0.06, stroke=True)

    for op in Lz:
        #cl = color.rgb(0.2*random(), random(), 0.2*random(), 0.5)
        draw.mark_op(op, st_qubit=[green] + st_thick, r=0.12, stroke=True)

    for idx in idxs:
        draw.mark(idx, st_qubit=[red] + st_thick, r=0.16, stroke=True)

    correctable = draw.cvs
    #draw.save("output")

    rows = [[], []]

    margin = 0.2
    mkbox = lambda cvs: MarginBox(cvs, margin, 2 * margin)
    for op in Lx:
        draw = Draw(c0, c1, d0, d1)
        draw.mark_op(op, st_qubit=[blue] + st_thick, r=0.06, stroke=True)
        rows[0].append(mkbox(draw.cvs))

    for op in Lz:
        draw = Draw(c0, c1, d0, d1)
        draw.mark_op(op, st_qubit=[green] + st_thick, r=0.12, stroke=True)
        rows[1].append(mkbox(draw.cvs))

    row = [None] * len(Lx)
    row[0] = correctable
    rows.append(row)

    box = TableBox(rows)
    cvs = box.render()
    cvs.writePDFfile("output.pdf")
示例#26
0
def test_overlap(n, mx, mz, k, c0, c1, d0, d1, Hx, Hz, Lx, Lz, Lxi, Lzi, LxiHx,
                 LziHz, Ic0, Ic1, Id0, Id1, C, D, KerC, CokerD, KerD, CokerC,
                 **kw):

    if 0:
        # This makes len(idxs) much bigger, because we
        # end up with logops from many different rows/cols:
        Lx = shuff2(Lx)
        Lz = shuff2(Lz)

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

    def get_logops(idxs_C, idxs_Ct, idxs_D, idxs_Dt):

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

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

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

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

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

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

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

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

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

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

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

        return Lxi, Lzi

    print("get_bipuncture(C)")
    l_C, r_C = get_bipuncture(C)
    print("get_bipuncture(Ct)")
    l_Ct, r_Ct = get_bipuncture(C.transpose())
    print("get_bipuncture(D)")
    l_D, r_D = get_bipuncture(D)
    print("get_bipuncture(Dt)")
    l_Dt, r_Dt = get_bipuncture(D.transpose())
    print("done.")

    left_Lxi, left_Lzi = get_logops(l_C, l_Ct, l_D, l_Dt)
    right_Lxi, right_Lzi = get_logops(r_C, r_Ct, r_D, r_Dt)

    randvec = lambda U: dot2(rand2(1, len(U)), U)

    print("shapes:", left_Lxi.shape, right_Lzi.shape, left_Lzi.shape,
          right_Lxi.shape)
    #while 1:
    for trial in range(100):
        l_op = randvec(left_Lxi) * randvec(right_Lzi)  # intersection
        r_op = randvec(right_Lxi) * randvec(left_Lzi)  # intersection
        assert (l_op * r_op).sum() == 0
        op = l_op + r_op  # union
        idxs = numpy.where(op)[0]
        print("(%.2f)" % (len(idxs) / n), end="", flush=True)
        assert is_correctable(**locals())
    print()

    l_op = zeros2(n)
    for lx in left_Lxi:
        for lz in right_Lzi:
            lxz = lx * lz
            l_op += lxz

    r_op = zeros2(n)
    for lx in right_Lxi:
        for lz in left_Lzi:
            lxz = lx * lz
            r_op += lxz

    assert (l_op * r_op).sum() == 0
    op = l_op + r_op
    #op = l_op

    idxs = numpy.where(op)[0]
    print("--> (%.2f)\n" % (len(idxs) / n), end="", flush=True)

    #assert is_correctable(**locals())

    draw = Draw(c0, c1, d0, d1)
    for idx in idxs:
        draw.mark_idx(idx)

    if 0:
        #draw.mark_xop(Lx[0])
        for xop in Lxi:
            draw.mark_xop(xop)

        #draw.mark_zop(Lz[0])
        for zop in Lzi:
            draw.mark_zop(zop)

    # h_mark
    assert KerC.shape[1] == c1
    for j, op in enumerate(KerC):
        for i in range(c1):
            row = i
            col = -j - 1
            if op[i]:
                draw.h_mark(row, col, st_qubit=[green], stroke=True)
            else:
                draw.h_mark(row, col)

    assert CokerD.shape[1] == d0
    for j, op in enumerate(CokerD):
        #print(op)
        for i in range(d0):
            col = i
            #row = -j-1
            row = c1 + j
            if op[i]:
                draw.h_mark(row, col, st_qubit=[blue], stroke=True)
            else:
                draw.h_mark(row, col)

    # v_mark
    assert KerD.shape[1] == d1
    for j, op in enumerate(KerD):
        for i in range(d1):
            col = i
            #row = -j-1
            row = c0 + j
            if op[i]:
                draw.v_mark(row, col, st_qubit=[green], stroke=True)
            else:
                draw.v_mark(row, col)

    assert CokerC.shape[1] == c0
    for j, op in enumerate(CokerC):
        #print(op)
        for i in range(c0):
            row = i
            col = -j - 1
            if op[i]:
                draw.v_mark(row, col, st_qubit=[blue], stroke=True)
            else:
                draw.v_mark(row, col)

    draw.save("output.2")

    return is_correctable(**locals())
示例#27
0
文件: glue.py 项目: 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)
示例#28
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)