Skip to content

Commit d6c7256

Browse files
committed
Corrected find_max_2_3_subgraph
1 parent c4bd412 commit d6c7256

1 file changed

Lines changed: 122 additions & 30 deletions

File tree

bar_yehuda_fvs.py

Lines changed: 122 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,135 @@
22
from collections import deque
33

44

5-
def dfs_construct(G, H, v, visited, edges_visited):
6-
visited.add(v)
7-
for u in G.neighbors(v):
8-
edge = (min(v, u), max(v, u))
9-
if edge in edges_visited:
5+
def find_maximal_2_3_subgraph(og_G):
6+
G = og_G.copy()
7+
H = nx.Graph()
8+
H.add_nodes_from(G.nodes())
9+
nodes_to_visit = list(G.nodes())
10+
11+
# Chemin actuel
12+
stack = []
13+
in_stack = set()
14+
15+
# stack[0] est connecté à un noeud de H de degré 2?
16+
start_connected = False
17+
18+
while True:
19+
if len(stack) == 0:
20+
start_node = None
21+
while len(nodes_to_visit) > 0:
22+
n = nodes_to_visit.pop(0)
23+
if G.degree(n) > 0:
24+
start_node = n
25+
break
26+
27+
if start_node is None:
28+
# Plus de noeuds à visiter
29+
break
30+
31+
stack = [start_node]
32+
in_stack = {start_node}
33+
if H.degree(start_node) == 2:
34+
start_connected = True
35+
else:
36+
start_connected = False
37+
38+
# Extrémité du chemin actuel
39+
u = stack[-1]
40+
parent = stack[-2] if len(stack) > 1 else None
41+
nb = list(G.neighbors(u))
42+
43+
# Si pas de voisins du tout ou seul voisin est le parent -> cul de sac
44+
if len(nb) == 0 or (len(nb) == 1 and nb[0] == parent):
45+
if parent is not None:
46+
if G.has_edge(parent, u):
47+
G.remove_edge(parent, u)
48+
in_stack.remove(stack.pop())
49+
50+
# Reset si la stack est vide
51+
if len(stack) == 0:
52+
start_connected = False
1053
continue
1154

12-
edges_visited.add(edge)
13-
deg_u = H.degree[u] if u in H else 0
14-
deg_v = H.degree[v] if v in H else 0
55+
v = None
56+
for neighbor in nb:
57+
if neighbor != parent:
58+
v = neighbor
59+
break
1560

16-
if deg_u < 3 and deg_v < 3:
17-
H.add_edge(u, v)
18-
if u not in visited:
19-
dfs_construct(G, H, u, visited, edges_visited)
61+
if H.degree(v) == 3:
62+
G.remove_edge(u, v)
63+
continue
2064

65+
# Si v est dans la stack, alors on a un cycle
66+
elif v in in_stack:
67+
idx = stack.index(v)
68+
cycle_nodes = stack[idx:]
69+
edges_to_add = []
70+
for i in range(len(cycle_nodes) - 1):
71+
edges_to_add.append((cycle_nodes[i], cycle_nodes[i + 1]))
72+
edges_to_add.append((u, v))
73+
H.add_edges_from(edges_to_add)
74+
G.remove_edges_from(edges_to_add)
75+
76+
# Si idx == 0, cycle formé par tous les sommets de la stack
77+
if idx == 0:
78+
stack = []
79+
in_stack = set()
80+
start_connected = False
81+
82+
else:
83+
stack = stack[: idx + 1]
84+
in_stack = set(stack)
85+
# Le bout de la pile (v) est connecté à H
86+
# Si le début est connecté, alors c'est un chemin valide à ajouter
87+
if start_connected:
88+
path_edges = []
89+
for i in range(len(stack) - 1):
90+
path_edges.append((stack[i], stack[i + 1]))
91+
H.add_edges_from(path_edges)
92+
G.remove_edges_from(path_edges)
93+
stack = []
94+
in_stack = set()
95+
start_connected = False
96+
97+
else:
98+
# La pile est inversée pour essayer d'attacher le début du chemin à H ou un autre cycle
99+
stack.reverse()
100+
# v était à la fin de la stack, maintenant au début donc le début est connecté à H
101+
start_connected = True
21102

22-
def find_maximal_2_3_subgraph(G):
23-
H = nx.Graph()
24-
visited = set()
25-
edges_visited = set()
26-
for node in G.nodes:
27-
if node not in visited:
28-
dfs_construct(G, H, node, visited, edges_visited)
29-
30-
to_remove = {n for n in H.nodes if H.degree(n) < 2}
31-
while len(to_remove) > 0:
32-
v = to_remove.pop()
33-
if v not in H:
34103
continue
35104

36-
nb = set(H.neighbors(v))
37-
H.remove_node(v)
38-
for u in nb:
39-
if u in H and H.degree[u] < 2:
40-
to_remove.add(u)
105+
elif H.degree(v) == 2:
106+
# v est déjà dans H et à un degré 2 donc la connexion du chemin dans stack est possible à v
107+
# Si le début est connecté, alors c'est un chemin valide à ajouter
108+
if start_connected:
109+
path_edges = []
110+
for i in range(len(stack) - 1):
111+
path_edges.append((stack[i], stack[i + 1]))
112+
path_edges.append((u, v))
113+
H.add_edges_from(path_edges)
114+
G.remove_edges_from(path_edges)
115+
stack = []
116+
in_stack = set()
117+
start_connected = False
118+
119+
else:
120+
stack.append(v)
121+
in_stack.add(v)
122+
stack.reverse()
123+
start_connected = True
124+
continue
125+
126+
# v est degré 0 ou 1 dans H, on peut l'ajouter au chemin
127+
else:
128+
stack.append(v)
129+
in_stack.add(v)
130+
continue
41131

132+
to_remove = [n for n in H.nodes() if H.degree(n) == 0]
133+
H.remove_nodes_from(to_remove)
42134
return H
43135

44136

@@ -104,5 +196,5 @@ def subG_2_3(G):
104196
return X | Y | W
105197

106198

107-
def get_decycling_number_bar_yehuda(G):
199+
def approx_decycling_number_bar_yehuda(G):
108200
return len(subG_2_3(G))

0 commit comments

Comments
 (0)