# HG changeset patch
# User Yann Laigle-Chapuy <yannlaiglechapuy@gmail.com>
# Date 1259682400 -3600
# Node ID 1244ebc79c9fe270a2d7a9da936bde1e94aaafb7
# Parent 6e1d0fcde31742fb9c905a7b01f6364baf06e242
use more dicts in graph.py
diff -r 6e1d0fcde317 -r 1244ebc79c9f sage/graphs/graph.py
|
a
|
b
|
|
| 2885 | 2885 | sage: D.connected_components() |
| 2886 | 2886 | [[0, 1, 2, 3], [4, 5, 6]] |
| 2887 | 2887 | """ |
| 2888 | | seen = [] |
| | 2888 | seen = set() |
| 2889 | 2889 | components = [] |
| 2890 | 2890 | for v in self: |
| 2891 | 2891 | if v not in seen: |
| 2892 | | c = list(self.breadth_first_search(v, ignore_direction=True)) |
| 2893 | | c.sort() |
| 2894 | | seen.extend(c) |
| | 2892 | c = self.connected_component_containing_vertex(v) |
| | 2893 | seen.update(c) |
| 2895 | 2894 | components.append(c) |
| 2896 | 2895 | components.sort(lambda comp1, comp2: cmp(len(comp2), len(comp1))) |
| 2897 | 2896 | return components |
| … |
… |
|
| 2979 | 2978 | sage: graphs.StarGraph(3).blocks_and_cut_vertices() |
| 2980 | 2979 | ([[1, 0], [2, 0], [3, 0]], [0]) |
| 2981 | 2980 | |
| | 2981 | TESTS:: |
| | 2982 | |
| | 2983 | sage: Graph(0).blocks_and_cut_vertices() |
| | 2984 | ([], []) |
| | 2985 | sage: Graph(1).blocks_and_cut_vertices() |
| | 2986 | ([0], [0]) |
| | 2987 | sage: Graph(2).blocks_and_cut_vertices() |
| | 2988 | Traceback (most recent call last): |
| | 2989 | ... |
| | 2990 | NotImplementedError: ... |
| | 2991 | |
| 2982 | 2992 | ALGORITHM: 8.3.8 in [1]. Notice that the termination condition on |
| 2983 | 2993 | line (23) of the algorithm uses "p[v] == 0" which in the book |
| 2984 | 2994 | means that the parent is undefined; in this case, v must be the |
| … |
… |
|
| 2991 | 3001 | - [1] D. Jungnickel, Graphs, Networks and Algorithms, |
| 2992 | 3002 | Springer, 2005. |
| 2993 | 3003 | """ |
| 2994 | | G = self.to_undirected() |
| 2995 | | map_to_ints = G.relabel(return_map=True) |
| 2996 | | s = G.vertex_iterator().next() |
| 2997 | | nr = [0]*G.num_verts() |
| 2998 | | p = [None]*G.num_verts() # no vertex has a parent until visited |
| 2999 | | L = [0]*G.num_verts() |
| 3000 | | edges = {} |
| 3001 | | for u,v in G.edges(labels=False): |
| 3002 | | edges[(u,v)] = False |
| 3003 | | edges[(v,u)] = False |
| | 3004 | if not self: # empty graph |
| | 3005 | return [],[] |
| | 3006 | |
| | 3007 | s = self.vertex_iterator().next() # source |
| | 3008 | |
| | 3009 | if len(self) == 1: # only one vertex |
| | 3010 | return [s],[s] |
| | 3011 | |
| | 3012 | if not self.is_connected(): |
| | 3013 | raise NotImplementedError("Blocks and cut vertices is currently only implemented for connected graphs.") |
| | 3014 | |
| | 3015 | nr = {} # enumerate |
| | 3016 | p = {} # predecessors |
| | 3017 | L = {} |
| | 3018 | visited_edges = set() |
| 3004 | 3019 | i = 1 |
| 3005 | | v = s |
| 3006 | | nr[s] = 1 |
| | 3020 | v = s # visited |
| | 3021 | nr[s] = 1 |
| 3007 | 3022 | L[s] = 1 |
| 3008 | | C = [] |
| 3009 | | B = [] |
| 3010 | | S = [s] |
| | 3023 | C = [] # cuts |
| | 3024 | B = [] # blocks |
| | 3025 | S = [s] #stack |
| | 3026 | its = {} |
| 3011 | 3027 | while True: |
| 3012 | 3028 | while True: |
| 3013 | | u = -1 |
| 3014 | | for u in G.neighbor_iterator(v): |
| 3015 | | if not edges[(v,u)]: break |
| 3016 | | if u == -1: break |
| 3017 | | if edges[(v,u)]: break |
| 3018 | | edges[(v,u)] = True |
| 3019 | | edges[(u,v)] = True |
| 3020 | | if nr[u] == 0: |
| | 3029 | for u in self.neighbor_iterator(v): |
| | 3030 | if not (v,u) in visited_edges: break |
| | 3031 | else: |
| | 3032 | break |
| | 3033 | visited_edges.add((v,u)) |
| | 3034 | visited_edges.add((u,v)) |
| | 3035 | if u not in nr: |
| 3021 | 3036 | p[u] = v |
| 3022 | 3037 | i += 1 |
| 3023 | 3038 | nr[u] = i |
| … |
… |
|
| 3025 | 3040 | S.append(u) |
| 3026 | 3041 | v = u |
| 3027 | 3042 | else: |
| 3028 | | L[v] = min([ L[v], nr[u] ]) |
| 3029 | | if p[v] != s: |
| 3030 | | if L[v] < nr[p[v]]: |
| 3031 | | L[p[v]] = min([ L[p[v]], L[v] ]) |
| 3032 | | else: |
| 3033 | | if p[v] not in C: |
| 3034 | | C.append(p[v]) |
| 3035 | | B_k = [] |
| 3036 | | while True: |
| 3037 | | u = S.pop(-1) |
| 3038 | | B_k.append(u) |
| 3039 | | if u == v: break |
| 3040 | | B_k.append(p[v]) |
| 3041 | | B.append(B_k) |
| 3042 | | else: |
| 3043 | | if any([ not edges[(s,u)] for u in G.neighbors(s)]) and p[v] not in C: |
| 3044 | | C.append(s) |
| 3045 | | B_k = [] |
| 3046 | | while True: |
| 3047 | | u = S.pop(-1) |
| 3048 | | B_k.append(u) |
| 3049 | | if u == v: break |
| 3050 | | B_k.append(s) |
| 3051 | | B.append(B_k) |
| 3052 | | v = p[v] |
| 3053 | | if v == s and all([edges[(v,u)] for u in G.neighbors(v)]): |
| | 3043 | L[v] = min( L[v], nr[u] ) |
| | 3044 | |
| | 3045 | if v is s: |
| 3054 | 3046 | break |
| | 3047 | |
| | 3048 | pv = p[v] |
| | 3049 | if L[v] < nr[pv]: |
| | 3050 | L[pv] = min( L[pv], L[v] ) |
| | 3051 | v = pv |
| | 3052 | continue |
| | 3053 | |
| | 3054 | if pv not in C: |
| | 3055 | if pv is not s or\ |
| | 3056 | not all([(s,u) in visited_edges for u in self.neighbor_iterator(s)]): |
| | 3057 | C.append(pv) |
| | 3058 | |
| | 3059 | B_k = [] |
| | 3060 | while True: |
| | 3061 | u = S.pop() |
| | 3062 | B_k.append(u) |
| | 3063 | if u == v: break |
| | 3064 | B_k.append(pv) |
| | 3065 | B.append(B_k) |
| | 3066 | |
| | 3067 | v = pv |
| 3055 | 3068 | return B, C |
| 3056 | 3069 | |
| 3057 | 3070 | ### Vertex handlers |
| … |
… |
|
| 5568 | 5581 | sage: graphs.trees(9).next().girth() |
| 5569 | 5582 | +Infinity |
| 5570 | 5583 | """ |
| 5571 | | G = self.to_undirected() |
| 5572 | | G.relabel() # vertices are now {0, ..., n-1} |
| 5573 | | n = G.num_verts() |
| | 5584 | n = self.num_verts() |
| 5574 | 5585 | best = n+1 |
| 5575 | | for i in range(n-2): |
| 5576 | | span = [0]*n |
| 5577 | | span[i] = 1 |
| | 5586 | for i in self.vertex_iterator(): |
| | 5587 | span = set([i]) |
| 5578 | 5588 | depth = 1 |
| 5579 | | thisList = [i] |
| | 5589 | thisList = set([i]) |
| 5580 | 5590 | while 2*depth <= best and 3 < best: |
| 5581 | | nextList = [] |
| | 5591 | nextList = set() |
| 5582 | 5592 | for v in thisList: |
| 5583 | | for u in G.neighbors(v): |
| 5584 | | if not span[u]: |
| 5585 | | span[u] = 1 |
| 5586 | | nextList.append(u) |
| | 5593 | for u in self.neighbors(v): |
| | 5594 | if not u in span: |
| | 5595 | span.add(u) |
| | 5596 | nextList.add(u) |
| 5587 | 5597 | else: |
| 5588 | 5598 | if u in thisList: |
| 5589 | 5599 | best = depth*2-1 |