Skip to content

Commit

Permalink
Fix types of find_cycle and fix generation of Eulerian graph
Browse files Browse the repository at this point in the history
  • Loading branch information
jilljenn committed Sep 9, 2023
1 parent 6346457 commit 3b4d4bc
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 23 deletions.
20 changes: 9 additions & 11 deletions tests/test_tryalgo.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def isclose(a, b, rel_tol, abs_tol):
from tryalgo.ford_fulkerson import ford_fulkerson
from tryalgo.gale_shapley import gale_shapley
from tryalgo.gauss_jordan import gauss_jordan, GJ_ZERO_SOLUTIONS, GJ_SINGLE_SOLUTION, GJ_SEVERAL_SOLUTIONS
from tryalgo.graph import Graph_named_vertices
from tryalgo.graph import GraphNamedVertices
from tryalgo.graph01 import dist01
from tryalgo.horn_sat import horn_sat
from tryalgo.huffman import huffman
Expand Down Expand Up @@ -514,17 +514,16 @@ def test_find_cycle(self):
([[], []], None),
([[1], [0]], None),
([[], [2], [1]], None),
([[1, 2], [0, 2], [0, 1]], {0, 1, 2}),
([[1, 2], [0], [0], [2, 4], [3]], [2, 3]),
([[1, 2], [0, 2], [0, 1]], [1, 2, 0]),
([[1, 2], [0], [0, 3], [2, 4], [3]], None),
([[1, 2], [0], [0]], None),
([[1, 2], [0], [0], [4, 5], [3, 5], [3, 4]], [4, 5, 3])]
([[1, 2], [0], [0], [4, 5], [3, 5], [3, 4]], [4, 5, 3]),
([[1], [0, 2, 3], [1, 3], [1]], [3, 2, 1]),
([[1], [0, 2], [1, 3, 7], [2, 4, 5], [3], [3, 6, 7], [5], [2, 5]], [3, 5, 7, 2])]
for graph, result in L:
for g in [graph, listlist_and_matrix_to_listdict(graph)]:
answer = find_cycle(g)
if isinstance(result, set):
self.assertEqual(set(answer), result)
else:
self.assertEqual(answer, result)
self.assertEqual(answer, result)

def test_dijkstra(self):
_ = None
Expand Down Expand Up @@ -692,8 +691,7 @@ def test_eulerian_tour_directed(self):
[[1, 2], [0, 2, 3, 4], [0, 1], [1, 4],
[1, 3, 5, 6], [4, 6], [4, 5]],
[[1], [0]],
[[1, 2], [0, 2], [0, 1]]
]
[[1, 2], [0, 2], [0, 1]]]
directed_graphs = [
[[1, 2], [0, 3], [0, 3], [1, 2, 4], [3]],
[[1], [2], [3], [4, 5], [3, 6], [4], [0]]
Expand Down Expand Up @@ -803,7 +801,7 @@ def test_gauss_jordan(self):
x, [1, 1, 3]), GJ_ZERO_SOLUTIONS)

def test_graph(self):
G = Graph_named_vertices()
G = GraphNamedVertices()
G.add_node("A")
G.add_node("B")
G.add_node("C")
Expand Down
17 changes: 8 additions & 9 deletions tryalgo/dfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,26 +111,25 @@ def dfs_grid(grid, i, j, mark='X', free: str='.') -> None:


# pylint: disable=too-many-nested-blocks, no-else-return
def find_cycle(graph: Graph) -> Optional[List[Optional[int]]]:
def find_cycle(graph: Graph) -> Optional[List[int]]:
"""find a cycle in an undirected graph
:param graph: undirected graph in listlist or listdict format
:returns: list of vertices in a cycle or None
:complexity: `O(|V|+|E|)`
"""
n = len(graph)
prec: List[Optional[int]] = [None] * n # ancestor marks for visited vertices
for u in range(n):
if prec[u] is None: # unvisited vertex
S = [u] # start new DFS
prec[u] = u # mark root (not necessary for this algorithm)
prec: List[int] = [-1] * n # ancestor marks for visited vertices
for start in range(n):
if prec[start] == -1: # unvisited vertex
S: List[int] = [start] # start new DFS
while S:
u = S.pop()
for v in graph[u]: # for all neighbors
if v != prec[u]: # except arcs to father in DFS tree
if prec[v] is not None:
cycle = [v, u] # cycle found, (u,v) back edge
while u not in (prec[v], prec[u]): # directed
if prec[v] != -1:
cycle = [v, u] # cycle found, (u, v) back edge
while u != prec[v]: #not in [prec[v], prec[u]]: # directed
u = prec[u] # climb up the tree
cycle.append(u)
return cycle
Expand Down
8 changes: 7 additions & 1 deletion tryalgo/eulerian_tour.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,14 @@ def random_eulerien_graph(n):
"""
graphe = [[] for _ in range(n)]
for v in range(n - 1):
if len(graphe[v]) % 2 == 1:
nb_min_neighbors = 1
elif n - v == 2:
nb_min_neighbors = 0
else:
nb_min_neighbors = 2
noeuds = random.sample(range(v + 1, n), random.choice(
range(0 if len(graphe[v]) % 2 == 0 else 1, (n - v), 2)))
range(nb_min_neighbors, (n - v), 2)))
graphe[v].extend(noeuds)
for w in graphe[v]:
if w > v:
Expand Down
4 changes: 2 additions & 2 deletions tryalgo/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ def make_flow_labels(graph, flow, capac):

# pylint: disable=arguments-out-of-order
# snip{ class_graph
class Graph_named_vertices:
class GraphNamedVertices:
def __init__(self):
self.neighbors = []
self.name2node = {}
Expand Down Expand Up @@ -387,4 +387,4 @@ def add_arc(self, name_u, name_v, weight_uv=None):
self.weight[u][v] = weight_uv
# snip}

Graph = Union[List[List[int]], List[Dict[int, Any]], Graph_named_vertices]
Graph = Union[List[List[int]], List[Dict[int, Any]], GraphNamedVertices]

0 comments on commit 3b4d4bc

Please sign in to comment.