Changeset 7495:92dacf17ba77


Ignore:
Timestamp:
12/02/07 00:07:26 (5 years ago)
Author:
mabshoff@…
Branch:
default
Parents:
7492:22c24fe79fcf (diff), 7494:ac2e1bfbd5dd (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Tags:
2.8.15.alpha2
Message:

merge

Location:
sage/graphs
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • sage/graphs/graph.py

    r7460 r7495  
    36623662        """ 
    36633663        L = self._nxg.edges() 
    3664         if sort: 
    3665             L.sort() 
    36663664        if labels: 
    3667             return L 
     3665            if sort: 
     3666                return sorted(L) 
     3667            else: 
     3668                return L 
    36683669        else: 
    3669             return [(u,v) for u,v,_ in L] 
    3670  
     3670            if sort: 
     3671                return sorted([tuple(sorted((u,v))) for u,v,_ in L]) 
     3672            else: 
     3673                return [(u,v) for u,v,_ in L] 
    36713674 
    36723675    def edge_boundary(self, vertices1, vertices2=None, labels=True): 
  • sage/graphs/graph.py

    r7493 r7495  
    26372637            sage: C.plot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show() 
    26382638 
     2639            sage: D = graphs.DodecahedralGraph() 
     2640            sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]] 
     2641            sage: D.show(partition=Pi) 
     2642 
    26392643        """ 
    26402644        from sage.plot.plot import networkx_plot 
     2645        from sage.plot.plot import rainbow 
    26412646        import networkx 
    26422647        if vertex_colors is None: 
     
    27822787            ...            edge_colors[R[i]].append((u,v,l)) 
    27832788            sage: C.plot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show() 
     2789 
     2790            sage: D = graphs.DodecahedralGraph() 
     2791            sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]] 
     2792            sage: D.show(partition=Pi) 
    27842793 
    27852794        """ 
  • sage/graphs/graph_generators.py

    r7432 r7495  
    26652665################################################################################ 
    26662666     
    2667     def __call__(self, vertices, property=lambda x: True): 
    2668         """ 
    2669         Accesses the generator of isomorphism class representatives. 
    2670          
     2667    def __call__(self, vertices, property=lambda x: True, augment='edges'): 
     2668        """ 
     2669        Accesses the generator of isomorphism class representatives. Iterates 
     2670        over distinct, exhaustive representatives. 
     2671 
    26712672        INPUT: 
    2672             vertices -- the maximum number of vertices in the graphs to be 
    2673                 generated. 
     2673            vertices -- natural number 
    26742674            property -- any property to be tested on graphs before generation. 
    2675                 If for any graph G satisfying the property, every subgraph, 
    2676                 obtained from G by deleting one vertex and only edges incident 
    2677                 to that vertex satisfies the property, then this will generate 
    2678                 all graphs with that property. If this does not hold, then all 
    2679                 the graphs generated will satisfy the property, but there will 
    2680                 be some missing. 
    2681          
    2682         NOTE: 
    2683             There could be other implementations of the algorithm so that the 
    2684             restriction on 'property' was also different- the restriction is 
    2685             specific to this particular implementation. 
    2686          
     2675            augment -- choices: 
     2676                'vertices' -- augments by adding a vertex, and edges incident 
     2677                    to that vertex. 
     2678                    In this case, all graphs on up to n=vertices are generated. 
     2679                    If for any graph G satisfying the property, every subgraph, 
     2680                    obtained from G by deleting one vertex and only edges incident 
     2681                    to that vertex, satisfies the property, then this will generate 
     2682                    all graphs with that property. If this does not hold, then all 
     2683                    the graphs generated will satisfy the property, but there will 
     2684                    be some missing. 
     2685                'edges' -- augments a fixed number of vertices by adding one edge 
     2686                    In this case, all graphs on exactly n=vertices are generated. 
     2687                    If for any graph G satisfying the property, every subgraph, 
     2688                    obtained from G by deleting one edge but not the vertices 
     2689                    incident to that edge, satisfies the property, then this will 
     2690                    generate all graphs with that property. If this does not hold, 
     2691                    then all the graphs generated will satisfy the property, but 
     2692                    there will be some missing. 
     2693 
    26872694        EXAMPLES: 
    26882695        Print graphs on 3 or less vertices. 
    2689             sage: for G in graphs(3): 
     2696            sage: for G in graphs(3, augment='vertices'): 
    26902697            ...    print G 
    26912698            ... 
     
    26982705            Graph on 2 vertices 
    26992706            Graph on 3 vertices 
    2700          
    2701         Generate all graphs with up to 5 vertices and up to 4 edges. 
     2707 
     2708        Print graphs on 3 vertices. 
     2709            sage: for G in graphs(3): 
     2710            ...    print G 
     2711            ... 
     2712            Graph on 3 vertices 
     2713            Graph on 3 vertices 
     2714            Graph on 3 vertices 
     2715            Graph on 3 vertices 
     2716         
     2717        Generate all graphs with 5 vertices and up to 4 edges. 
    27022718            sage: L = list(graphs(5, lambda G: G.size() <= 4)) 
    27032719            sage: len(L) 
    2704             31 
     2720            13 
    27052721            sage: graphs_list.show_graphs(L)    # long time 
    27062722         
    27072723        Generate all graphs with degree at most 2, up to 6 vertices. 
    27082724            sage: property = lambda G: ( max([G.degree(v) for v in G] + [0]) <= 2 ) 
    2709             sage: L = list(graphs(6, property)) 
     2725            sage: L = list(graphs(6, property, augment='vertices')) 
    27102726            sage: len(L) 
    27112727            45 
    27122728         
    2713         Generate all bipartite graphs on up to 7, 8 vertices: 
    2714             sage: L = list( graphs(7, lambda G: G.is_bipartite()) ) 
     2729        Generate all bipartite graphs on up to 7 vertices: 
     2730            sage: L = list( graphs(7, lambda G: G.is_bipartite(), augment='vertices') ) 
    27152731            sage: len(L) 
    27162732            133 
    2717             sage: L = list( graphs(8, lambda G: G.is_bipartite()) ) # long time (30 secs) 
    2718             sage: len(L)                                            # long time 
    2719             354 
     2733 
     2734        Generate all bipartite graphs on exactly 8 vertices: 
     2735            sage: L = list( graphs(8, lambda G: G.is_bipartite()) ) 
     2736            sage: len(L) 
     2737            38 
    27202738         
    27212739        REFERENCE: 
     
    27232741            Algorithms Volume 26, Issue 2, February 1998, pages 306-324. 
    27242742        """ 
    2725         from sage.graphs.graph_fast import binary 
    27262743        from sage.graphs.graph import Graph 
    27272744        g = Graph() 
    2728         for gg in canaug_traverse(g, [], vertices, property): 
    2729             yield gg 
    2730  
    2731 def canaug_traverse(g, aut_gens, max_verts, property): 
     2745        if augment == 'vertices': 
     2746            for gg in canaug_traverse_vert(g, [], vertices, property): 
     2747                yield gg 
     2748        elif augment == 'edges': 
     2749            g.add_vertices(range(vertices)) 
     2750            gens = [] 
     2751            for i in range(vertices-1): 
     2752                gen = range(i) 
     2753                gen.append(i+1); gen.append(i) 
     2754                gen += range(i+2, vertices) 
     2755                gens.append(gen) 
     2756            for gg in canaug_traverse_edge(g, gens, property): 
     2757                yield gg 
     2758        else: 
     2759            raise NotImplementedError() 
     2760 
     2761def canaug_traverse_vert(g, aut_gens, max_verts, property): 
    27322762    """ 
    27332763    Main function for exhaustive generation. Recursive traversal of a 
     
    27422772     
    27432773    EXAMPLES: 
    2744         sage: from sage.graphs.graph_generators import canaug_traverse 
    2745         sage: list(canaug_traverse(Graph(), [], 3, lambda x: True)) 
     2774        sage: from sage.graphs.graph_generators import canaug_traverse_vert 
     2775        sage: list(canaug_traverse_vert(Graph(), [], 3, lambda x: True)) 
    27462776        [Graph on 0 vertices, ... Graph on 3 vertices] 
    27472777 
     
    27492779     
    27502780    Print graphs on 3 or less vertices. 
    2751         sage: for G in graphs(3): 
     2781        sage: for G in graphs(3, augment='vertices'): 
    27522782        ...    print G 
    27532783        ... 
     
    27622792     
    27632793    Generate all graphs with up to 5 vertices and up to 4 edges. 
    2764         sage: L = list(graphs(5, lambda G: G.size() <= 4)) 
     2794        sage: L = list(graphs(5, lambda G: G.size() <= 4, augment='vertices')) 
    27652795        sage: len(L) 
    27662796        31 
     
    27682798     
    27692799    Generate all bipartite graphs on up to 7 vertices: 
    2770         sage: L = list( graphs(7, lambda G: G.is_bipartite()) ) 
     2800        sage: L = list( graphs(7, lambda G: G.is_bipartite(), augment='vertices') ) 
    27712801        sage: len(L) 
    27722802        133     
     
    28302860            m_z = z.subgraph(sub_verts) 
    28312861             
    2832             perm = range(n+1) 
    2833             seen_perms = [perm] 
    28342862            if m_z == g: 
    2835                 for a in canaug_traverse(z, z_aut_gens, max_verts, property): 
     2863                for a in canaug_traverse_vert(z, z_aut_gens, max_verts, property): 
    28362864                    yield a 
    28372865            else: 
    28382866                for possibility in check_aut(z_aut_gens, cut_vert, n): 
    28392867                    if m_z.relabel(possibility, inplace=False) == g: 
    2840                         for a in canaug_traverse(z, z_aut_gens, max_verts, property): 
     2868                        for a in canaug_traverse_vert(z, z_aut_gens, max_verts, property): 
    28412869                            yield a 
    28422870                        break 
     
    28762904                    yield new_perm 
    28772905 
     2906def canaug_traverse_edge(g, aut_gens, property): 
     2907    """ 
     2908    Main function for exhaustive generation. Recursive traversal of a 
     2909    canonically generated tree of isomorph free graphs satisfying a given 
     2910    property. 
     2911     
     2912    INPUT: 
     2913        g -- current position on the tree. 
     2914        aut_gens -- list of generators of Aut(g), in list notation. 
     2915        property -- check before traversing below g. 
     2916     
     2917    EXAMPLES: 
     2918        sage: from sage.graphs.graph_generators import canaug_traverse_edge 
     2919        sage: G = Graph(); G.add_vertices(range(3)) 
     2920        sage: list(canaug_traverse_edge(G, [], lambda x: True)) 
     2921        [Graph on 3 vertices, ... Graph on 3 vertices] 
     2922 
     2923    The best way to access this function is through the graphs() iterator: 
     2924     
     2925    Print graphs on 3 or less vertices. 
     2926        sage: for G in graphs(3): 
     2927        ...    print G 
     2928        ... 
     2929        Graph on 3 vertices 
     2930        Graph on 3 vertices 
     2931        Graph on 3 vertices 
     2932        Graph on 3 vertices 
     2933     
     2934    Generate all graphs with 5 vertices and up to 4 edges. 
     2935        sage: L = list(graphs(5, lambda G: G.size() <= 4)) 
     2936        sage: len(L) 
     2937        13 
     2938        sage: graphs_list.show_graphs(L)              # long time 
     2939     
     2940    Generate all bipartite graphs on 7 vertices: 
     2941        sage: L = list( graphs(7, lambda G: G.is_bipartite()) ) 
     2942        sage: len(L) 
     2943        23     
     2944 
     2945    """ 
     2946    from sage.graphs.graph_fast import binary 
     2947    from sage.graphs.graph_isom import search_tree 
     2948    if not property(g): 
     2949        return 
     2950    yield g 
     2951    n = g.order() 
     2952    n_choose_2 = (n*(n-1))>>1 # >> 1 is just / 2 
     2953    if g.size() < n_choose_2: 
     2954         
     2955        # build a list representing C(g) - the edge to be added 
     2956        # is one of n*(n-1)/2 choices 
     2957        num_roots = n_choose_2 
     2958        children = [[(j-1,i) for i in range(j-1)] for j in range(1,n+1)] 
     2959         
     2960        # union-find C(g) under Aut(g) 
     2961        for gen in aut_gens: 
     2962            for i in xrange(n): 
     2963                for j in xrange(i): # i > j 
     2964                    if children[i][j] == (i,j): 
     2965                        y, x = sorted([gen[i], gen[j]]) 
     2966                        if x < i: 
     2967                            children[i][j] = (x, y) 
     2968                        elif x > i: 
     2969                            children[x][y] = (i, j) 
     2970                        elif y < j: 
     2971                            children[i][j] = (x, y) 
     2972                        elif y > j: 
     2973                            children[x][y] = (i, j) 
     2974                        else: 
     2975                            continue 
     2976                        num_roots -= 1 
     2977 
     2978        # find representatives of orbits of C(g) 
     2979        roots = [] 
     2980        found_roots = 0 
     2981        i = 0; j = 1 
     2982        while found_roots < num_roots: 
     2983            if children[j][i] == (j, i): 
     2984                found_roots += 1 
     2985                roots.append((i, j)) 
     2986            if j < n - 1: 
     2987                j += 1 
     2988            elif i < j: # j == n-1 
     2989                i += 1 
     2990                j = i + 1 
     2991         
     2992        for i, j in roots: 
     2993            if g.has_edge(i, j): 
     2994                continue 
     2995            # construct a z for each edge in roots... 
     2996            z = g.copy() 
     2997            z.add_edge(i, j) 
     2998 
     2999            z_aut_gens, _, canonical_relabeling = search_tree(z, [z.vertices()], certify=True) 
     3000            relabel_inverse = [0]*n 
     3001            for i in xrange(n): 
     3002                relabel_inverse[canonical_relabeling[i]] = i 
     3003            z_can = z.relabel(canonical_relabeling, inplace=False) 
     3004            cut_edge_can = z_can.edges(labels=False, sort=True)[-1] 
     3005            cut_edge = [relabel_inverse[cut_edge_can[0]], relabel_inverse[cut_edge_can[1]]] 
     3006            cut_edge = tuple(sorted(cut_edge)) 
     3007 
     3008            m_z = z.copy() 
     3009            m_z.delete_edge(cut_edge) 
     3010 
     3011            if m_z == g: 
     3012                for a in canaug_traverse_edge(z, z_aut_gens, property): 
     3013                    yield a 
     3014            else: 
     3015                for possibility in check_aut_edge(z_aut_gens, cut_edge, i, j, n): 
     3016                    if m_z.relabel(possibility, inplace=False) == g: 
     3017                        for a in canaug_traverse_edge(z, z_aut_gens, property): 
     3018                            yield a 
     3019                        break 
     3020 
     3021def check_aut_edge(aut_gens, cut_edge, i, j, n): 
     3022    """ 
     3023    Helper function for exhaustive generation. 
     3024     
     3025    At the start, check_aut_edge is given a set of generators for the automorphism 
     3026    group, aut_gens. We already know we are looking for an element of the auto- 
     3027    morphism group that sends cut_edge to \{i, j\}, and check_aut generates 
     3028    these for the canaug_traverse function. 
     3029     
     3030    EXAMPLE: 
     3031    Note that the last two entries indicate that none of the automorphism group 
     3032    has yet been searched - we are starting at the identity [0, 1, 2, 3] and so 
     3033    far that is all we have seen. We return automorphisms mapping 2 to 3. 
     3034        sage: from sage.graphs.graph_generators import check_aut 
     3035        sage: list( check_aut( [ [0, 3, 2, 1], [1, 0, 3, 2], [2, 1, 0, 3] ], 2, 3)) 
     3036        [[1, 0, 3, 2], [1, 2, 3, 0]] 
     3037 
     3038    """ 
     3039    from copy import copy 
     3040    perm = range(n) 
     3041    seen_perms = [perm] 
     3042    unchecked_perms = [perm] 
     3043    while len(unchecked_perms) != 0: 
     3044        perm = unchecked_perms.pop(0) 
     3045        for gen in aut_gens: 
     3046            new_perm = copy(perm) 
     3047            for i in xrange(n): 
     3048                new_perm[i] = gen[perm[i]] 
     3049            if new_perm not in seen_perms: 
     3050                seen_perms.append(new_perm) 
     3051                unchecked_perms.append(new_perm) 
     3052                if new_perm[cut_edge[0]] == i and new_perm[cut_edge[1]] == j: 
     3053                    yield new_perm 
     3054                if new_perm[cut_edge[0]] == j and new_perm[cut_edge[1]] == i: 
     3055                    yield new_perm 
     3056 
    28783057# Easy access to the graph generators from the command line: 
    28793058graphs = GraphGenerators() 
  • sage/graphs/graph_generators.py

    r7494 r7495  
    307307        return graph.Graph(G, pos=pos_dict, name="Bull Graph") 
    308308         
     309 
     310    def ButterflyGraph(self, n, vertices='strings'): 
     311        """ 
     312        Returns a n-dimensional butterfly graph.  The vertices consist 
     313        of pairs (v,i), where v is an n-dimensional tuple (vector) 
     314        with binary entries (or a string representation of such)  
     315        and i is an integer in [0..n].  A directed 
     316        edge goes from (v,i) to (w,i+1) if v and w are identical 
     317        except for possibly v[i] != w[i]. 
     318 
     319        A butterfly graph has (2^n)(n+1) vertices and n2^(n+1) edges. 
     320 
     321        INPUT: 
     322            vertices -- 'strings' (default) or 'vectors', specifying 
     323            whether the vertices are zero-one strings or actually 
     324            tuples over GF(2). 
     325         
     326        EXAMPLES: 
     327        sage: graphs.ButterflyGraph(2).edges(labels=False) 
     328        [(('00', 0), ('00', 1)), 
     329        (('00', 0), ('10', 1)), 
     330        (('00', 1), ('00', 2)), 
     331        (('00', 1), ('01', 2)), 
     332        (('01', 0), ('01', 1)), 
     333        (('01', 0), ('11', 1)), 
     334        (('01', 1), ('00', 2)), 
     335        (('01', 1), ('01', 2)), 
     336        (('10', 0), ('00', 1)), 
     337        (('10', 0), ('10', 1)), 
     338        (('10', 1), ('10', 2)), 
     339        (('10', 1), ('11', 2)), 
     340        (('11', 0), ('01', 1)), 
     341        (('11', 0), ('11', 1)), 
     342        (('11', 1), ('10', 2)), 
     343        (('11', 1), ('11', 2))] 
     344        sage: graphs.ButterflyGraph(2,vertices='vectors').edges(labels=False) 
     345        [(((0, 0), 0), ((0, 0), 1)), 
     346        (((0, 0), 0), ((1, 0), 1)), 
     347        (((0, 0), 1), ((0, 0), 2)), 
     348        (((0, 0), 1), ((0, 1), 2)), 
     349        (((0, 1), 0), ((0, 1), 1)), 
     350        (((0, 1), 0), ((1, 1), 1)), 
     351        (((0, 1), 1), ((0, 0), 2)), 
     352        (((0, 1), 1), ((0, 1), 2)), 
     353        (((1, 0), 0), ((0, 0), 1)), 
     354        (((1, 0), 0), ((1, 0), 1)), 
     355        (((1, 0), 1), ((1, 0), 2)), 
     356        (((1, 0), 1), ((1, 1), 2)), 
     357        (((1, 1), 0), ((0, 1), 1)), 
     358        (((1, 1), 0), ((1, 1), 1)), 
     359        (((1, 1), 1), ((1, 0), 2)), 
     360        (((1, 1), 1), ((1, 1), 2))] 
     361         
     362        """ 
     363        # We could switch to Sage integers to handle arbitrary n. 
     364        if vertices=='strings': 
     365            if n>=31: 
     366                raise NotImplementedError, "vertices='strings' is only valid for n<=30." 
     367            from sage.graphs.graph_fast import binary 
     368            butterfly = {} 
     369            for v in xrange(2**n): 
     370                for i in range(n): 
     371                    w = v 
     372                    w ^= (1 << i)   # push 1 to the left by i and xor with w 
     373                    bv = binary(v) 
     374                    bw = binary(w) 
     375                    # pad and reverse the strings 
     376                    padded_bv = ('0'*(n-len(bv))+bv)[::-1] 
     377                    padded_bw = ('0'*(n-len(bw))+bw)[::-1] 
     378                    butterfly[(padded_bv,i)]=[(padded_bv,i+1), (padded_bw,i+1)] 
     379        elif vertices=='vectors': 
     380            from sage.modules.free_module import VectorSpace 
     381            from sage.rings.finite_field import FiniteField 
     382            from copy import copy 
     383            butterfly = {} 
     384            for v in VectorSpace(FiniteField(2),n): 
     385                for i in xrange(n): 
     386                    w=copy(v) 
     387                    w[i] += 1 # Flip the ith bit 
     388                    # We must call tuple since vectors are mutable.  To obtain 
     389                    # a vector from the tuple t, just call vector(t). 
     390                    butterfly[(tuple(v),i)]=[(tuple(v),i+1), (tuple(w),i+1)] 
     391        else: 
     392            raise NotImplementedError, "vertices must be 'strings' or 'vectors'." 
     393        return graph.DiGraph(butterfly) 
    309394         
    310395    def CircularLadderGraph(self, n): 
Note: See TracChangeset for help on using the changeset viewer.