Ejemplo n.º 1
0
    def all_parts2(self):
        "all the ways to break self into two subsets"
        items = self.items
        n = len(items)
        #    if n==0:
        #        yield items, items
        #        return
        #
        #    if n==1:
        #        yield [], items
        #        yield items, []
        #        return
        #
        #    if n==2:
        #        yield [], items
        #        yield [items[0]], [items[1]]
        #        yield [items[1]], [items[0]]
        #        yield items, []
        #        return

        bits = [(0, 1)] * n
        for idxs in cross(bits):
            left = Set([items[i] for i in range(n) if idxs[i] == 0])
            right = Set([items[i] for i in range(n) if idxs[i] == 1])
            yield left, right
Ejemplo n.º 2
0
    def build_E8(cls, check=False):
        D8 = cls.build_D(8, check=check)
        half = Fraction(1, 2)
        roots = list(D8.roots)
        for signs in cross([(-1, 1)] * 8):
            r = reduce(mul, signs)
            if r != 1:
                continue
            root = tuple(sign * half for sign in signs)
            roots.append(root)

        assert len(roots) == 240

        simple = []
        for i in range(6):
            root = [0] * 8
            root[i] = 1
            root[i + 1] = -1
            simple.append(tuple(root))

        root = [0] * 8
        root[i] = 1
        root[i + 1] = 1
        simple.append(tuple(root))

        root = [-half] * 8
        simple.append(tuple(root))

        return Weyl_E8.buildfrom_simple(roots,
                                        simple,
                                        name="E_8",
                                        order=696729600,
                                        check=check)
Ejemplo n.º 3
0
 def dist(self):
     "depth-first _apply dist"
     if not self:
         return self
     op = self[0].dist()
     i = 1
     while i < len(self):
         op = op * self[i].dist()
         i += 1
     itemss = []
     for item in self:
         if isinstance(item, (Var, Integer, Reciprocal)):
             itemss.append([item])
         elif isinstance(item, Add):
             itemss.append(item.items)
         else:
             assert 0, repr(item)
     ops = []
     for items in cross(itemss):
         ops.append(reduce(mul, items))
     assert len(ops)
     if len(ops) == 1:
         op = ops[0]
     else:
         op = Add(ops)
     return op
Ejemplo n.º 4
0
 def all_states(self):
     N = self.N
     ceil = self.ceil
     itemss = [list(range(ceil[idx])) for idx in range(1, N)]
     for values in cross(itemss):
         state = self.make_state(values)
         yield state
Ejemplo n.º 5
0
def get_cell(row, col, p=2):
    """
        return all matrices in bruhat cell at (row, col)
        These have shape (col, col+row).
    """

    if col == 0:
        yield zeros(0, row)
        return

    if row == 0:
        yield identity(col)
        return

    # recursive steps:
    m, n = col, col + row
    for left in get_cell(row, col - 1, p):
        A = zeros(m, n)
        A[:m - 1, :n - 1] = left
        A[m - 1, n - 1] = 1
        yield A

    els = list(range(p))
    vecs = list(cross((els, ) * m))
    for right in get_cell(row - 1, col, p):
        for v in vecs:
            A = zeros(m, n)
            A[:, :n - 1] = right
            A[:, n - 1] = v
            yield A
Ejemplo n.º 6
0
    def __init__(self, ring, mod):
        ModuloRing.__init__(self, ring, mod)
        assert isinstance(ring, PolynomialRing)
        assert mod[mod.deg] == 1 # monic
        dim = mod.deg
        assert dim>1
        one = ring.one # unwrapped
        x = ring.x # unwrapped
        basis = [one, x]
        for i in range(dim-2):
            basis.append(basis[-1]*x)
        self.basis = basis # unwrapped
        elements = []
        els = list(ring.base.get_elements())
        for idx in cross((els,)*dim):
            a = ring.zero # unwrapped
            for i, coeff in enumerate(idx):
                a = a + coeff * basis[i]
            a = ModuloElement(a, self) # wrap
            elements.append(a)
        self.elements = elements
        assert len(elements) == len(els) ** dim, len(elements)

        self.mod = mod 
        self.zero = ModuloElement(ring.zero, self)
        self.one = ModuloElement(one, self)
        self.x = ModuloElement(x, self)
