def R_mon(*args): R"""Return the monomial $\prod R_{ij}$. args is i1, j1, i2, j2, ...""" result = DualSteenrodDense.unit() for i in range(len(args) // 2): s, t = args[2 * i], args[2 * i + 1] result *= DualSteenrodDense.gen(t - s, 2**s) for m in result.data: return m
def basis_mon(s, t, u): """Return a basis of degree s, t and weight <= u.""" for d in orderedpartition(s, t): iters = (DualSteenrodDense.basis_mons(d[i]) for i in range(s)) for mon in itertools.product(*iters): if CobarSteenrod.weight_mon(mon) <= u: yield mon
def d0(self): """Return the d_0 differential.""" data = set() for mon in self.data: for i in range(len(mon)): m = mon[i] coprod = DualSteenrodDense(m).coprod_E0() for m1, m2 in coprod.data: if m1 and m2: data ^= {mon[:i] + (m1, m2) + mon[i + 1:]} return type(self)(data)
def d0_inv_data(cls, data: set): """Find a cycle $c$ such that $d_0c = data$.""" data = data.copy() result = set() while data: mon = max(data, key=cls.key_mon) i = cls._get_i(mon) if i is None: raise BA.MyValueError("Not d0 invertible") m_d0_inv = mon[:i] + (DualSteenrodDense.mul_mons( mon[i + 1], mon[i]), ) + mon[i + 2:] assert m_d0_inv not in result result ^= {m_d0_inv} data ^= cls(m_d0_inv).d0().data BA.Monitor.print(len(data)) return result
def _get_i(mon): """$R_{ij}<R_{kl}$ if (j-i, i)<(l-k,k)""" for i in range(len(mon)): if DualSteenrodDense.is_gen_E0(mon[i]): if i > 0 and (len(mon[i]), mon[i][-1]) < (len( mon[i - 1]), mon[i - 1][-1]): return i - 1 else: if i > 0 and all( (g + 1, 1 << s) < (len(mon[i - 1]), mon[i - 1][-1]) for g, e in enumerate(mon[i]) if e > 0 for s in two_expansion(e)): return i - 1 else: break return None
def R(i, j): """Return $R_{ij}$""" return DualSteenrodDense.gen(j - i, 2**i)
def deg_mon(mon: tuple): return Vector( (len(mon), sum(DualSteenrodDense.deg_mon(m) for m in mon)))
def key_mon(mon): return [(DualSteenrodDense.is_gen_E0(m), len(m), m[-1]) for m in mon]
def weight_mon(mon: tuple): return sum(DualSteenrodDense.weight_mon(m) for m in mon)