def spanning_stars(M): r""" Returns the edges of a connected subgraph that is a union of all edges incident some subset of vertices. INPUT: - ``M`` -- a matrix defining a bipartite graph G. The vertices are the rows and columns, if `M[i,j]` is non-zero, then there is an edge between row i and column 0. OUTPUT: A list of tuples `(row,column)` in a spanning forest of the bipartite graph defined by ``M`` EXAMPLES:: sage: edges = sage.matroids.utilities.spanning_stars(matrix([[1,1,1],[1,1,1],[1,1,1]])) sage: Graph([(x+3, y) for x,y in edges]).is_connected() True """ G = Graph() m = M.ncols() for (x,y) in M.dict(): G.add_edge(x+m,y) delta = (M.nrows()+m)**0.5 # remove low degree vertices H = [] # candidate vertices V_0 = set([]) d = 0 while G.order()>0: (x,d) = min(G.degree_iterator(labels=True),key=itemgetter(1)) if d < delta: V_0.add(x) H.extend(G.edges_incident(x,False)) G.delete_vertex(x) else: break # min degree is at least sqrt(n) # greedily remove vertices G2 = G.copy() # set of picked vertices V_1 = set([]) while G2.order()>0: # choose vertex with maximum degree in G2 (x,d) = max(G2.degree_iterator(labels=True),key=itemgetter(1)) V_1.add(x) G2.delete_vertices(G2.neighbors(x)) G2.delete_vertex(x) # G2 is a graph of all edges incident to V_1 G2 = Graph() for v in V_1: for u in G.neighbors(v): G2.add_edge(u,v) V = V_0 | V_1 # compute a spanning tree T = spanning_forest(M) for (x,y) in T: if not x in V and not y in V: V.add(v) for v in V: if G.has_vertex(v): # some vertices are not in G H.extend(G.edges_incident(v,False)) # T contain all edges in some spanning tree T = [] for (x,y) in H: if x < m: t = x x = y y = t T.append((x-m,y)) return T
def spanning_stars(M): r""" Returns the edges of a connected subgraph that is a union of all edges incident some subset of vertices. INPUT: - ``M`` -- a matrix defining a bipartite graph G. The vertices are the rows and columns, if `M[i,j]` is non-zero, then there is an edge between row i and column 0. OUTPUT: A list of tuples `(row,column)` in a spanning forest of the bipartite graph defined by ``M`` EXAMPLES:: sage: edges = sage.matroids.utilities.spanning_stars(matrix([[1,1,1],[1,1,1],[1,1,1]])) sage: Graph([(x+3, y) for x,y in edges]).is_connected() True """ G = Graph() m = M.ncols() for (x, y) in M.dict(): G.add_edge(x + m, y) delta = (M.nrows() + m)**0.5 # remove low degree vertices H = [] # candidate vertices V_0 = set([]) d = 0 while G.order() > 0: (x, d) = min(G.degree_iterator(labels=True), key=itemgetter(1)) if d < delta: V_0.add(x) H.extend(G.edges_incident(x, False)) G.delete_vertex(x) else: break # min degree is at least sqrt(n) # greedily remove vertices G2 = G.copy() # set of picked vertices V_1 = set([]) while G2.order() > 0: # choose vertex with maximum degree in G2 (x, d) = max(G2.degree_iterator(labels=True), key=itemgetter(1)) V_1.add(x) G2.delete_vertices(G2.neighbors(x)) G2.delete_vertex(x) # G2 is a graph of all edges incident to V_1 G2 = Graph() for v in V_1: for u in G.neighbors(v): G2.add_edge(u, v) V = V_0 | V_1 # compute a spanning tree T = spanning_forest(M) for (x, y) in T: if not x in V and not y in V: V.add(v) for v in V: if G.has_vertex(v): # some vertices are not in G H.extend(G.edges_incident(v, False)) # T contain all edges in some spanning tree T = [] for (x, y) in H: if x < m: t = x x = y y = t T.append((x - m, y)) return T
class Isogeny_graph: # Class for construction isogeny graphs with 1 or more degrees # ls is a list of primes which define the defining degrees def __init__(self, E, ls, special=False): self._ls = ls j = E.j_invariant() self.field = E.base_field() self._graph = Graph(multiedges=True, loops=True) self._special = False self._graph.add_vertex(j) queue = [j] R = rainbow(len(ls) + 1) self._rainbow = R self._edge_colors = {R[i]: [] for i in range(len(ls))} while queue: color = 0 s = queue.pop(0) if s == 0 or s == 1728: self._special = True for l in ls: neighb = isogenous_curves(s, l) for i in neighb: if not self._graph.has_vertex(i[0]): queue.append(i[0]) self._graph.add_vertex(i[0]) if not ((s, i[0], l) in self._edge_colors[R[color]] or (i[0], s, l) in self._edge_colors[R[color]]): for _ in range(i[1]): self._graph.add_edge((s, i[0], l)) self._edge_colors[R[color]].append((s, i[0], l)) color += 1 if self._special and special: print("Curve with j_invariant 0 or 1728 found, may malfunction.") def __repr__(self): return "Isogeny graph of degrees %r" % (self._ls) # Returns degrees of isogenies def degrees(self): return self._ls # Returns list of all edges def edges(self): return self._graph.edges() # Returns list of all vertices def vertices(self): return self._graph.vertices() # Plots the graph # Optional arguments figsize, vertex_size, vertex_labels and layout which are the same as in igraph def plot(self, figsize=None, edge_labels=False, vertex_size=None, layout=None): if vertex_size == None: return self._graph.plot(edge_colors=self._edge_colors, figsize=figsize, edge_labels=edge_labels, layout=layout) else: return self._graph.plot(edge_colors=self._edge_colors, figsize=figsize, edge_labels=edge_labels, vertex_size=vertex_size, layout=layout)