def genus_symbol_string_to_dict(s): sl = s.split('.') d = dict() for s in sl: L1 = s.split('^') if len(L1) > 2: raise ValueError() elif len(L1) == 1: nn = 1 else: nn = L1[1] n = Integer(nn) L1 = L1[0].split("_") q = Integer(L1[0]) if len(L1) > 2: # more than one _ in item raise ValueError elif len(L1) == 2: if Integer(L1[1]) in range(8): t = Integer(L1[1]) else: raise ValueError, "Type given, which ist not in 0..7: %s" % ( L1[1]) else: t = None if not (n != 0 and q != 1 and q.is_prime_power() and (None == t or (is_even(q) and t % 2 == n % 2)) and (not (None == t and is_even(q)) or 0 == n % 2)): raise ValueError, "{0} is not a valid signature!".format(s) p = q.prime_factors()[0] r = q.factor()[0][1] eps = sign(n) n = abs(n) if not d.has_key(p): d[p] = list() if p == 2: if t == None: print "eps = ", eps if not is_even(n): raise ValueError() d[p].append([ r, n, 3 * (-1)**(Integer(n - 2) / 2) % 8 if eps == -1 else (-1)**(Integer(n)), t, 4 if eps == -1 else 0 ]) print d else: if t.kronecker(2) == eps: det = t % 8 else: if eps == -1: det = 3 else: det = 1 d[p].append([r, n, det, 1, t % 8]) else: d[p].append([r, n, eps]) return d
def genus_symbol_string_to_dict(s): sl = s.split('.') d = dict() for s in sl: L1 = s.split('^') if len(L1)>2: raise ValueError() elif len(L1) == 1: nn = 1 else: nn = L1[1] n = Integer(nn) L1= L1[0].split("_") q = Integer(L1[0]) if len(L1) > 2: # more than one _ in item raise ValueError elif len(L1) == 2: if Integer(L1[1]) in range(8): t = Integer(L1[1]) else: raise ValueError, "Type given, which ist not in 0..7: %s"%(L1[1]) else: t = None if not (n != 0 and q != 1 and q.is_prime_power() and ( None == t or (is_even(q) and t%2 == n%2)) and ( not (None == t and is_even(q)) or 0 == n%2) ): raise ValueError,"{0} is not a valid signature!".format(s) p = q.prime_factors()[0] r = q.factor()[0][1] eps = sign(n) n = abs(n) if not d.has_key(p): d[p]=list() if p==2: if t == None: print "eps = ", eps if not is_even(n): raise ValueError() d[p].append([r, n, 3*(-1)**(Integer(n-2)/2) % 8 if eps == -1 else (-1)**(Integer(n)),t,4 if eps == -1 else 0]) print d else: if t.kronecker(2) == eps: det = t % 8 else: if eps == -1: det = 3 else: det = 1 d[p].append([r,n,det,1,t % 8]) else: d[p].append([r,n,eps]) return d
def _compute_simple_modules_graph_from_startpoint(self, s, p=None, cut_nonsimple_aniso=True, fast=1): # for forking this is necessary logger = get_logger(s) # print logger k = self._weight ########################################################### # Determine which primes need to be checked # According to the proof of Proposition XX in [BEF], we # only need to check primesnot dividing the 6*level(s), # for which prime_pol(s,p,k) <= 0. # For those primes, we check if there is any # k-simple fqm in s.C(p) and if not, we do not have to # consider p anymore. ########################################################### if p == None: p = 2 N = Integer(6) * s.level() slp = N.prime_factors() for q in prime_range(next_prime(N) + 1): if not q in slp: logger.info( "Smallest prime not dividing 6*level({0}) = {1} is p = {2}".format(s, Integer(6) * s.level(), q)) p = q break while prime_pol(s, p, k) <= 0 or p in slp: p = next_prime(p) p = uniq(prime_range(p) + slp) logger.info("Starting with s = {0} and primes = {1}".format(s, p)) if isinstance(p, list): primes = p else: primes = [p] simple = s.is_simple(k, reduction = self._reduction, bound = self._bound) if not simple: logger.info("{0} is not simple.".format(s)) # print simple s = FQM_vertex(s) # print s self.add_vertex(s) # print "added vertex ", s ############################################################ # Starting from the list of primes we generated, # we now compute which primes we actually need to consider. # That is, the primes such that there is a fqm in s.C(p) # which is k-simple. ############################################################ np = list() if cut_nonsimple_aniso and simple: for i in range(len(primes)): p = primes[i] fs = False for t in s.genus_symbol().C(p, False): if t.is_simple(k, bound = self._bound): fs = True logger.debug("Setting fs = True") break if fs: np.append(p) primes = np # print "here", primes logger.info("primes for graph for {0}: {1}".format(s, primes)) # if len(primes) == 0: # return heights = self._heights h = 0 if not heights.has_key(h): heights[h] = [s] else: if heights[h].count(s) == 0: heights[h].append(s) vertex_colors = self._vertex_colors nonsimple_color = self._nonsimple_color simple_color = self._simple_color # Bs contains the modules of the current level (= height = h) Bs = [s] # set the correct color for the vertex s if simple: if vertex_colors[simple_color].count(s) == 0: vertex_colors[simple_color].append(s) elif vertex_colors[nonsimple_color].count(s) == 0: vertex_colors[nonsimple_color].append(s) ################################################### # MAIN LOOP # we loop until we haven't found any simple fqm's ################################################### while simple: h = h + 1 if not heights.has_key(h): heights[h] = list() # the list Bss will contain the k-simple modules of the next height level # recall that Bs contains the modules of the current height level Bss = list() simple = False # checklist = modules that we need to check for with .is_simple(k) # we assemble this list because afterwards # we check them in parallel checklist = [] for s1 in Bs: Bs2 = list() for p in primes: # check if we really need to check p for s1 # otherwise none of the fqm's in s1.C(p) are simple # and we will not consider them. if prime_pol(s1.genus_symbol(), p, k) <= 0: Bs2 = Bs2 + s1.genus_symbol().C(p, False) else: logger.info( "Skipping p = {0} for s1 = {1}".format(p, s1)) # print "Skipping p = {0} for s1 = {1}".format(p, s1) # print "Bs2 = ", Bs2 # now we actually check the symbols in Bs2 for s2 in Bs2: if s2.max_rank() > self._rank_limit: # we skip s2 if its minimal number of generators # is > than the given rank_limit. continue s2 = FQM_vertex(s2) skip = False for v in self._heights[h]: # we skip symbols that correspond to isomorphic modules if v.genus_symbol().defines_isomorphic_module(s2.genus_symbol()): skip = True logger.debug( "skipping {0} b/c isomorphic to {1}".format(s2.genus_symbol(), v.genus_symbol())) s2 = v break if skip: continue if not skip: self.add_vertex(s2) heights[h].append(s2) self.update_edges(s2, h, fast=fast) # before using the actual dimension formula # we check if there is already a non-k-simple neighbor # (an incoming edge from a non-k-simple module) # which would imply that s2 is not k-simple. has_nonsimple_neighbor = False for e in self.incoming_edges(s2): if vertex_colors[nonsimple_color].count(e[0]) > 0: has_nonsimple_neighbor = True logger.debug( "Has nonsimple neighbor: {0}".format(s2.genus_symbol())) break if has_nonsimple_neighbor: #not simple if not vertex_colors[nonsimple_color].count(s2) > 0: vertex_colors[nonsimple_color].append(s2) else: checklist.append((s2, k, self._reduction, self._bound)) logger.debug("checklist = {0}".format(checklist)) # check the modules in checklist # for being k-simple # this is done in parallel # when a process returns # we add the vertex and give it its appropriate color if NCPUS1 == 1: checks = [([[s[0]]],check_simple(*s)) for s in checklist] else: checks = list(check_simple(checklist)) logger.info("checks = {0}".format(checks)) for check in checks: s2 = check[0][0][0] if check[1]: simple = True logger.info( "Found simple module: {0}".format(s2.genus_symbol())) Bss.append(s2) if not vertex_colors[simple_color].count(s2) > 0: vertex_colors[simple_color].append(s2) else: if not vertex_colors[nonsimple_color].count(s2) > 0: vertex_colors[nonsimple_color].append(s2) Bs = Bss simple = [v.genus_symbol() for v in vertex_colors[simple_color]] self._simple = uniq(simple)
def _compute_simple_modules_graph_from_startpoint(self, s, p=None, cut_nonsimple_aniso=True, fast=1): # for forking this is necessary logger = get_logger(s) # print logger k = self._weight ########################################################### # Determine which primes need to be checked # According to the proof of Proposition XX in [BEF], we # only need to check primesnot dividing the 6*level(s), # for which prime_pol(s,p,k) <= 0. # For those primes, we check if there is any # k-simple fqm in s.C(p) and if not, we do not have to # consider p anymore. ########################################################### if p == None: p = 2 N = Integer(6) * s.level() slp = N.prime_factors() for q in prime_range(next_prime(N) + 1): if not q in slp: logger.info( "Smallest prime not dividing 6*level({0}) = {1} is p = {2}" .format(s, Integer(6) * s.level(), q)) p = q break while prime_pol(s, p, k) <= 0 or p in slp: p = next_prime(p) p = uniq(prime_range(p) + slp) logger.info("Starting with s = {0} and primes = {1}".format(s, p)) if isinstance(p, list): primes = p else: primes = [p] simple = s.is_simple(k, reduction=self._reduction, bound=self._bound) if not simple: logger.info("{0} is not simple.".format(s)) # print simple s = FQM_vertex(s) # print s self.add_vertex(s) # print "added vertex ", s ############################################################ # Starting from the list of primes we generated, # we now compute which primes we actually need to consider. # That is, the primes such that there is a fqm in s.C(p) # which is k-simple. ############################################################ np = list() if cut_nonsimple_aniso and simple: for i in range(len(primes)): p = primes[i] fs = False for t in s.genus_symbol().C(p, False): if t.is_simple(k, bound=self._bound): fs = True logger.debug("Setting fs = True") break if fs: np.append(p) primes = np # print "here", primes logger.info("primes for graph for {0}: {1}".format(s, primes)) # if len(primes) == 0: # return heights = self._heights h = 0 if not heights.has_key(h): heights[h] = [s] else: if heights[h].count(s) == 0: heights[h].append(s) vertex_colors = self._vertex_colors nonsimple_color = self._nonsimple_color simple_color = self._simple_color # Bs contains the modules of the current level (= height = h) Bs = [s] # set the correct color for the vertex s if simple: if vertex_colors[simple_color].count(s) == 0: vertex_colors[simple_color].append(s) elif vertex_colors[nonsimple_color].count(s) == 0: vertex_colors[nonsimple_color].append(s) ################################################### # MAIN LOOP # we loop until we haven't found any simple fqm's ################################################### while simple: h = h + 1 if not heights.has_key(h): heights[h] = list() # the list Bss will contain the k-simple modules of the next height level # recall that Bs contains the modules of the current height level Bss = list() simple = False # checklist = modules that we need to check for with .is_simple(k) # we assemble this list because afterwards # we check them in parallel checklist = [] for s1 in Bs: Bs2 = list() for p in primes: # check if we really need to check p for s1 # otherwise none of the fqm's in s1.C(p) are simple # and we will not consider them. if prime_pol(s1.genus_symbol(), p, k) <= 0: Bs2 = Bs2 + s1.genus_symbol().C(p, False) else: logger.info("Skipping p = {0} for s1 = {1}".format( p, s1)) # print "Skipping p = {0} for s1 = {1}".format(p, s1) # print "Bs2 = ", Bs2 # now we actually check the symbols in Bs2 for s2 in Bs2: if s2.max_rank() > self._rank_limit: # we skip s2 if its minimal number of generators # is > than the given rank_limit. continue s2 = FQM_vertex(s2) skip = False for v in self._heights[h]: # we skip symbols that correspond to isomorphic modules if v.genus_symbol().defines_isomorphic_module( s2.genus_symbol()): skip = True logger.debug( "skipping {0} b/c isomorphic to {1}".format( s2.genus_symbol(), v.genus_symbol())) s2 = v break if skip: continue if not skip: self.add_vertex(s2) heights[h].append(s2) self.update_edges(s2, h, fast=fast) # before using the actual dimension formula # we check if there is already a non-k-simple neighbor # (an incoming edge from a non-k-simple module) # which would imply that s2 is not k-simple. has_nonsimple_neighbor = False for e in self.incoming_edges(s2): if vertex_colors[nonsimple_color].count(e[0]) > 0: has_nonsimple_neighbor = True logger.debug("Has nonsimple neighbor: {0}".format( s2.genus_symbol())) break if has_nonsimple_neighbor: #not simple if not vertex_colors[nonsimple_color].count(s2) > 0: vertex_colors[nonsimple_color].append(s2) else: checklist.append((s2, k, self._reduction, self._bound)) logger.debug("checklist = {0}".format(checklist)) # check the modules in checklist # for being k-simple # this is done in parallel # when a process returns # we add the vertex and give it its appropriate color if NCPUS1 == 1: checks = [([[s[0]]], check_simple(*s)) for s in checklist] else: checks = list(check_simple(checklist)) logger.info("checks = {0}".format(checks)) for check in checks: s2 = check[0][0][0] if check[1]: simple = True logger.info("Found simple module: {0}".format( s2.genus_symbol())) Bss.append(s2) if not vertex_colors[simple_color].count(s2) > 0: vertex_colors[simple_color].append(s2) else: if not vertex_colors[nonsimple_color].count(s2) > 0: vertex_colors[nonsimple_color].append(s2) Bs = Bss simple = [v.genus_symbol() for v in vertex_colors[simple_color]] self._simple = uniq(simple)