Changeset 7495:92dacf17ba77
- Timestamp:
- 12/02/07 00:07:26 (5 years ago)
- 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
- Location:
- sage/graphs
- Files:
-
- 4 edited
-
graph.py (modified) (1 diff)
-
graph.py (modified) (2 diffs)
-
graph_generators.py (modified) (9 diffs)
-
graph_generators.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
sage/graphs/graph.py
r7460 r7495 3662 3662 """ 3663 3663 L = self._nxg.edges() 3664 if sort:3665 L.sort()3666 3664 if labels: 3667 return L 3665 if sort: 3666 return sorted(L) 3667 else: 3668 return L 3668 3669 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] 3671 3674 3672 3675 def edge_boundary(self, vertices1, vertices2=None, labels=True): -
sage/graphs/graph.py
r7493 r7495 2637 2637 sage: C.plot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show() 2638 2638 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 2639 2643 """ 2640 2644 from sage.plot.plot import networkx_plot 2645 from sage.plot.plot import rainbow 2641 2646 import networkx 2642 2647 if vertex_colors is None: … … 2782 2787 ... edge_colors[R[i]].append((u,v,l)) 2783 2788 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) 2784 2793 2785 2794 """ -
sage/graphs/graph_generators.py
r7432 r7495 2665 2665 ################################################################################ 2666 2666 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 2671 2672 INPUT: 2672 vertices -- the maximum number of vertices in the graphs to be 2673 generated. 2673 vertices -- natural number 2674 2674 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 2687 2694 EXAMPLES: 2688 2695 Print graphs on 3 or less vertices. 2689 sage: for G in graphs(3 ):2696 sage: for G in graphs(3, augment='vertices'): 2690 2697 ... print G 2691 2698 ... … … 2698 2705 Graph on 2 vertices 2699 2706 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. 2702 2718 sage: L = list(graphs(5, lambda G: G.size() <= 4)) 2703 2719 sage: len(L) 2704 312720 13 2705 2721 sage: graphs_list.show_graphs(L) # long time 2706 2722 2707 2723 Generate all graphs with degree at most 2, up to 6 vertices. 2708 2724 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')) 2710 2726 sage: len(L) 2711 2727 45 2712 2728 2713 Generate all bipartite graphs on up to 7 , 8vertices: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') ) 2715 2731 sage: len(L) 2716 2732 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 2720 2738 2721 2739 REFERENCE: … … 2723 2741 Algorithms Volume 26, Issue 2, February 1998, pages 306-324. 2724 2742 """ 2725 from sage.graphs.graph_fast import binary2726 2743 from sage.graphs.graph import Graph 2727 2744 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 2761 def canaug_traverse_vert(g, aut_gens, max_verts, property): 2732 2762 """ 2733 2763 Main function for exhaustive generation. Recursive traversal of a … … 2742 2772 2743 2773 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)) 2746 2776 [Graph on 0 vertices, ... Graph on 3 vertices] 2747 2777 … … 2749 2779 2750 2780 Print graphs on 3 or less vertices. 2751 sage: for G in graphs(3 ):2781 sage: for G in graphs(3, augment='vertices'): 2752 2782 ... print G 2753 2783 ... … … 2762 2792 2763 2793 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')) 2765 2795 sage: len(L) 2766 2796 31 … … 2768 2798 2769 2799 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') ) 2771 2801 sage: len(L) 2772 2802 133 … … 2830 2860 m_z = z.subgraph(sub_verts) 2831 2861 2832 perm = range(n+1)2833 seen_perms = [perm]2834 2862 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): 2836 2864 yield a 2837 2865 else: 2838 2866 for possibility in check_aut(z_aut_gens, cut_vert, n): 2839 2867 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): 2841 2869 yield a 2842 2870 break … … 2876 2904 yield new_perm 2877 2905 2906 def 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 3021 def 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 2878 3057 # Easy access to the graph generators from the command line: 2879 3058 graphs = GraphGenerators() -
sage/graphs/graph_generators.py
r7494 r7495 307 307 return graph.Graph(G, pos=pos_dict, name="Bull Graph") 308 308 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) 309 394 310 395 def CircularLadderGraph(self, n):
Note: See TracChangeset
for help on using the changeset viewer.