Ejemplo n.º 7
0
def all_act(n, m):
    itemss = [tuple(range(m))] * (n - 1) * m
    for idxs in cross(itemss):
        act = table(n, m)
        for i in range(m):
            act[0, i] = i  # identity is always zero
        for i in range(n - 1):
            for j in range(m):
                act[1 + i, j] = idxs[i + (n - 1) * j]
        yield act
Ejemplo n.º 8
0
 def build_F4(cls, **kw):
     roots = []
     idxs = range(4)
     for root in cross([(-1, 0, 1)] * 4):
         d = sum(root[i]**2 for i in idxs)
         if d == 1 or d == 2:
             roots.append(root)
     half = Fraction(1, 2)
     for root in cross([(-half, 0, half)] * 4):
         d = sum(root[i]**2 for i in idxs)
         if d == 1 or d == 2:
             roots.append(root)
     assert len(roots) == 48
     simple = [(1, -1, 0, 0), (0, 1, -1, 0), (0, 0, 1, 0),
               (-half, -half, -half, -half)]
     return Weyl_F.buildfrom_simple(roots,
                                    simple,
                                    name="F_4",
                                    order=1152,
                                    **kw)
Ejemplo n.º 9
0
 def build_G2(cls, **kw):
     roots = []
     for root in cross([(-2, -1, 0, 1, 2)] * 3):
         if sum(root) != 0:
             continue
         d = sum(root[i]**2 for i in range(3))
         if d == 2 or d == 6:
             roots.append(root)
     assert len(roots) == 12
     simple = [(1, -1, 0), (-1, 2, -1)]
     return Weyl_G.buildfrom_simple(roots, simple, name="G_2", **kw)
Ejemplo n.º 10
0
def all_mul(n):
    itemss = [tuple(range(n))] * (n - 1) * (n - 1)
    for idxs in cross(itemss):
        mul = table(n, n)
        for i in range(n):
            mul[0, i] = i  # identity is always zero
            mul[i, 0] = i  # identity is always zero
        for i in range(n - 1):
            for j in range(n - 1):
                mul[1 + i, 1 + j] = idxs[i + (n - 1) * j]
        yield mul
Ejemplo n.º 11
0
def all_subsets(els):
    els = tuple(els)
    n = len(els)
    if n == 0:
        yield ()
        return
    if n == 1:
        yield ()
        yield els
        return
    bits = [(0, 1)] * n
    for select in cross(bits):
        items = tuple(els[i] for i in range(n) if select[i])
        yield items
Ejemplo n.º 12
0
 def getitem(self, idx):
     idxs = list(range(idx+1))
     n = self.n
     child = self.child
     ring = self.ring
     value = ring.zero
     for jdxs in cross([idxs]*(n-1)):
         total = 0
         walue = ring.one
         for j in jdxs:
             walue *= child[j]
             total += j
         if total <= idx:
             walue *= child[idx-total]
             value += walue
     return value
Ejemplo n.º 13
0
 def __getitem__(self, U):
     F = self.F
     G = self.G
     #        print("ComposeSpecies.__getitem__", F, G, U)
     items = []
     for p in U.all_partitions():
         # the partition p is a Set of Set's (subsets of U)
         #            print("partition:", p)
         factors = []
         for V in p:
             #                print("V = %s, len(V)=%s, G[V] = %s" % (V, len(V), G[V]))
             factors.append(tuple(G[V]))
         for struct in F[p]:
             #                print("F[p]:", struct)
             #item = Set.mul_many([struct] + factors)
             for item in cross(factors):
                 yield (struct, item)
Ejemplo n.º 14
0
def main():

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

    field = FiniteField(p)
    ring = PolynomialRing(field)
    x = ring.x

    found = set()
    items = [list(field.elements)] * p
    for cs in cross(items):
        f = ring.zero
        for c in cs:
            f = x * f
            f = f + c
        vals = tuple(f(j) for j in field.elements)
        found.add(vals)
        print(' '.join([str(v) for v in vals]))
    print(len(found), p**p)
Ejemplo n.º 15
0
def all_monomials(vs, deg, ring):
    n = len(vs)
    assert n>0
    if n==1:
        v = vs[0]
        yield v**deg
        return

    items = list(range(deg+1))
    for idxs in cross((items,)*(n-1)):
        idxs = list(idxs)
        remain = deg - sum(idxs)
        if remain < 0:
            continue
        idxs.append(remain)
        p = Poly({():1}, ring)
        assert p==1
        for idx, v in zip(idxs, vs):
            p = p * v**idx
        yield p
