def compute_hi_products(self, x, y): v2 = fp.FpVector(2, 0) w2 = fp.FpVector(2, 0) vout = fp.FpVector(2, 0) wout = fp.FpVector(2, 0) result = [] for hi in [0, 1, 3]: t1 = (hi, 1) t2 = (x, y) tout = (x + hi, y + 1) hi_result = [] if tout not in self.dense_products: result.append(hi_result) continue ng2 = self.gens_in_bidegree(*t2) ngout = self.gens_in_bidegree(*tout) b2 = self.basis_in_bidegree(*t2) try: bout = self.basis_in_bidegree(*tout) except IndexError: result.append(hi_result) continue v2.set_scratch_vector_size(ng2) w2.set_scratch_vector_size(ng2) vout.set_scratch_vector_size(ngout) wout.set_scratch_vector_size(ngout) for i in range(ng2): v2.set_to_zero() w2.set_to_zero() vout.set_to_zero() wout.set_to_zero() v2[i] = 1 b2.apply(w2, v2) pair = (t1, t2) if t1 <= t2 else (t2, t1) products = None if pair in self.dense_products[tout]: products = self.dense_products[tout][pair] else: pair = tuple(reversed(pair)) if tuple(reversed(pair)) in self.dense_products: products = self.dense_products[tout][pair] if products: for j in range(ng2): if w2[j] != 0: vout.add(products[j]) bout.apply_inverse(wout, vout) hi_result.append(list(wout)) result.append(hi_result) return result
def get_binary_decompositions(self, x, y): v1 = fp.FpVector(2, 0) w1 = fp.FpVector(2, 0) v2 = fp.FpVector(2, 0) w2 = fp.FpVector(2, 0) tensor = fp.FpVector(2, 0) tout = (x, y) ngout = self.gens_in_bidegree(*tout) vout = fp.FpVector(2, ngout) wout = fp.FpVector(2, ngout) result = [] for (t1, t2) in self.dense_products[tout]: ng1 = self.gens_in_bidegree(*t1) ng2 = self.gens_in_bidegree(*t2) v1.set_scratch_vector_size(ng1) v2.set_scratch_vector_size(ng2) for idx1 in range(ng1): v1.set_to_zero() v1[idx1] = 1 for idx2 in range(ng2): v2.set_to_zero() v2[idx2] = 1 product = self.multiply_vectors_helper( t1, v1, t2, v2, w1, w2, tensor, vout, wout) if 1 in product: result.append((t1 + (idx1, ), t2 + (idx2, ), product)) result.sort(key=lambda x: [-sum(x[-1]), *x[-1], -x[0][0], -x[0][1]], reverse=True) return result
def get_binary_decomposition_info(self, bidegree): result = [] v = fp.FpVector(2, self.table.gens_in_bidegree(*bidegree)) w = fp.FpVector(2, self.table.gens_in_bidegree(*bidegree)) b = self.table.basis_in_bidegree(*bidegree) for (in1, in2, out) in self.get_filtered_binary_decompositions(bidegree): [n1, n2] = [(x, self.get_name(x, keep_parens=True), self.get_monomial_name(x)) for x in [in1, in2]] v.pack(out) w.set_to_zero() b.apply_inverse(w, v) out_name = self.table.name_to_str( self.table.get_vec_name(*bidegree, out)) result.append({ "left": n1, "right": n2, "out_res_basis": out, "out_our_basis": list(w), "out_name": out_name }) return result
def compute_hi_indecomposables_in_bidegree(self, x, y): ng = self.gens_in_bidegree(x, y) subspace = fp.Subspace(2, ng + 1, ng) subspace.set_to_zero() image_vecs = [ out for (in1, in2, out) in self.binary_decomposition_table[(x, y)] if in1[1] == 1 ] py_v = [0] * ng v = fp.FpVector(2, ng) w = fp.FpVector(2, ng) B = self.basis_in_bidegree(x, y) for e in image_vecs: for i in range(ng): py_v[i] = 1 if i in e else 0 v.pack(py_v) w.set_to_zero() B.apply_inverse(w, v) subspace.add_vector(w) return [ idx for (idx, e) in enumerate(subspace.matrix().pivots()) if e == -1 ]
def multiply_vectors(self, in1, vec1, in2, vec2): t1 = tuple(in1) t2 = tuple(in2) ng1 = self.gens_in_bidegree(*t1) ng2 = self.gens_in_bidegree(*t2) v1 = fp.FpVector(2, ng1) v2 = fp.FpVector(2, ng2) v1.pack(vec1) v2.pack(vec2) w1 = fp.FpVector(2, 0) w2 = fp.FpVector(2, 0) tensor = fp.FpVector(2, 0) vout = fp.FpVector(2, 0) wout = fp.FpVector(2, 0) return self.multiply_vectors_helper(t1, v1, t2, v2, w1, w2, tensor, vout, wout)
def propagate_names(self, names): result = dict([(*name["bidegree"], tuple(name["vec"])), name] for name in names) new_names = result product_list = [{ "bidegree": [(1 << i) - 1, 1], "name": name_tools.parse_name(f"h_{i}"), "vec": [1] } for i in range(HI_MAX)] while new_names: last_names = new_names new_names = {} for name in last_names.values(): for prod in product_list: out_x = prod["bidegree"][0] + name["bidegree"][0] out_y = prod["bidegree"][1] + name["bidegree"][1] out_vec = tuple( self.table.multiply_vectors(prod["bidegree"], prod["vec"], name["bidegree"], name["vec"])) out_our_basis = fp.FpVector( 2, self.table.gens_in_bidegree(out_x, out_y)) try: self.table.basis_in_bidegree(out_x, out_y) \ .apply(out_our_basis, fp.FpVector.from_list(2, out_vec)) if 1 in out_vec and \ not self.table.named_vecs[out_y][out_x].get(out_vec, None) \ and (out_x, out_y, out_vec) not in result: new_name = name_tools.reduce_monomial( name["name"] + prod["name"]) new_names[(out_x, out_y, out_vec)] = { "type": "set_name", "bidegree": [out_x, out_y], "name": new_name, "vec": out_vec, "our_basis_vec": list(out_our_basis), "state": None } except IndexError: pass result.update(new_names) return list(result.values())
def build_dense_products_bidegree(self, t1, t2): tout = (t1[0] + t2[0], t1[1] + t2[1]) ng1 = self.gens_in_bidegree(*t1) ng2 = self.gens_in_bidegree(*t2) ngout = self.gens_in_bidegree(*tout) products = [fp.FpVector(2, ngout) for _ in range(ng1 * ng2)] for idx1 in range(ng1): in1 = t1 + (idx1, ) for idx2 in range(ng2): in2 = t2 + (idx2, ) if (in1, in2) in self.product_table: product_table_entry = self.product_table.get((in1, in2), []) else: product_table_entry = self.product_table.get((in2, in1), []) for [_, _, e] in product_table_entry: try: products[idx1 * ng2 + idx2][e] = 1 except IndexError: print("bdpbi", t1, t2, "product_table_entry", product_table_entry, "ngout", ngout) raise return products