def set_diff(cls, gen_name: str, diff: Union[None, set, "GbDga"]): """Define the differential of gen_name.""" for i, gen in enumerate(cls.generators): if gen.name == gen_name: break else: raise BA.MyKeyError(f"generator {gen_name} not found") if i is not None: if type(diff) is not set and diff is not None: diff = diff.data if diff and (not cls(diff).is_homo() or cls.deg3d_data(diff) - gen.deg3d != cls.deg_diff): raise BA.MyDegreeError("inconsistent differential degree") gen = cls.generators[i] cls.generators[i] = DgaGen(gen.index, gen.name, gen.deg, gen.deg3d, diff)
def determine_diff(cls, g: Union[str, int], basis: dict, image_gens=None): """Determine differentials by relations.""" if type(g) is str: for gen in cls.generators: if gen.name == g: break else: raise BA.MyKeyError(f"generator {g} not found") else: gen = cls.get_gen(g) g = gen.name deg_target = gen.deg3d + cls.deg_diff if deg_target not in basis: cls.set_diff(g, set()) print(f"set d({g})=0") return # print("Possible summands:") # for m in basis[deg_target]: # print(cls(m)) rels = [] cls.set_diff(g, set()) for m in cls.rels: if cls.is_differentiable_mon(m) and all(map(cls.is_differentiable_mon, cls.rels[m])): if cls.contains_gen_mon(m, gen.index) or any(map(cls.contains_gen_mon, cls.rels[m], repeat(gen.index))): rels.append({m} | cls.rels[m]) possible_diffs = [] for n in range(1 << len(basis[deg_target])): data = {basis[deg_target][i] for i in two_expansion(n)} if all(map(cls.is_differentiable_mon, data)) and cls(data).diff(): continue cls.set_diff(g, data) compatible = True for rel in rels: if cls(rel).diff(): compatible = False break if image_gens and image_gens[gen.name].is_differentiable() and\ cls(data).evaluation(image_gens) != image_gens[gen.name].diff(): compatible = False if compatible: possible_diffs.append(data) if len(possible_diffs) == 1: cls.set_diff(g, possible_diffs[0]) print(f"set d({g})={cls(possible_diffs[0])}") elif len(possible_diffs) == 0: raise BA.MyClassError(f"Invalid DGA. d({g})=?") else: for data in possible_diffs: print(f"d({g})={cls(data)} is possible.") cls.set_diff(g, None)
def gen(cls, k: str): """Return a generator.""" for gen in cls.generators: if gen.name == k: m = ((gen.index, -1),) return cls(m).simplify() if cls.auto_simplify else cls(m) else: raise BA.MyKeyError(f"No generator named {k}")
def add_gen(cls, name: str, deg, deg3d=(0, 0, 0), diff=None): """Add a new generator and return it.""" index = cls.generators[-1][0] + 1 if cls.generators else 0 if diff is None: diff = set() elif type(diff) is not set: diff = diff.data if diff and cls.deg3d_data(diff) - deg3d != cls.deg_diff: raise BA.MyDegreeError("inconsistent differential degree") cls.generators.append(DgaGen(index, name, deg, Vector(deg3d), diff)) m = ((index, -1),) return cls(m).simplify() if cls.auto_simplify else cls(m)
def new_alg(*, key=None, pred=None, deg_diff=None) -> "Type[GbDga]": """Return a dynamically created subclass of GbDga.""" cls = GbDga class_name = f"GbAlgMod2_{cls._name_index}" cls._name_index += 1 if deg_diff is not None: deg_diff = Vector(deg_diff) else: raise BA.MyDegreeError("degree of differential not supplied") dct = {'generators': [], 'rels': {}, '_rels_gen_leads': set(), '_rels_cache': [], 'key': key, 'pred': pred or GbAlgMod2.pred_default, 'auto_simplify': True, 'deg_diff': deg_diff} # noinspection PyTypeChecker return type(class_name, (cls,), dct)
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 load_alg(cls, filename) -> Union[Type["GbAlgMod2"], Type["GbDga"]]: """Create an algebra from a pickle file.""" with open(filename, 'rb') as file: init_list = pickle.load(file) if cls is GbAlgMod2: class_name = f"GbAlgMod2_{cls._name_index}" elif cls is GbDga: class_name = f"GbDga_{cls._name_index}" else: raise BA.MyKeyError("cls should be either GbAlgMod2 or GbDga.") cls._name_index += 1 if init_list[0] == "5-11-2020": dct = {attr: init_v for attr, init_v in zip(cls._attributes, init_list[1:])} else: raise ValueError("file version not recognized") # noinspection PyTypeChecker return type(class_name, (cls,), dct)
def get_gen_by_name(cls, name: str) -> Union[Gen, DgaGen]: for gen in cls.generators: if gen.name == name: return gen raise BA.MyKeyError(f"generator {name} not found")