Ejemplo n.º 16
0
 def find_irreducible(ring, deg):
     assert isinstance(ring.base, FiniteField)
     assert deg > 1 
     field = ring.base
     x = ring.x
     vals = list(range(field.p))
     poly = None
     for coefs in cross([vals]*deg):
         #f = ring.promote(coefs[0])
         f = ring.one
         for c in coefs:
             f = x*f + c 
         #print(coefs, f)
         for i in range(field.p):
             if f(i)==0:
                 break
         else:
             poly = f 
         if poly is not None:
             break
     return poly
Ejemplo n.º 17
0
    def all_trees(self):
        # A tree is a sequence of partitions of self,
        # each succesively refining the next, including top and bot.
        # See: https://oeis.org/A000311
        items = self.items
        top = Set((self, ))
        if len(items) == 0:
            return
        if len(items) == 1:
            yield (top, )  # top == bot
            return
        if len(items) == 2:
            a, b = self
            bot = Set([Set([a]), Set([b])])
            yield (top, bot)
            return

        for partition in self.all_partitions():
            if len(partition) == 1:
                continue
            if len(partition) == len(self):
                yield (top, partition)  # top, bot
                continue
            stack = []  # not a stack
            for part in partition:
                trees = list(part.all_trees())
                stack.append(trees)
            for section in cross(stack):
                n = max(len(tree) for tree in section)
                result = [partition]
                for i in range(n):
                    items = [tree[min(i,
                                      len(tree) - 1)]
                             for tree in section]  # brain hurts...
                    items = Set(items)
                    result.append(items)
                yield tuple(result)
