def counit(A): assert isinstance(A, Cell1) src = A * A.dual tgt = Cell1.identity(A.tgt) assert tgt.hom == src.hom shape = tgt.shape n = shape[0] assert n == shape[1] rig = A.rig ring = rig.ring linss = [] for i in range(n): lins = [] # row for k in range(n): t, s = tgt[i, k], src[i, k] if i != k: lin = Lin.zero(t, s) else: # argh... why can't we direct_sum the Lin.counit's ? a = elim.zeros(ring, t.n, s.n) idx = 0 for j in range(A.shape[1]): counit = Lin.counit(rig.one, A[i, j]) a[:, idx:idx + counit.shape[1]] = counit.A idx += counit.shape[1] assert idx == s.n lin = Lin(t, s, a) lins.append(lin) linss.append(lins) return Cell2(tgt, src, linss)
def randchain(ring, n, m): V = Space(ring, n, 1, "V") U = Space(ring, m, 0, "U") B = Lin.rand(U, V) A = B.kernel() A = Lin(A.tgt, A.src.asgrade(2), A.A) # yikes assert (B * A).is_zero() C = B.cokernel() C = Lin(C.tgt.asgrade(-1), C.src, C.A) assert (C * B).is_zero() c = Chain([A, B, C]) return c
def zero(cls, tgt, src): # tgt <---- src assert isinstance(tgt, Cell1) assert isinstance(src, Cell1) assert tgt.rig == src.rig assert tgt.hom == src.hom rig = tgt.rig rows, cols = tgt.shape linss = [[Lin.zero(tgt[i, j], src[i, j]) for j in range(cols)] for i in range(rows)] return Cell2(tgt, src, linss)
def mk_ising(m, n): U = Space(ring, m, 0, "U") V = Space(ring, n, 1, "V") A = Lin(U, V) # U <--- V for i in range(m): A[i, i] = one if i + 1 < n: A[i, i + 1] = -one return A
def get_sl(self, V): assert V.n == 2, "todo.." lins = [] for a in self: for b in self: for c in self: for d in self: if a * d - b * c == 1: f = Lin(V, V, [[a, b], [c, d]]) lins.append(f) return lins
def right_unitor(cls, cell1, inverse=False): m, n = cell1.hom I_n = Cell1.identity(n) tgt, src = cell1, cell1 * I_n if inverse: tgt, src = src, tgt # Bit of a hack just using .iso here! # Should use MulSpace.unitor, etc. etc. XXX rows, cols = cell1.shape A = [[Lin.iso(tgt[i, j], src[i, j]) for j in range(cols)] for i in range(rows)] return Cell2(tgt, src, A)
def __add__(left, right): "direct_sum of 2-morphisms's" right = Cell2.promote(right) tgt = left.tgt + right.tgt src = left.src + right.src rig = left.rig zero = Lin(rig.zero, rig.zero) A = numpy.empty(tgt.shape, dtype=object) A[:] = [[zero]] A[:left.shape[0], :left.shape[1]] = left.A A[left.shape[0]:, left.shape[1]:] = right.A return Cell2(tgt, src, A)
def test_chain_tensor(): #p = argv.get("p", 3) #ring = element.FiniteField(p) ring = element.Q space = Space(ring) m = argv.get("m", 3) n = argv.get("n", 4) one = ring.one if argv.toric: V = Space(ring, n, 1, "V") U = Space(ring, m, 0, "U") A = Lin(U, V) for i in range(m): A[i, i] = one A[i, (i + 1) % m] = -one elif argv.surface: V = Space(ring, m, 1, "V") U = Space(ring, m - 1, 0, "U") A = Lin(U, V) for i in range(m - 1): A[i, i] = one A[i, (i + 1) % m] = -one else: V = Space(ring, n, 1, "V") U = Space(ring, m, 0, "U") A = Lin.rand(U, V) c = Chain([A]) print(c) c.dump()
def test_gf(): ring = GF(4) x = ring.x space = Space(ring) m = argv.get("m", 3) n = argv.get("n", 4) one = ring.one A = elim.zeros(ring, m, n) for i in range(m): for j in range(n): A[i, j] = choice(ring.elements) H = Lin(Space(ring, m, 0), Space(ring, n, 1), A) #print(H) c = Chain([H])
def __init__(self, lhs, rhs): assert lhs.lins assert rhs.lins assert lhs.ring is rhs.ring ring = lhs.ring self._init() for g in rhs.lins: # cols for f in lhs.lins: # rows self._addlin(f @ g.src.identity()) # vertical arrow sign = -1 if f.src.grade % 2 else 1 self._addlin(sign * f.src.identity() @ g) # _horizontal arrow sign = -1 if f.tgt.grade % 2 else 1 self._addlin(sign * f.tgt.identity() @ g) # _horizontal arrow for f in lhs.lins: # rows self._addlin(f @ g.tgt.identity()) # vertical arrow keys = list(self.grades.keys()) keys.sort(reverse=True) #print(keys) N = len(keys) lins = [] for idx in range(N - 1): i = keys[idx] assert keys[idx + 1] == i - 1, keys tgt = AddSpace(ring, *self.grades[i - 1]) src = AddSpace(ring, *self.grades[i]) #print(tgt) #print(src) A = elim.zeros(ring, tgt.n, src.n) #print(shortstr(A)) for s in src.items: for lin in self.srcs[s]: assert lin.src is s cols = src.get_slice(lin.src) rows = tgt.get_slice(lin.tgt) A[rows, cols] = lin.A #print(shortstr(A)) lin = Lin(tgt, src, A) #print(repr(lin)) lins.append(lin) #print() Chain.__init__(self, lins)
def __init__(self, tgt, src, lins=None, check=True): assert isinstance(tgt, Chain) assert isinstance(src, Chain) n = len(src) assert len(tgt) == n if lins is None: # zero map lins = [Lin(tgt.get(i), src.get(i)) for i in range(n + 1)] assert len(lins) == n + 1 for i in range(n): assert src[i].src == lins[i].src assert tgt[i].src == lins[i].tgt if n: assert src[n - 1].tgt == lins[n].src assert tgt[n - 1].tgt == lins[n].tgt self.ring = tgt.ring self.tgt = tgt self.src = src self.hom = (tgt, src) # yes it's backwards, just like shape is. self.lins = list(lins) if check: self._check()
def reassociate(A, B, C, inverse=False): "A*(B*C) <--- (A*B)*C" assert C.tgt == B.src assert B.tgt == A.src m, n = A.shape p, q = C.shape if n * p == 0: tgt, src = A * (B * C), (A * B) * C if inverse: tgt, src = src, tgt return Cell2.zero(tgt, src) rig = A.rig ring = rig.ring def add(items): items = list(items) assert len(items) if len(items) == 1: return items[0] return AddSpace(ring, *items) #ABC = numpy.empty((m, n, p, q), dtype=object) #for i in range(m): # for j in range(n): # for k in range(p): # for l in range(q): # ABC[i,j,k,l] = A[i,j]@B[j,k]@C[k,l] # src AB_C = numpy.empty((m, q), dtype=object) ab_c = numpy.empty((m, q), dtype=object) for i in range(m): for l in range(q): AB_C[i, l] = add( add(A[i, j] @ B[j, k] for j in range(n)) @ C[k, l] for k in range(p)) items = [ Lin.right_distributor( add(A[i, j] @ B[j, k] for j in range(n)), C[k, l]) for k in range(p) ] #rd = reduce(Lin.direct_sum, items or [rig.zero.identity()]) # will need nullitor's ? rd = reduce(Lin.direct_sum, items) assert rd.src == AB_C[i, l], ("%s != %s" % (rd.src, AB_C[i, l])) ab_c[i, l] = rd src = Cell1(A.tgt, C.src, AB_C) cell1 = Cell1(A.tgt, C.src, [[ab_c[i, l].tgt for l in range(q)] for i in range(m)]) ab_c = Cell2(cell1, src, ab_c) # tgt A_BC = numpy.empty((m, q), dtype=object) a_bc = numpy.empty((m, q), dtype=object) for i in range(m): for l in range(q): A_BC[i, l] = add(A[i, j] @ add(B[j, k] @ C[k, l] for k in range(p)) for j in range(n)) items = [ Lin.left_distributor(A[i, j], add(B[j, k] @ C[k, l] for k in range(p)), inverse=True) for j in range(n) ] #ld = reduce(Lin.direct_sum, items or [rig.zero.identity()]) # will need nullitor's ? ld = reduce(Lin.direct_sum, items) assert ld.tgt == A_BC[i, l] a_bc[i, l] = ld tgt = Cell1(A.tgt, C.src, A_BC) cell1 = Cell1(A.tgt, C.src, [[a_bc[i, l].src for l in range(q)] for i in range(m)]) a_bc = Cell2(tgt, cell1, a_bc) lookup = {} for k in range(p): for j in range(n): lookup[(j, k)] = len(lookup) perm = tuple(lookup[j, k] for j in range(n) for k in range(p)) def get_swap(u): assert isinstance(u, AddSpace), (u, perm) f = u.get_swap(perm) return f if len(perm) > 1: s = Cell2.send(ab_c.tgt, get_swap) assert s.tgt == a_bc.src else: s = Cell2.identity(ab_c.tgt) assert s.tgt == a_bc.src f = a_bc * s * ab_c assert f.src == src assert f.tgt == tgt if inverse: f = f.transpose2() return f
def rand(cls, tgt, src): assert tgt.hom == src.hom shape = tgt.shape lins = [[Lin.rand(tgt[i, j], src[i, j]) for j in range(shape[1])] for i in range(shape[0])] return Cell2(tgt, src, lins)
def test_chainmap(): p = argv.get("p", 2) ring = element.FiniteField(p) #ring = element.Q one = ring.one space = Space(ring) def mk_ising(m, n): U = Space(ring, m, 0, "U") V = Space(ring, n, 1, "V") A = Lin(U, V) # U <--- V for i in range(m): A[i, i] = one if i + 1 < n: A[i, i + 1] = -one return A A = mk_ising(3, 4) c = Chain([A]) f = c.identity() zero = ChainMap(c, c) assert f != zero assert f == f assert f != 2 * f assert f + f == 2 * f assert f - f == zero B = mk_ising(2, 2) d = Chain([B]) fn = Lin(A.src, B.src) for i in range(len(B.src)): fn[i, i] = one fm = Lin(A.tgt, B.tgt) for i in range(len(B.tgt)): fm[i, i] = one f = ChainMap(c, d, [fn, fm]) # ----------------------------------- m, n = 8, 10 V1 = Space(ring, n, 1, "V1") V0 = Space(ring, m, 0, "V0") A = Lin.rand(V0, V1) # V0 <--- V1 c = Chain([A]) U0 = Space(ring, m, 0, "U0") f0 = Lin.rand(V0, U0) f1, B = A.pullback(f0) d = Chain([B]) f = ChainMap(c, d, [f1, f0]) # ----------------------------------- # construct a chain map (and a chain) from a # pullback of a grade zero map. m, n, p = 5, 6, 1 V1 = Space(ring, n, 1, "V1") V0 = Space(ring, m, 0, "V0") #A = Lin.rand(V0, V1) # V0 <--- V1 A = Lin(V0, V1) for i in range(m): A[i, i] = one A[i, (i + 1)] = one a = Chain([A]) #print("A:") #print(A) U0 = Space(ring, p, 0, "U0") f0 = Lin(V0, U0) for i in range(p): f0[i, i] = one f1, B = A.pullback(f0) b = Chain([B]) #print("B:") #print(B) f = ChainMap(a, b, [f1, f0]) #print(f0) #print(f1) g = ChainMap(a, b) h = f.coequalizer(g) #print(h) #print(h[0]) #print(h[1]) c = h.tgt C = c[0] #print(C.shape, C.rank()) #print(C) # ----------------------------------- # construct a 'puncture' of a repitition code # as a cokernel m, n, p = 5, 6, 1 V1 = Space(ring, n, 1, "V1") V0 = Space(ring, m, 0, "V0") #A = Lin.rand(V0, V1) # V0 <--- V1 A = Lin(V0, V1) for i in range(m): A[i, i] = one A[i, (i + 1)] = one a = Chain([A]) U1 = Space(ring, 1, 1, "U1") U0 = Space(ring, 2, 0, "U0") B = Lin(U0, U1) B[0, 0] = one B[1, 0] = one b = Chain([B]) offset = 2 # where to puncture f0 = Lin(V0, U0) f0[0 + offset, 0] = one f0[1 + offset, 1] = one f1 = Lin(V1, U1) f1[offset + 1, 0] = one f = ChainMap(a, b, [f1, f0]) h = f.cokernel() c = h.tgt # ----------------------------------- # Here we puncture a bit from a parity check matrix # by using a cokernel. This deletes that column, # as well as all the rows with support therein. m, n, p = 5, 6, 1 V1 = Space(ring, n, 1, "V1") V0 = Space(ring, m, 0, "V0") A = Lin.rand(V0, V1) # V0 <--- V1 a = Chain([A]) #print(A) col = 0 rows = [] for i in range(V0.n): if A[i, col]: rows.append(i) U1 = Space(ring, 1, 1, "U1") U0 = Space(ring, len(rows), 0, "U0") B = Lin(U0, U1) for i in range(U0.n): B[i, 0] = one b = Chain([B]) #print(B) f0 = Lin(V0, U0) for i, row in enumerate(rows): f0[row, i] = one #print(f0) f1 = Lin(V1, U1) f1[col, 0] = one f = ChainMap(a, b, [f1, f0]) h = f.cokernel() c = h.tgt
def lin(a, b, c, d): a = S.promote(a) b = S.promote(b) c = S.promote(c) d = S.promote(d) return Lin(V, V, [[a, b], [c, d]])