Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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)