Ejemplo n.º 18
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) 
Ejemplo n.º 19
0
def main():

    d = argv.get("d", 3)
    assert d>=2

    double = argv.double

    if d==2:
        ring = CyclotomicRing(4)
        #ring = element.Z
        gamma = ring.x
        w = gamma**2
        assert w == -1
        double = True

    else:
        ring = CyclotomicRing(d**2)
        gamma = ring.x
        w = gamma**d

    I = numpy.zeros((d, d), dtype=object)
    wI = numpy.zeros((d, d), dtype=object)
    X = numpy.zeros((d, d), dtype=object)
    Z = numpy.zeros((d, d), dtype=object)
    Zdag = numpy.zeros((d, d), dtype=object)
    S = numpy.zeros((d, d), dtype=object)
    Sdag = numpy.zeros((d, d), dtype=object)
    T = numpy.zeros((d, d), dtype=object)
    Tdag = numpy.zeros((d, d), dtype=object)
    for j in range(d):
        I[j, j] = 1
        wI[j, j] = w
        X[j, (j+1)%d] = 1
        Z[j, j] = w**j
        Zdag[j, j] = w**(d-j)

        if d==2:
            val = gamma**(j**2)
            ival = gamma**(d**2 - (j**2)%(d**2))
        else:
            val = w**(j**2)
            ival = w**(d - (j**2)%d)
        assert val*ival == 1

        S[j, j] = val
        Sdag[j, j] = ival

        if d in [2, 3, 6]:
            val = gamma**(j**3)
            ival = gamma**(d**2 - (j**3)%(d**2))
        else:
            val = w**(j**3)
            ival = w**(d - (j**3)%d)
        assert val*ival == 1

        T[j, j] = val
        Tdag[j, j] = ival

    qu = Space(d, ring)
    hom = Hom(qu, qu)

    I = Map.from_array(I, hom)
    wI = Map.from_array(wI, hom)
    Xdag = Map.from_array(X.transpose(), hom)
    X = Xs = Map.from_array(X, hom)
    Z = Map.from_array(Z, hom)
    Zdag = Map.from_array(Zdag, hom)
    S = Map.from_array(S, hom)
    Sdag = Map.from_array(Sdag, hom)
    T = Map.from_array(T, hom)
    Tdag = Map.from_array(Tdag, hom)

    if d==2:
        Y = gamma*X*Z # ?
    else:
        Y = w*X*Z # ?

    assert S*Sdag == I

    assert Z*Zdag == I
    assert X*Xdag == I

    if d>2:
        for j in range(1, d+1):
            assert (j==d) == (X**j==I)
            assert (j==d) == (Z**j==I)
    else:
        assert X != I
        assert Z != I
        assert X*X == I
        assert Z*Z == I

    assert Z*X == (w**(d-1))*X*Z

    if double:
        pauli = mulclose([X, Z, gamma*I])
        names = mulclose_names([X, Z, gamma*I], "X Z i".split())

    else:
        pauli = mulclose([X, Z])
        names = mulclose_names([X, Z, Xdag, Zdag, -I], "X Z Xi Zi -I".split())

    pauli = set(pauli)
    print("pauli:", len(pauli))
    assert Zdag in pauli
    assert Xdag in pauli

    if d<6:
        # slow..
        lhs = atpow(X, d)
        rhs = atpow(Z, d)
        assert lhs * rhs == rhs * lhs
    
    lhs = X@X
    rhs = Z@Zdag
    assert lhs * rhs == rhs * lhs

    lhs = X@(X**(d-1))
    rhs = Z@Z
    assert lhs * rhs == rhs * lhs

    if 0:
        n = 5
        ops = [X, Xdag]
        lhs = []
        for op in cross([ops]*n):
            op = reduce(matmul, op)
            lhs.append(op) 
    
        ops = [Z, Zdag]
        rhs = []
        for op in cross([ops]*n):
            op = reduce(matmul, op)
            rhs.append(op) 
    
        for l in lhs:
          for r in rhs:
            if l*r == r*l:
                print("/", end=" ", flush=True)
            else:
                print(".", end=" ", flush=True)
        print()

    print("S =")
    print(S)
    print("XSX =")
    print(X*S*X)
    print("XSXS =")
    print(X*S*X*S)
    
    #print("Y =")
    #print(Y)
    #print("S*X*Sdag =")
    #print(S*X*Sdag)
    assert Y == S*X*Sdag

    def get_orbit(g, gi, v):
        orbit = [v]
        while 1:
            u = g*orbit[-1]*gi
            if u == orbit[0]:
                break
            orbit.append(u)
        return orbit

    print("S orbit:")
    for A in [X, Z]:
        print('\t', [''.join(names[op]) for op in get_orbit(S, Sdag, A)])

    U = X*S
    Ui = Sdag * Xdag
    assert U*Ui == I

    print("XS orbit:")
    for A in [X, Z]:
        print('\t', [''.join(names[op]) for op in get_orbit(U, Ui, A)])

    U = X*X*S
    Ui = Sdag * Xdag * Xdag
    assert U*Ui == I

    print("XXS orbit:")
    for A in [X, Z]:
        print('\t', [''.join(names[op]) for op in get_orbit(U, Ui, A)])

    return

    inverse = {}
    for g in pauli:
      for h in pauli:
        if g*h == I:
            inverse[g] = h
            inverse[h] = g

    def is_cliff(A, Ai):
        assert A*Ai == I
        for g in pauli:
            h = A*g*Ai
            if h not in pauli:
                return False
        return True
    print("S =")
    print(S)
    print("S**2 =")
    print(S**2)
    print("Sdag =")
    print(Sdag)
    assert is_cliff(S, Sdag)

    #print("is_cliff:", (S in pauli), is_cliff(S, Sdag))

    def is_third_level(A, Ai):
        assert A*Ai == I
        for g in pauli:
            gi = inverse[g]
            h = A*g*Ai*gi
            hi = g*A*gi*Ai
            if not is_cliff(h, hi):
                return False
        return True

    print("is_pauli(S)", S in pauli)
    print("is_cliff(S)", is_cliff(S, Sdag))
    #print("is_third_level(S)", is_third_level(S, Tdag))

    print("is_pauli(T)", T in pauli)
    print("is_cliff(T)", is_cliff(T, Tdag))
    print("is_third_level(T)", is_third_level(T, Tdag))
        

    print("OK")
Ejemplo n.º 20
0
Theorem: It is not possible to assign values phi in {-1, 1} to 
every member of the 2-qubit pauli group such that
    phi(XI)*phi(IX)*phi(XX) = 1
    phi(IZ)*phi(ZI)*phi(ZZ) = 1
    phi(XZ)*phi(ZX)*phi(YY) = 1
    phi(XI)*phi(IZ)*phi(XZ) = 1
    phi(IX)*phi(ZI)*phi(ZX) = 1
    phi(XX)*phi(ZZ)*phi(YY) = -1
