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