def test_topological_sort(): g = Graph(7, directed=True) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(0, 3) g.add_edge(0, 4) g.add_edge(1, 5) g.add_edge(2, 5) g.add_edge(3, 5) g.add_edge(5, 6) g.add_edge(4, 6) ''' 1 ↗ ↘ 0 → 2 → 5 → 6 ↓↘ ↗ ↑ ↓ 3 ↗ ↘ ↗ 4 → ↗ ''' s = g.topological_sort() l = [0, 4, 3, 2, 1, 5, 6] for i in xrange(7): assert s.pop() == l[i] ''' 0 1 ↘ ↙ | 2 | ↙ ↓ 3 4 ↘ ↙ 5 ↓ 6 ''' g = Graph(7, directed=True) g.add_edge(0, 2) g.add_edge(1, 2) g.add_edge(1, 4) g.add_edge(2, 3) g.add_edge(3, 5) g.add_edge(4, 5) g.add_edge(5, 6) assert str(g.topological_sort()) == "[7]: 1 4 0 2 3 5 6"
def test_dfs_directed(recursive=True): g = Graph(6, directed=True) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 2) g.add_edge(2, 0) g.add_edge(3, 3) g.add_edge(3, 4) g.add_edge(4, 4) g.add_edge(4, 2) g.add_edge(5, 5) ''' 0 -> 1 | | | v < - > 2 <- | | 3 -> 4 -> | 5 ''' def aggregate_list(v): if not hasattr(aggregate_list, "l"): setattr(aggregate_list, "l", []) aggregate_list.l.append(v) return aggregate_list.l if recursive: dfs_reachable = g.dfs_reachable dfs_all = g.dfs_all else: dfs_reachable = g.dfs_reachable_i dfs_all = g.dfs_all_i dfs_reachable(2, aggregate_list) assert (aggregate_list.l == [2, 0, 1]) aggregate_list.l = [] dfs_reachable(0, aggregate_list) assert (aggregate_list.l == [0, 1, 2]) aggregate_list.l = [] dfs_all(aggregate_list) assert (aggregate_list.l == [0, 1, 2, 3, 4, 5]) aggregate_list.l = [] dfs_reachable(4, aggregate_list) assert (aggregate_list.l == [4, 2, 0, 1]) aggregate_list.l = [] dfs_reachable(5, aggregate_list) assert (aggregate_list.l == [5])
def test_dfs_undirected(recursive=True): g = Graph(6) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 2) g.add_edge(2, 0) g.add_edge(3, 3) g.add_edge(3, 4) g.add_edge(4, 4) g.add_edge(4, 2) g.add_edge(5, 5) ''' 0 -- 1 \ | -- 2 -- | | 3 -- 4 -- | 5 ''' def aggregate_list(v): if not hasattr(aggregate_list, "l"): setattr(aggregate_list, "l", []) aggregate_list.l.append(v) return aggregate_list.l if recursive: dfs_reachable = g.dfs_reachable dfs_all = g.dfs_all else: dfs_reachable = g.dfs_reachable_i dfs_all = g.dfs_all_i dfs_reachable(2, aggregate_list) assert (aggregate_list.l == [2, 0, 1, 4, 3]) aggregate_list.l = [] dfs_reachable(0, aggregate_list) assert (aggregate_list.l == [0, 1, 2, 4, 3]) aggregate_list.l = [] dfs_all(aggregate_list) assert (aggregate_list.l == [0, 1, 2, 4, 3, 5]) aggregate_list.l = [] dfs_reachable(4, aggregate_list) assert (aggregate_list.l == [4, 2, 0, 1, 3]) aggregate_list.l = [] dfs_reachable(5, aggregate_list) assert (aggregate_list.l == [5])
def basic_testcases(): g = Graph(3) assert str(g) == str([[None] * 3] * 3) g.add_edge(1, 2) g.add_edge(1, 0) assert str(g) == "[[None, 1, None], [1, None, 1], [None, 1, None]]" # directed graph g = Graph(3, directed=True) g.add_edge(1, 2) g.add_edge(1, 2) # duplicate - won't be added to adjacency lists g.add_edge(1, 0) assert str(g) == "[[None, None, None], [1, None, 1], [None, None, None]]" # weighted undirected graph g = Graph(3) g.add_edge(1, 2, 5) g.add_edge(1, 2, 10) # duplicate - Update weight g.add_edge(1, 0, 11) assert str(g) == "[[None, 11, None], [11, None, 10], [None, 10, None]]" # weighted directed graph g = Graph(3, directed=True) g.add_edge(1, 2, 5) g.add_edge(1, 2, 10) # duplicate - Update weight g.add_edge(1, 0, 11) assert str(g) == "[[None, None, None], [11, None, 10], [None, None, None]]"
def test_paths_directed(): g = Graph(7, directed=True) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(0, 3) g.add_edge(0, 4) g.add_edge(1, 5) g.add_edge(2, 5) g.add_edge(3, 5) g.add_edge(5, 6) g.add_edge(4, 6) ''' 1 ↗ ↘ 0 → 2 → 5 → 6 ↓↘ ↗ ↑ ↓ 3 ↗ ↘ ↗ 4 → ↗ ''' def aggregate_list(path): if not hasattr(aggregate_list, "l"): setattr(aggregate_list, "l", []) aggregate_list.l.append(path) return aggregate_list.l g.paths(0, 6, aggregate_list) assert aggregate_list.l == [[0, 1, 5, 6], [0, 2, 5, 6], [0, 3, 5, 6], [0, 4, 6]] aggregate_list.l = [] g.paths(1, 6, aggregate_list) assert aggregate_list.l == [[1, 5, 6]] aggregate_list.l = [] g.paths(6, 1, aggregate_list) assert aggregate_list.l == [] # Try BFS-based all paths extraction aggregate_list.l = [] g.paths_2(0, 6, aggregate_list) assert aggregate_list.l == [[0, 4, 6], [0, 1, 5, 6], [0, 2, 5, 6], [0, 3, 5, 6]] aggregate_list.l = [] g.paths_2(1, 6, aggregate_list) assert aggregate_list.l == [[1, 5, 6]] aggregate_list.l = [] g.paths_2(6, 1, aggregate_list) assert aggregate_list.l == [] # All shortest paths by length aggregate_list.l = [] g.all_shortest_paths_by_length(0, 6, aggregate_list) assert aggregate_list.l == [[0, 4, 6]] aggregate_list.l = [] g.all_shortest_paths_by_length(0, 5, aggregate_list) assert aggregate_list.l == [[0, 1, 5], [0, 2, 5], [0, 3, 5]] # shortest path by length assert g.shortest_path_by_length(0, 6) == [0, 4, 6] assert g.shortest_path_by_length(0, 5) == [0, 1, 5] assert g.shortest_path_by_length(6, 1) == []
def test_paths_undirected(): g = Graph(7, directed=False) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(0, 3) g.add_edge(0, 4) g.add_edge(1, 5) g.add_edge(2, 5) g.add_edge(3, 5) g.add_edge(5, 6) g.add_edge(4, 6) ''' 1 ⤢ ⤡ 0 ⇿ 2 ⇿ 5 ⇿ 6 ↕⤡ ⤢ ⤢ ↕ 3 ⤢ ⤡ ⤢ 4 ⇿ ⤢ ''' def aggregate_list(path): if not hasattr(aggregate_list, "l"): setattr(aggregate_list, "l", []) aggregate_list.l.append(path) return aggregate_list.l g.paths(0, 6, aggregate_list) assert aggregate_list.l == [[0, 1, 5, 6], [0, 2, 5, 6], [0, 3, 5, 6], [0, 4, 6]] aggregate_list.l = [] g.paths(1, 6, aggregate_list) assert aggregate_list.l == [[1, 0, 2, 5, 6], [1, 0, 3, 5, 6], [1, 0, 4, 6], [1, 5, 2, 0, 4, 6], [1, 5, 3, 0, 4, 6], [1, 5, 6]] aggregate_list.l = [] g.paths(1, 1, aggregate_list) assert aggregate_list.l == [[1]] # Try BFS-based all paths extraction aggregate_list.l = [] g.paths_2(0, 6, aggregate_list) assert aggregate_list.l == [[0, 4, 6], [0, 1, 5, 6], [0, 2, 5, 6], [0, 3, 5, 6]] aggregate_list.l = [] g.paths_2(1, 6, aggregate_list) assert aggregate_list.l == sorted( [[1, 0, 2, 5, 6], [1, 0, 3, 5, 6], [1, 0, 4, 6], [1, 5, 2, 0, 4, 6], [1, 5, 3, 0, 4, 6], [1, 5, 6]], cmp=lambda l1, l2: cmp(len(l1), len(l2))) aggregate_list.l = [] g.paths_2(1, 1, aggregate_list) assert aggregate_list.l == [[1]] # All shortest paths by length aggregate_list.l = [] g.all_shortest_paths_by_length(0, 6, aggregate_list) assert aggregate_list.l == [[0, 4, 6]] aggregate_list.l = [] g.all_shortest_paths_by_length(1, 6, aggregate_list) assert aggregate_list.l == [[1, 5, 6]] aggregate_list.l = [] g.all_shortest_paths_by_length(0, 5, aggregate_list) assert aggregate_list.l == [[0, 1, 5], [0, 2, 5], [0, 3, 5]] # shortest path by length assert g.shortest_path_by_length(0, 6) == [0, 4, 6] assert g.shortest_path_by_length(1, 6) == [1, 5, 6] assert g.shortest_path_by_length(0, 5) == [0, 1, 5]
def test_dfs_directed(): g = Graph(6, directed=True) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 2) g.add_edge(2, 0) g.add_edge(3, 3) g.add_edge(3, 4) g.add_edge(4, 4) g.add_edge(4, 2) g.add_edge(5, 5) ''' 0 -> 1 | | | v < - > 2 <- | | 3 -> 4 -> | 5 ''' def aggregate_list(v): if not hasattr(aggregate_list, "l"): setattr(aggregate_list, "l", []) aggregate_list.l.append(v) return aggregate_list.l g.dfs_reachable(2, aggregate_list) assert(aggregate_list.l == [2,0,1]) aggregate_list.l = [] g.dfs_reachable(0, aggregate_list) assert(aggregate_list.l == [0,1,2]) aggregate_list.l = [] g.dfs_all(aggregate_list) assert(aggregate_list.l == [0,1,2,3,4,5]) aggregate_list.l = [] g.dfs_reachable(4, aggregate_list) assert(aggregate_list.l == [4,2,0,1]) aggregate_list.l = [] g.dfs_reachable(5, aggregate_list) assert(aggregate_list.l == [5])
def test_dfs_undirected(): g = Graph(6) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 2) g.add_edge(2, 0) g.add_edge(3, 3) g.add_edge(3, 4) g.add_edge(4, 4) g.add_edge(4, 2) g.add_edge(5, 5) ''' 0 -- 1 \ | -- 2 -- | | 3 -- 4 -- | 5 ''' def aggregate_list(v): if not hasattr(aggregate_list, "l"): setattr(aggregate_list, "l", []) aggregate_list.l.append(v) return aggregate_list.l g.dfs_reachable(2, aggregate_list) assert(aggregate_list.l == [2,0,1,4,3]) aggregate_list.l = [] g.dfs_reachable(0, aggregate_list) assert(aggregate_list.l == [0,1,2,4,3]) aggregate_list.l = [] g.dfs_all(aggregate_list) assert(aggregate_list.l == [0,1,2,4,3,5]) aggregate_list.l = [] g.dfs_reachable(4, aggregate_list) assert(aggregate_list.l == [4,2,0,1,3]) aggregate_list.l = [] g.dfs_reachable(5, aggregate_list) assert(aggregate_list.l == [5])
def basic_testcases(): g = Graph(3) assert str(g) == str([[None]*3]*3) g.add_edge(1,2) g.add_edge(1,0) assert str(g) == "[[None, 1, None], [1, None, 1], [None, 1, None]]" # directed graph g = Graph(3, directed=True) g.add_edge(1,2) g.add_edge(1,2) # duplicate - won't be added to adjacency lists g.add_edge(1,0) assert str(g) == "[[None, None, None], [1, None, 1], [None, None, None]]" # weighted undirected graph g = Graph(3) g.add_edge(1,2, 5) g.add_edge(1,2, 10) # duplicate - Update weight g.add_edge(1,0, 11) assert str(g) == "[[None, 11, None], [11, None, 10], [None, 10, None]]" # weighted directed graph g = Graph(3, directed=True) g.add_edge(1,2, 5) g.add_edge(1,2, 10) # duplicate - Update weight g.add_edge(1,0, 11) assert str(g) == "[[None, None, None], [11, None, 10], [None, None, None]]"
def test_bfs_directed(recursive=False): g = Graph(6, directed=True) g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 2) g.add_edge(2, 0) g.add_edge(3, 3) g.add_edge(3, 4) g.add_edge(4, 4) g.add_edge(4, 2) g.add_edge(5, 5) ''' 0 -> 1 | | | v < - > 2 <- | | 3 -> 4 -> | 5 ''' def aggregate_list(v): if not hasattr(aggregate_list, "l"): setattr(aggregate_list, "l", []) aggregate_list.l.append(v) return aggregate_list.l if recursive: bfs_fn = g.bfs_reachable_r bfs_all = g.bfs_all_r else: bfs_fn = g.bfs_reachable bfs_all = g.bfs_all bfs_fn(2, aggregate_list) assert(aggregate_list.l == [2,0,1]) aggregate_list.l = [] bfs_fn(0, aggregate_list) assert(aggregate_list.l == [0,1,2]) aggregate_list.l = [] bfs_fn(4, aggregate_list) assert(aggregate_list.l == [4,2,0,1]) aggregate_list.l = [] bfs_fn(5, aggregate_list) assert(aggregate_list.l == [5]) aggregate_list.l = [] bfs_all(aggregate_list) assert(aggregate_list.l == [0,1,2,3,4,5])
def basic_testcases(): g = Graph(3) assert g.get_adjmatrix() == \ [ [None, None, None], [None, None, None], [None, None, None] ] attribute_error_raised = False try: g.get_adjlists() except AttributeError: attribute_error_raised = True # Graph uses adjacency matrix for underlying storage # and won't have an adjacency list assert (attribute_error_raised == True) # undirected graph g.add_edge(1, 2) g.add_edge(1, 2) # duplicate - won't be added to adjacency lists g.add_edge(1, 0) assert g.get_adjmatrix() == \ [ [None, 1, None], [1, None, 1], [None, 1, None] ] assert [v for v, _ in g.get_neighbors(0)] == [1] assert [v for v, _ in g.get_neighbors(1)] == [0, 2] assert [v for v, _ in g.get_neighbors(2)] == [1] # directed graph g = Graph(3, directed=True) g.add_edge(1, 2) g.add_edge(1, 2) # duplicate - won't be added to adjacency lists g.add_edge(1, 0) assert g.get_adjmatrix() == \ [ [None, None, None], [1, None, 1], [None, None, None] ] assert [v for v, _ in g.get_neighbors(0)] == [] assert [v for v, _ in g.get_neighbors(1)] == [0, 2] assert [v for v, _ in g.get_neighbors(2)] == [] # weighted undirected graph g = Graph(3) g.add_edge(1, 2, 5) g.add_edge(1, 2, 10) # duplicate - update weight g.add_edge(1, 0, 11) assert g.get_adjmatrix() == \ [ [None, 11, None], [11, None, 10], [None, 10, None] ] assert [x for x in g.get_neighbors(0)] == [(1, 11)] assert [x for x in g.get_neighbors(1)] == [(0, 11), (2, 10)] assert [x for x in g.get_neighbors(2)] == [(1, 10)] # weighted directed graph g = Graph(3, directed=True) g.add_edge(1, 2, 5) g.add_edge(1, 2, 10) # duplicate - Update weight g.add_edge(1, 0, 11) assert g.get_adjmatrix() == \ [ [None, None, None], [11, None, 10], [None, None, None] ] assert [x for x in g.get_neighbors(0)] == [] assert [x for x in g.get_neighbors(1)] == [(0, 11), (2, 10)] assert [x for x in g.get_neighbors(2)] == []