"""

items = "XI IX XX IZ ZI ZZ XZ ZX YY".split()
XI, IX, XX, IZ, ZI, ZZ, XZ, ZX, YY = items

n = len(items)

for vals in cross([(-1, 1)] * n):
    phi = {}
    for idx, item in enumerate(items):
        phi[items[idx]] = vals[idx]

    if (phi[XI] * phi[IX] * phi[XX] == 1 and phi[IZ] * phi[ZI] * phi[ZZ] == 1
            and phi[XZ] * phi[ZX] * phi[YY] == 1
            and phi[XI] * phi[IZ] * phi[XZ] == 1
            and phi[IX] * phi[ZI] * phi[ZX] == 1
            and phi[XX] * phi[ZZ] * phi[YY] == -1):

        for idx, item in enumerate(items):
            print("phi(%s)=%s " % (item, phi[item]), end=" ")
            if (idx + 1) % 3 == 0:
                print()
        break
Ejemplo n.º 21
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)
Ejemplo n.º 22
0
def triortho():
    code = get_code()

    code.dump()
    print(code)

    Gx = []
    for u in code.G:
        print(shortstr(u), u.sum()%2)
        parity = u.sum()%2
        if parity==0:
            Gx.append(u)
    Gx = array2(Gx)

    print("is_triorthogonal:", code.is_triorthogonal())

    A = array2(list(span(Gx)))
    print("span(Gx) is_morthogonal(2):", is_morthogonal(A, 2))
    print("span(Gx) is_morthogonal(3):", is_morthogonal(A, 3))

    return

    G = code.G

#    A = array2(list(span(G)))
#    poly = {}
#    for v in A:
#        w = v.sum()
#        poly[w] = poly.get(w, 0) + 1
#    print(poly)

    k, n = G.shape

    if 0:
        from comm import Poly
        a = Poly({(1,0):1})
        b = Poly({(0,1):1})
        poly = Poly.zero(2)
        for v in span(G):
            w = v.sum()
            term = Poly({(n-w,0) : 1}) * Poly({(0,w) : 1})
            poly = poly + term
        print(poly)

    # print higher genus weight enumerator
    genus = argv.get("genus", 1)
    assert 1<=genus<=4
    N = 2**genus
    idxs = list(cross([(0,1)]*genus))

    cs = {} # _coefficients : map exponent to coeff
    for vs in cross([list(span(G)) for _ in range(genus)]):
        key = [0]*N
        for i in range(n):
            ii = tuple(v[i] for v in vs)
            idx = idxs.index(ii)
            key[idx] += 1
        key = tuple(key)
        cs[key] = cs.get(key, 0) + 1
    #print(cs)
    keys = list(cs.keys())
    keys.sort()
    print(idxs)
    for key in keys:
        print(key, cs[key])
Ejemplo n.º 23
0
def find_stabilizer_code(H):
    H = H.strip().split()
    H = [list(row) for row in H]
    H = numpy.array(H)
    m, n = H.shape
    #print(H)

    import z3
    from z3 import Bool, And, Or, Not, Implies, If, Solver

    vs = {}
    clauses = []
    solver = Solver()
    for i in range(m):
        for j in range(n):
            c = H[i, j]
            if c == '.':
                continue
            X = Bool("X_%d_%d" % (i, j))
            Z = Bool("Z_%d_%d" % (i, j))
            vs[i, j] = (X, Z)
            if c == 'I':
                # X or Z and not both
                solver.add(Or(X, Z))
                solver.add(Not(And(X, Z)))
            elif c == 'X':
                # freeze this as X
                solver.add(X)
                solver.add(Not(Z))
            elif c == 'Z':
                # freeze this Z
                solver.add(Not(X))
                solver.add(Z)
            elif c == 'Y':
                # freeze this as X and Z
                solver.add(X)
                solver.add(Z)
            else:
                assert 0, (i, j, c)

    for i in range(m):
        for j in range(i + 1, m):
            bits = []
            for k in range(n):
                if H[i, k] == '.' or H[j, k] == '.':
                    continue
                bits.append(k)
            if not bits:
                continue
            #print()
            #print(i, j, bits)
            for lhs in cross([(0, 1)] * len(bits)):
                lvars = [vs[i, k][l] for (k, l) in zip(bits, lhs)]
                #print(lhs, lvars)
                for rhs in cross([(0, 1)] * len(bits)):
                    rvars = [vs[j, k][r] for (k, r) in zip(bits, rhs)]
                    syndrome = len([
                        idx for idx in range(len(bits)) if lhs[idx] != rhs[idx]
                    ]) % 2
                    #print('\t', rhs, rvars, syndrome)
                    if syndrome:
                        clause = Not(And(*lvars, *rvars))
                        #print('\t', clause)
                        solver.add(clause)

    result = solver.check()
    if result != z3.sat:
        return None

    H = numpy.empty((m, n), dtype=object)
    H[:] = '.'
    model = solver.model()
    for key, XZ in vs.items():
        #for v in XZ:
        #print(v, model.evaluate(v))
        X, Z = XZ
        X = model.evaluate(X)
        Z = model.evaluate(Z)
        assert X or Z
        assert not (X and Z)
        if X:
            H[key] = 'X'
        if Z:
            H[key] = 'Z'

    H = ("\n".join(''.join(row) for row in H))
    return H
Ejemplo n.º 24
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) 
Ejemplo n.º 25
0
def GF(q):
    ps = factorize(q)
    assert len(set(ps)) == 1
    p = ps[0]
    r = len(ps)
    assert q == p**r
    #print(p, r)

    field = FiniteField(p)
    if r == 1:
        return field

    ring = PolynomialRing(field)

    zero = ring.zero
    one = ring.one
    x = ring.x

    itemss = [tuple(range(p)) for i in range(r)]
    for idxs in cross(itemss):
        poly = x**r
        for i, idx in enumerate(idxs):
            poly += idx * (x**i)
        #print(poly)
        for i in range(p):
            if poly(i) == zero:
                #print("i=", i)
                break
        else:
            break
    #print("poly:", poly)
    #print([str(poly(i)) for i in range(p)])

    F = GaloisField(ring, poly)

    def frobenius(a):
        return a**p

    def hermitian(a, b):
        return a * (b**p)

    def trace_hermitian(a, b):
        return (a**p) * b + a * (b**p)

    F.frobenius = frobenius
    F.hermitian = hermitian

    one = F.one
    zero = F.zero

    def order(u):
        count = 1
        v = u
        assert v != zero
        while v != one:
            v = u * v
            count += 1
            assert count < 2 * q
        return count

    for u in F.elements:
        if u == zero:
            continue
        #print(u, order(u))
        if order(u) == q - 1:
            F.omega = u  # generator of multiplicative group
            break
    else:
        assert 0
    return F
Ejemplo n.º 26
0
def ffield():
    "look for finite field solutions"

    p = argv.get("p", 3)
    dim = argv.get("dim", 3)
    dim2 = dim**2

    I = empty((dim, dim), dtype=int)
    I[:] = 0
    for i in range(dim):
        I[i, i] = 1
    #print(I)

    SWAP = empty((dim, dim, dim, dim), dtype=int)
    SWAP[:] = 0
    for i in range(dim):
        for j in range(dim):
            SWAP[i, j, j, i] = 1
    SWAP.shape = dim2, dim2
    #print(SWAP)

    assert alltrue(dot(SWAP, SWAP) == tensor(I, I))

    # -----------------------------------------------------------
    # Build some Frobenius algebra's ... find the copyable states

    system = System()

    F = system.array(dim, dim**2, "F")  # mul
    G = system.array(dim, 1, "G")  # unit

    D = system.array(dim**2, dim, "D")  # comul
    E = system.array(1, dim, "E")  # counit

    #for item in system.items:
    #    print(item)

    IF = tensor(I, F)
    FI = tensor(F, I)

    IG = tensor(I, G)
    GI = tensor(G, I)

    ID = tensor(I, D)
    DI = tensor(D, I)

    IE = tensor(I, E)
    EI = tensor(E, I)

    # unit
    system.add(compose(IG, F), I)
    system.add(compose(GI, F), I)

    # _assoc
    system.add(compose(FI, F), compose(IF, F))

    # commutative
    commutative = argv.get("commutative", True)
    if commutative:
        system.add(F, compose(SWAP, F))

    # counit
    system.add(compose(D, IE), I)
    system.add(compose(D, EI), I)

    # _coassoc
    system.add(compose(D, DI), compose(D, ID))

    # cocommutative
    #system.add(D, compose(D, SWAP))

    # Frobenius
    system.add(compose(DI, IF), compose(F, D))
    system.add(compose(ID, FI), compose(F, D))

    # special
    special = argv.get("special", True)
    if special:
        system.add(compose(D, F), I)

    # https://theory.stanford.edu/~nikolaj/programmingz3.html
    import z3

    def all_smt(s, initial_terms):
        def block_term(s, m, t):
            s.add(t != m.eval(t, model_completion=True))

        def fix_term(s, m, t):
            s.add(t == m.eval(t, model_completion=True))

        def all_smt_rec(terms):
            if z3.sat == s.check():
                m = s.model()
                yield m
                for i in range(len(terms)):
                    s.push()
                    block_term(s, m, terms[i])
                    for j in range(i):
                        fix_term(s, m, terms[j])
                    yield from all_smt_rec(terms[i:])
                    s.pop()

        yield from all_smt_rec(list(initial_terms))

    def block_model(s):
        m = s.model()
        s.add(z3.Or([f() != m[f] for f in m.decls() if f.arity() == 0]))

    ns = {}
    clauses = []
    for v in system.vs:
        v = str(v)
        iv = z3.Int(v)
        ns[v] = iv
        clauses.append(iv < p)
        clauses.append(0 <= iv)
    print(ns)

    for eq in system.eqs:
        eq = eval(str(eq), ns) % p == 0
        clauses.append(eq)

    solver = z3.Solver()

    for c in clauses:
        solver.add(c)


#    print("solve...")
#    result = solver.check()
#    assert result == z3.sat, result
#    print("done.")

#for model in all_smt(solver, []):

    while solver.check() == z3.sat:
        model = solver.model()

        values = {}
        for d in model:
            #print(d, model[d])
            values[str(d)] = int(str(model[d]))
        print(values)

        items = []
        for A in system.items:
            B = numpy.zeros(A.shape, int)
            for idx in numpy.ndindex(A.shape):
                B[idx] = values[str(A[idx])]
            items.append(B)

        F, G, D, E = items
        print(F)

        for vals in cross([tuple(range(dim))] * dim):
            v = numpy.array(vals)
            v.shape = (dim, 1)
            if v.sum() == 0:
                continue
            lhs = dot(D, v)
            rhs = tensor(v, v)
            if numpy.allclose(lhs, rhs):
                print(v.transpose())

        block_model(solver)
        print()

    print("done")
Ejemplo n.º 27
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()
Ejemplo n.º 28
0
def main():

    d = 2

    ring = CyclotomicRing(8)
    #ring = element.Z
    e = ring.x
    gamma = e**2
    w = gamma**2
    assert w == -1

    I = numpy.zeros((d, d), dtype=object)
    wI = numpy.zeros((d, d), dtype=object)
    X = numpy.zeros((d, d), dtype=object)
    Z = numpy.zeros((d, d), dtype=object)
    Zdag = numpy.zeros((d, d), dtype=object)
    S = numpy.zeros((d, d), dtype=object)
    Sdag = numpy.zeros((d, d), dtype=object)
    T = numpy.zeros((d, d), dtype=object)
    Tdag = numpy.zeros((d, d), dtype=object)
    for j in range(d):
        I[j, j] = 1
        wI[j, j] = w
        X[j, (j + 1) % d] = 1
        Z[j, j] = w**j
        Zdag[j, j] = w**(d - j)

        val = [1, gamma][j]
        ival = [1, -gamma][j]
        assert val * ival == 1

        S[j, j] = val
        Sdag[j, j] = ival

        val = [1, e][j]
        ival = [1, e**7][j]
        assert val * ival == 1

        T[j, j] = val
        Tdag[j, j] = ival

    qu = Space(d, ring)
    hom = Hom(qu, qu)

    I = Map.from_array(I, hom)
    wI = Map.from_array(wI, hom)
    Xdag = Map.from_array(X.transpose(), hom)
    X = Xs = Map.from_array(X, hom)
    Z = Map.from_array(Z, hom)
    Zdag = Map.from_array(Zdag, hom)
    S = Map.from_array(S, hom)
    Sdag = Map.from_array(Sdag, hom)
    T = Map.from_array(T, hom)
    Tdag = Map.from_array(Tdag, hom)

    Y = w * X * Z  # ?

    assert S * Sdag == I
    assert S * S == Z
    assert T * T == S

    assert Z * Zdag == I
    assert X * Xdag == I

    if d > 2:
        for j in range(1, d + 1):
            assert (j == d) == (X**j == I)
            assert (j == d) == (Z**j == I)
    else:
        assert X != I
        assert Z != I
        assert X * X == I
        assert Z * Z == I

    assert Z * X == (w**(d - 1)) * X * Z

    pauli = mulclose([X, Z, gamma * I])
    pauli = set(pauli)
    print("pauli:", len(pauli))
    assert Zdag in pauli
    assert Xdag in pauli

    if d < 6:
        # slow..
        lhs = atpow(X, d)
        rhs = atpow(Z, d)
        assert lhs * rhs == rhs * lhs

    lhs = X @ X
    rhs = Z @ Zdag
    assert lhs * rhs == rhs * lhs

    lhs = X @ (X**(d - 1))
    rhs = Z @ Z
    assert lhs * rhs == rhs * lhs

    if 0:
        n = 5
        ops = [X, Xdag]
        lhs = []
        for op in cross([ops] * n):
            op = reduce(matmul, op)
            lhs.append(op)

        ops = [Z, Zdag]
        rhs = []
        for op in cross([ops] * n):
            op = reduce(matmul, op)
            rhs.append(op)

        for l in lhs:
            for r in rhs:
                if l * r == r * l:
                    print("/", end=" ", flush=True)
                else:
                    print(".", end=" ", flush=True)
        print()

    #print(Z@Z@Z)

    #print(Y)
    #print(S*X*Sdag)
    #print(Y == S*X*Sdag)
    if d == 3:
        assert (Y == S * X * Sdag)

    inverse = {}
    for g in pauli:
        for h in pauli:
            if g * h == I:
                inverse[g] = h
                inverse[h] = g

    def is_cliff(A, Ai):
        assert A * Ai == I
        for g in pauli:
            h = A * g * Ai
            if h not in pauli:
                return False
        return True

    print(S)
    print(Sdag)
    assert is_cliff(S, Sdag)

    #print("is_cliff:", (S in pauli), is_cliff(S, Sdag))

    def is_third_level(A, Ai):
        assert A * Ai == I
        for g in pauli:
            gi = inverse[g]
            h = A * g * Ai * gi
            hi = g * A * gi * Ai
            if not is_cliff(h, hi):
                return False
        return True

    print("is_pauli(S)", S in pauli)
    print("is_cliff(S)", is_cliff(S, Sdag))
    #print("is_third_level(S)", is_third_level(S, Tdag))

    print("is_pauli(T)", T in pauli)
    print("is_cliff(T)", is_cliff(T, Tdag))
    print("is_third_level(T)", is_third_level(T, Tdag))

    #C2 = mulclose([X, T, H])

    print("OK")
Ejemplo n.º 29
0
def super_young(U, V, part):
    ring = U.ring

    n = sum(part)

    lookup = {}
    summands = []
    for idxs in cross([(0, 1)] * n):
        spaces = [[U, V][idx] for idx in idxs]
        space = reduce(matmul, spaces)
        lookup[idxs] = len(summands)
        summands.append(space)
        #print(idxs, end=" ")
        #print(space.n)

    src = reduce(add, summands)

    G = Group.symmetric(n)
    hom = {}

    colim = src.identity()
    for action in G:
        perm = tuple(action[i] for i in range(n))
        #print(perm)
        sumswap = [None] * len(summands)
        fs = []
        for i, idxs in enumerate(cross([(0, 1)] * n)):
            jdxs = tuple(idxs[i] for i in perm)
            #print(idxs, "-->", jdxs)
            sumswap[lookup[jdxs]] = i
            space = src.items[i]
            f = space.get_swap(perm)
            fs.append(f)
        #print(sumswap)
        f = reduce(dsum, fs)
        #print(f.src.name, "-->", f.tgt.name)
        g = f.tgt.get_swap(sumswap)
        #print(g.src.name, "-->", g.tgt.name)
        assert f.tgt == g.src
        assert g.tgt == src
        hom[action] = (g, f)
        #print()

    young = Young(G, part)
    #print("Young:")
    #print(young)

    rowperms = young.get_rowperms()
    colperms = young.get_colperms()
    #print("rowperms", len(rowperms))
    #print("colperms", len(colperms))

    horiz = None
    for action in rowperms:
        (g, f) = hom[action]
        gf = g * f
        horiz = gf if horiz is None else (horiz + gf)
    assert horiz is not None

    vert = None
    for action in colperms:
        sign = action.sign() * ring.one
        g, f = hom[action]
        g = sign * g
        gf = g * f
        vert = gf if vert is None else (vert + gf)
    assert vert is not None
    P = horiz * vert

    P = P.row_reduce()
    #print(P.rank())
    #print(P)

    #for a in src.items:
    #    print(a)

    even = src.identity()
    odd = src.identity()
    i = 0
    j = 0
    for space in src.items:
        j += space.n
        while i < j:
            if space.grade % 2 == 0:
                odd[i, i] = ring.zero
            else:
                even[i, i] = ring.zero
            i += 1

    return (P * even).rank(), (P * odd).rank()