def deltaPrefix(self, MGen, algGens): # Preliminary tests if len(algGens) == 0: return True if algGens[0].left_idem != MGen.idem2: return False if any([algGens[i].right_idem != algGens[i+1].left_idem for i in range(len(algGens)-1)]): return False assignment, algs_local, prod_d = self.getAssignments(MGen, algGens) if assignment is None: return E0 local_MGen = MGen.local_gen dbls = [self.single_idems2[i] for i in range(self.num_singles) if assignment[i] == self.DOUBLE] for to_remove in subset(dbls): if len(to_remove) != 0: cur_algs_local = tuple([alg.removeSingleHor(to_remove) for alg in algs_local]) else: cur_algs_local = algs_local if self.testPrefix(local_MGen, cur_algs_local): return True return False
def search(cur_strands): """Search starting with the given list of strands. May only add strands after the end position of the last strand. """ # First, check if the current list of strands is valid. left_occupied = [0] * self.num_pair right_occupied = [0] * self.num_pair for start, end in cur_strands: start_id, end_id = self.pairid[start], self.pairid[end] if start_id != -1: left_occupied[start_id] += 1 if end_id != -1: right_occupied[end_id] += 1 if any([n >= 2 for n in left_occupied + right_occupied]): # There should not be two strands starting or ending at points # in the same pair. return # Enumerate all possible ways of adding idempotents. empty_idems = [i for i in range(self.num_pair) if left_occupied[i] == 0 and right_occupied[i] == 0] left_idem = [i for i in range(self.num_pair) if left_occupied[i] > 0] for idems_to_add in subset(empty_idems): result.append(LocalStrandDiagram( algebra, left_idem + list(idems_to_add), cur_strands)) # Now enumerate all ways of adding more strands. last_end = 0 if len(cur_strands) > 0: last_end = cur_strands[-1][1] for start in range(last_end, self.n): for end in range(start + 1, self.n): if self.pairid[start] == -1 and self.pairid[end] == -1 and \ end == start + 1: # Exclude cases where a strand goes from an # end-boundary-point to a start-boundary-point break search(cur_strands + [(start, end)]) if self.pairid[end] == -1: # No strand should go beyond an end-boundary-point. break
def getLocalDAStructure(self): """Returns the local type DA structure associated to the anti-braid resolution. """ if self.is_degenerate: if self.c1 == 0: patterns_raw = self._get_patterns_bottom() else: assert self.c2 == self.n - 1 patterns_raw = self._get_patterns_top() else: patterns_raw = self._get_patterns_middle() arrow_patterns = {} for pattern in patterns_raw: start_class, end_class = pattern[0], pattern[1] coeffs_a = [] for i in range(2, len(pattern)-1): coeffs_a.append(self.local_pmc.sd(pattern[i])) key = (start_class, end_class, tuple(coeffs_a)) if key not in arrow_patterns: arrow_patterns[key] = [] arrow_patterns[key].append(self.local_pmc.sd(pattern[-1])) # Now start construction of the local DA structure. alg = LocalStrandAlgebra(F2, self.local_pmc) local_c_pair = 0 # Compute the set of local generators. Generators of class 0 has # idempotents (l_idem, r_idem) where l_idem has the c_pair and # r_idem has one of the u or d pairs (with the rest being the same). # Generators of class 1 and 2 has l_idem = r_idem such that c_pair # is in both. if self.is_degenerate: single_idems = [1] # local p_pair da_idems_0 = [([0], [1])] else: # Non-degenerate case single_idems = [1, 2] # local d_pair and local u_pair da_idems_0 = [([0], [1]), ([0], [2]), ([0, 1], [1, 2]), ([0, 2], [1, 2])] # class 0 local_da = LocalDAStructure( F2, alg, alg, single_idems1 = single_idems, single_idems2 = single_idems) for i in range(len(da_idems_0)): # class 0 l_idem, r_idem = da_idems_0[i] local_da.addGenerator(SimpleDAGenerator( local_da, LocalIdempotent(self.local_pmc, l_idem), LocalIdempotent(self.local_pmc, r_idem), "0_%d" % i)) all_idems = subset(range(self.local_pmc.num_pair)) # class 1 and 2 for i in range(len(all_idems)): idem = LocalIdempotent(self.local_pmc, all_idems[i]) if local_c_pair in idem: local_da.addGenerator( SimpleDAGenerator(local_da, idem, idem, "1_%d" % i)) local_da.addGenerator( SimpleDAGenerator(local_da, idem, idem, "2_%d" % i)) mod_gens = local_da.getGenerators() # Have to take care of u_map. It is sufficient to know that u_map musst # preserve class of generators. for i in range(len(single_idems)): idem = single_idems[i] for local_gen in mod_gens: idem1, idem2 = local_gen.idem1, local_gen.idem2 if idem in idem1 and idem in idem2: # local_gen is eligible for u_maps[i] target_idem1 = idem1.removeSingleHor([idem]) target_idem2 = idem2.removeSingleHor([idem]) target_gen = [target for target in mod_gens if target.idem1 == target_idem1 and target.idem2 == target_idem2 and target.name[0] == local_gen.name[0]] assert len(target_gen) == 1 local_da.add_u_map(i, local_gen, target_gen[0]) # Check all u_map has been filled. local_da.auto_u_map() # Add arrows according to arrow_pattern. for key in arrow_patterns.keys(): start_class, end_class, coeffs_a = key if len(coeffs_a) == 1 and coeffs_a[0].isIdempotent(): continue for coeff_d in arrow_patterns[key]: used = False for x, y in itertools.product(mod_gens, mod_gens): if x.name[0] == "%d" % start_class and \ y.name[0] == "%d" % end_class and \ DAStructure.idemMatchDA(x, y, coeff_d, coeffs_a): local_da.addDelta(x, y, coeff_d, coeffs_a, 1) used = True if not used: print "Warning: unused arrow: %s %s" % (coeffs_a, coeff_d) return local_da
def sGOfTGrad(t): return -gOfTGrad(subset(L, sampleSize), alpha * sampleSize / n, t, eta)
def getLocalDAStructure(self, seeds_only = False): """Returns the local type DA structure associated to slide. If seeds_only is set to True, get a local DA structure with incomplete da_action, that can be completed using the autocompleteda module. """ # Compute the set of arrow patterns patterns_raw = self.patterns_fun(seeds_only = seeds_only) if self.translator is not None: patterns_raw = ArcslideDA._restrict_local_arrows( patterns_raw, self.translator[0], self.translator[1]) arrow_patterns = {} for pattern in patterns_raw: coeffs_a = [] for i in range(len(pattern)-1): coeffs_a.append(self.local_pmc2.sd(pattern[i])) coeffs_a = tuple(coeffs_a) if coeffs_a not in arrow_patterns: arrow_patterns[coeffs_a] = [] arrow_patterns[coeffs_a].append(self.local_pmc1.sd(pattern[-1])) # Now start construction of the local DA structure. alg1 = LocalStrandAlgebra(F2, self.local_pmc1) alg2 = LocalStrandAlgebra(F2, self.local_pmc2) local_dastr = LocalDAStructure(F2, alg1, alg2) # Mappings between local starting and ending PMC. slide = self.slide local_to_r = dict() for i in range(slide.start_pmc.n): if i in self.mapping1: # to_r[i] must be in mapping2 local_to_r[self.mapping1[i]] = self.mapping2[slide.to_r[i]] local_pair_to_r = dict() for i in range(self.local_pmc1.n): if i not in self.local_pmc1.endpoints: local_pair_to_r[self.local_pmc1.pairid[i]] \ = self.local_pmc2.pairid[local_to_r[i]] b1, c1 = self.slide.b1, self.slide.c1 local_b1, local_c1 = self.mapping1[b1], self.mapping1[c1] b_pair1 = self.local_pmc1.pairid[local_b1] c_pair1 = self.local_pmc1.pairid[local_c1] # Compute the set of local generators. This includes all # (l_idem, r_idem) where l_idem = r_idem (under the usual identification # of pairs), or where l_idem has the c_pair and r_idem has the b_pair. da_idems = [] num_pair = self.local_pmc1.num_pair for idem in subset(range(num_pair)): da_idems.append((list(idem), [local_pair_to_r[p] for p in idem])) for idem in subset([p for p in range(num_pair) if p != b_pair1 and p != c_pair1]): da_idems.append((list(idem) + [c_pair1], [local_pair_to_r[p] for p in (list(idem) + [b_pair1])])) for i in range(len(da_idems)): l_idem, r_idem = da_idems[i] local_dastr.addGenerator(SimpleDAGenerator( local_dastr, LocalIdempotent(self.local_pmc1, l_idem), LocalIdempotent(self.local_pmc2, r_idem), "%d" % i)) mod_gens = local_dastr.getGenerators() # After having added all generators, create u_map: local_dastr.auto_u_map() # Add arrows according to arrow_pattern. for coeffs_a in arrow_patterns.keys(): if len(coeffs_a) == 1 and coeffs_a[0].isIdempotent(): continue for coeff_d in arrow_patterns[coeffs_a]: for x, y in itertools.product(mod_gens, mod_gens): if DAStructure.idemMatchDA(x, y, coeff_d, coeffs_a): local_dastr.addDelta(x, y, coeff_d, coeffs_a, 1) return local_dastr
def search(start_gen, cur_dgen, algs, last_assign, algs_local, last_prod_d): """Searching for an arrow in the box tensor product. - start_gen: starting generator in the box tensor product. The resulting arrow will start from here. - cur_dgen: current location in the type D structure. - algs: current list of A-side inputs to the type DA structure (or alternatively, list of algebra outputs produced by the existing path through the type D structure). - algs_local: current list of local restrictions of algs. - last_assign: a list of length self.num_singles. For each split idempotent, specify the single assignments at the last algebra input. - prod_d: product of the outer restrictions, except for the last algebra input. """ start_dagen, start_dgen = start_gen local_MGen = start_dagen.local_gen # Preliminary tests if len(algs) > 0: assert algs[0].left_idem == start_dagen.idem2 for i in range(len(algs)-1): assert algs[i].right_idem == algs[i+1].left_idem if any(alg.isIdempotent() for alg in algs): return # First, adjust local module generator, and check for delta. if len(algs_local) > 0: local_MGen = self.adjustLocalMGen(local_MGen, algs_local[0]) if local_MGen is None: return local_delta = self.local_da.delta(local_MGen, tuple(algs_local)) has_delta = (local_delta != E0) # Second, check for delta prefix. has_delta_prefix = False if len(algs) == 0: has_delta_prefix = True else: dbls = [self.single_idems2[i] for i in range(self.num_singles) if last_assign[i] == self.DOUBLE] for to_remove in subset(dbls): if len(to_remove) != 0: cur_algs_local = tuple([alg.removeSingleHor(to_remove) for alg in algs_local]) else: cur_algs_local = algs_local if self.testPrefix(local_MGen, cur_algs_local): has_delta_prefix = True break if (not has_delta) and (not has_delta_prefix): return # Now, compute new prod_d. if len(algs) > 0: prod_d = self.getNewProdD(last_assign, algs[-1], last_prod_d) else: prod_d = last_prod_d if prod_d is None: return # If has_delta is True, add to delta for (local_d, local_y), ring_coeff in local_delta.items(): alg_d, y = self.joinOutput(local_d, local_y, prod_d) if alg_d is not None: dstr_result.addDelta(start_gen, DATensorDGenerator( dstr_result, y, cur_dgen), alg_d, 1) if not has_delta_prefix: return for (new_alg, dgen_to), ring_coeff in dstr.delta(cur_dgen).items(): new_assign, new_local, last_prod_d = self.extendRestrictions( last_assign, algs_local, prod_d, new_alg) if new_assign is not None: search(start_gen, dgen_to, algs + [new_alg], new_assign, new_local, last_prod_d)