Changeset 7493:ec2dbddf8eba
- Timestamp:
- 12/01/07 23:27:41 (5 years ago)
- Branch:
- default
- Location:
- sage/graphs
- Files:
-
- 2 edited
-
graph.py (modified) (1 diff)
-
graph_generators.py (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sage/graphs/graph.py
r7369 r7493 3653 3653 """ 3654 3654 L = self._nxg.edges() 3655 if sort:3656 L.sort()3657 3655 if labels: 3658 return L 3656 if sort: 3657 return sorted(L) 3658 else: 3659 return L 3659 3660 else: 3660 return [(u,v) for u,v,_ in L] 3661 3661 if sort: 3662 return sorted([tuple(sorted((u,v))) for u,v,_ in L]) 3663 else: 3664 return [(u,v) for u,v,_ in L] 3662 3665 3663 3666 def edge_boundary(self, vertices1, vertices2=None, labels=True): -
sage/graphs/graph_generators.py
r7395 r7493 2580 2580 ################################################################################ 2581 2581 2582 def __call__(self, vertices, property=lambda x: True): 2583 """ 2584 Accesses the generator of isomorphism class representatives. 2585 2582 def __call__(self, vertices, property=lambda x: True, augment='edges'): 2583 """ 2584 Accesses the generator of isomorphism class representatives. Iterates 2585 over distinct, exhaustive representatives. 2586 2586 2587 INPUT: 2587 vertices -- the maximum number of vertices in the graphs to be 2588 generated. 2588 vertices -- natural number 2589 2589 property -- any property to be tested on graphs before generation. 2590 If for any graph G satisfying the property, every subgraph, 2591 obtained from G by deleting one vertex and only edges incident 2592 to that vertex satisfies the property, then this will generate 2593 all graphs with that property. If this does not hold, then all 2594 the graphs generated will satisfy the property, but there will 2595 be some missing. 2596 2597 NOTE: 2598 There could be other implementations of the algorithm so that the 2599 restriction on 'property' was also different- the restriction is 2600 specific to this particular implementation. 2601 2590 augment -- choices: 2591 'vertices' -- augments by adding a vertex, and edges incident 2592 to that vertex. 2593 In this case, all graphs on up to n=vertices are generated. 2594 If for any graph G satisfying the property, every subgraph, 2595 obtained from G by deleting one vertex and only edges incident 2596 to that vertex, satisfies the property, then this will generate 2597 all graphs with that property. If this does not hold, then all 2598 the graphs generated will satisfy the property, but there will 2599 be some missing. 2600 'edges' -- augments a fixed number of vertices by adding one edge 2601 In this case, all graphs on exactly n=vertices are generated. 2602 If for any graph G satisfying the property, every subgraph, 2603 obtained from G by deleting one edge but not the vertices 2604 incident to that edge, satisfies the property, then this will 2605 generate all graphs with that property. If this does not hold, 2606 then all the graphs generated will satisfy the property, but 2607 there will be some missing. 2608 2602 2609 EXAMPLES: 2603 2610 Print graphs on 3 or less vertices. 2604 sage: for G in graphs(3 ):2611 sage: for G in graphs(3, augment='vertices'): 2605 2612 ... print G 2606 2613 ... … … 2613 2620 Graph on 2 vertices 2614 2621 Graph on 3 vertices 2615 2616 Generate all graphs with up to 5 vertices and up to 4 edges. 2622 2623 Print graphs on 3 vertices. 2624 sage: for G in graphs(3): 2625 ... print G 2626 ... 2627 Graph on 3 vertices 2628 Graph on 3 vertices 2629 Graph on 3 vertices 2630 Graph on 3 vertices 2631 2632 Generate all graphs with 5 vertices and up to 4 edges. 2617 2633 sage: L = list(graphs(5, lambda G: G.size() <= 4)) 2618 2634 sage: len(L) 2619 312635 13 2620 2636 sage: graphs_list.show_graphs(L) # long time 2621 2637 2622 2638 Generate all graphs with degree at most 2, up to 6 vertices. 2623 2639 sage: property = lambda G: ( max([G.degree(v) for v in G] + [0]) <= 2 ) 2624 sage: L = list(graphs(6, property ))2640 sage: L = list(graphs(6, property, augment='vertices')) 2625 2641 sage: len(L) 2626 2642 45 2627 2643 2628 Generate all bipartite graphs on up to 7 , 8vertices:2629 sage: L = list( graphs(7, lambda G: G.is_bipartite() ) )2644 Generate all bipartite graphs on up to 7 vertices: 2645 sage: L = list( graphs(7, lambda G: G.is_bipartite(), augment='vertices') ) 2630 2646 sage: len(L) 2631 2647 133 2632 sage: L = list( graphs(8, lambda G: G.is_bipartite()) ) # long time (30 secs) 2633 sage: len(L) # long time 2634 354 2648 2649 Generate all bipartite graphs on exactly 8 vertices: 2650 sage: L = list( graphs(8, lambda G: G.is_bipartite()) ) 2651 sage: len(L) 2652 38 2635 2653 2636 2654 REFERENCE: … … 2638 2656 Algorithms Volume 26, Issue 2, February 1998, pages 306-324. 2639 2657 """ 2640 from sage.graphs.graph_fast import binary2641 2658 from sage.graphs.graph import Graph 2642 2659 g = Graph() 2643 for gg in canaug_traverse(g, [], vertices, property): 2644 yield gg 2645 2646 def canaug_traverse(g, aut_gens, max_verts, property): 2660 if augment == 'vertices': 2661 for gg in canaug_traverse_vert(g, [], vertices, property): 2662 yield gg 2663 elif augment == 'edges': 2664 g.add_vertices(range(vertices)) 2665 gens = [] 2666 for i in range(vertices-1): 2667 gen = range(i) 2668 gen.append(i+1); gen.append(i) 2669 gen += range(i+2, vertices) 2670 gens.append(gen) 2671 for gg in canaug_traverse_edge(g, gens, property): 2672 yield gg 2673 else: 2674 raise NotImplementedError() 2675 2676 def canaug_traverse_vert(g, aut_gens, max_verts, property): 2647 2677 """ 2648 2678 Main function for exhaustive generation. Recursive traversal of a … … 2657 2687 2658 2688 EXAMPLES: 2659 sage: from sage.graphs.graph_generators import canaug_traverse 2660 sage: list(canaug_traverse (Graph(), [], 3, lambda x: True))2689 sage: from sage.graphs.graph_generators import canaug_traverse_vert 2690 sage: list(canaug_traverse_vert(Graph(), [], 3, lambda x: True)) 2661 2691 [Graph on 0 vertices, ... Graph on 3 vertices] 2662 2692 … … 2664 2694 2665 2695 Print graphs on 3 or less vertices. 2666 sage: for G in graphs(3 ):2696 sage: for G in graphs(3, augment='vertices'): 2667 2697 ... print G 2668 2698 ... … … 2677 2707 2678 2708 Generate all graphs with up to 5 vertices and up to 4 edges. 2679 sage: L = list(graphs(5, lambda G: G.size() <= 4 ))2709 sage: L = list(graphs(5, lambda G: G.size() <= 4, augment='vertices')) 2680 2710 sage: len(L) 2681 2711 31 … … 2683 2713 2684 2714 Generate all bipartite graphs on up to 7 vertices: 2685 sage: L = list( graphs(7, lambda G: G.is_bipartite() ) )2715 sage: L = list( graphs(7, lambda G: G.is_bipartite(), augment='vertices') ) 2686 2716 sage: len(L) 2687 2717 133 … … 2745 2775 m_z = z.subgraph(sub_verts) 2746 2776 2747 perm = range(n+1)2748 seen_perms = [perm]2749 2777 if m_z == g: 2750 for a in canaug_traverse (z, z_aut_gens, max_verts, property):2778 for a in canaug_traverse_vert(z, z_aut_gens, max_verts, property): 2751 2779 yield a 2752 2780 else: 2753 2781 for possibility in check_aut(z_aut_gens, cut_vert, n): 2754 2782 if m_z.relabel(possibility, inplace=False) == g: 2755 for a in canaug_traverse (z, z_aut_gens, max_verts, property):2783 for a in canaug_traverse_vert(z, z_aut_gens, max_verts, property): 2756 2784 yield a 2757 2785 break … … 2791 2819 yield new_perm 2792 2820 2821 def canaug_traverse_edge(g, aut_gens, property): 2822 """ 2823 Main function for exhaustive generation. Recursive traversal of a 2824 canonically generated tree of isomorph free graphs satisfying a given 2825 property. 2826 2827 INPUT: 2828 g -- current position on the tree. 2829 aut_gens -- list of generators of Aut(g), in list notation. 2830 property -- check before traversing below g. 2831 2832 EXAMPLES: 2833 sage: from sage.graphs.graph_generators import canaug_traverse_edge 2834 sage: list(canaug_traverse_edge(Graph(), [], lambda x: True)) 2835 [Graph on 3 vertices, ... Graph on 3 vertices] 2836 2837 The best way to access this function is through the graphs() iterator: 2838 2839 Print graphs on 3 or less vertices. 2840 sage: for G in graphs(3): 2841 ... print G 2842 ... 2843 Graph on 3 vertices 2844 Graph on 3 vertices 2845 Graph on 3 vertices 2846 Graph on 3 vertices 2847 2848 Generate all graphs with 5 vertices and up to 4 edges. 2849 sage: L = list(graphs(5, lambda G: G.size() <= 4)) 2850 sage: len(L) 2851 13 2852 sage: graphs_list.show_graphs(L) # long time 2853 2854 Generate all bipartite graphs on 7 vertices: 2855 sage: L = list( graphs(7, lambda G: G.is_bipartite()) ) 2856 sage: len(L) 2857 23 2858 2859 """ 2860 from sage.graphs.graph_fast import binary 2861 from sage.graphs.graph_isom import search_tree 2862 if not property(g): 2863 return 2864 yield g 2865 n = g.order() 2866 n_choose_2 = (n*(n-1))>>1 # >> 1 is just / 2 2867 if g.size() < n_choose_2: 2868 2869 # build a list representing C(g) - the edge to be added 2870 # is one of n*(n-1)/2 choices 2871 num_roots = n_choose_2 2872 children = [[(j-1,i) for i in range(j-1)] for j in range(1,n+1)] 2873 2874 # union-find C(g) under Aut(g) 2875 for gen in aut_gens: 2876 for i in xrange(n): 2877 for j in xrange(i): # i > j 2878 if children[i][j] == (i,j): 2879 y, x = sorted([gen[i], gen[j]]) 2880 if x < i: 2881 children[i][j] = (x, y) 2882 elif x > i: 2883 children[x][y] = (i, j) 2884 elif y < j: 2885 children[i][j] = (x, y) 2886 elif y > j: 2887 children[x][y] = (i, j) 2888 else: 2889 continue 2890 num_roots -= 1 2891 2892 # find representatives of orbits of C(g) 2893 roots = [] 2894 found_roots = 0 2895 i = 0; j = 1 2896 while found_roots < num_roots: 2897 if children[j][i] == (j, i): 2898 found_roots += 1 2899 roots.append((i, j)) 2900 if j < n - 1: 2901 j += 1 2902 elif i < j: # j == n-1 2903 i += 1 2904 j = i + 1 2905 2906 for i, j in roots: 2907 if g.has_edge(i, j): 2908 continue 2909 # construct a z for each edge in roots... 2910 z = g.copy() 2911 z.add_edge(i, j) 2912 2913 z_aut_gens, _, canonical_relabeling = search_tree(z, [z.vertices()], certify=True) 2914 relabel_inverse = [0]*n 2915 for i in xrange(n): 2916 relabel_inverse[canonical_relabeling[i]] = i 2917 z_can = z.relabel(canonical_relabeling, inplace=False) 2918 cut_edge_can = z_can.edges(labels=False, sort=True)[-1] 2919 cut_edge = [relabel_inverse[cut_edge_can[0]], relabel_inverse[cut_edge_can[1]]] 2920 cut_edge = tuple(sorted(cut_edge)) 2921 2922 m_z = z.copy() 2923 m_z.delete_edge(cut_edge) 2924 2925 if m_z == g: 2926 for a in canaug_traverse_edge(z, z_aut_gens, property): 2927 yield a 2928 else: 2929 for possibility in check_aut_edge(z_aut_gens, cut_edge, i, j, n): 2930 if m_z.relabel(possibility, inplace=False) == g: 2931 for a in canaug_traverse_edge(z, z_aut_gens, property): 2932 yield a 2933 break 2934 2935 def check_aut_edge(aut_gens, cut_edge, i, j, n): 2936 """ 2937 Helper function for exhaustive generation. 2938 2939 At the start, check_aut_edge is given a set of generators for the automorphism 2940 group, aut_gens. We already know we are looking for an element of the auto- 2941 morphism group that sends cut_edge to \{i, j\}, and check_aut generates 2942 these for the canaug_traverse function. 2943 2944 EXAMPLE: 2945 Note that the last two entries indicate that none of the automorphism group 2946 has yet been searched - we are starting at the identity [0, 1, 2, 3] and so 2947 far that is all we have seen. We return automorphisms mapping 2 to 3. 2948 sage: from sage.graphs.graph_generators import check_aut 2949 sage: list( check_aut( [ [0, 3, 2, 1], [1, 0, 3, 2], [2, 1, 0, 3] ], 2, 3)) 2950 [[1, 0, 3, 2], [1, 2, 3, 0]] 2951 2952 """ 2953 from copy import copy 2954 perm = range(n) 2955 seen_perms = [perm] 2956 unchecked_perms = [perm] 2957 while len(unchecked_perms) != 0: 2958 perm = unchecked_perms.pop(0) 2959 for gen in aut_gens: 2960 new_perm = copy(perm) 2961 for i in xrange(n): 2962 new_perm[i] = gen[perm[i]] 2963 if new_perm not in seen_perms: 2964 seen_perms.append(new_perm) 2965 unchecked_perms.append(new_perm) 2966 if new_perm[cut_edge[0]] == i and new_perm[cut_edge[1]] == j: 2967 yield new_perm 2968 if new_perm[cut_edge[0]] == j and new_perm[cut_edge[1]] == i: 2969 yield new_perm 2970 2793 2971 # Easy access to the graph generators from the command line: 2794 2972 graphs = GraphGenerators()
Note: See TracChangeset
for help on using the changeset viewer.
