From e5ee9c64184c61ae697a866e204e7e3fee8d3551 Mon Sep 17 00:00:00 2001 From: chester-tan Date: Sun, 20 Mar 2022 15:07:59 +0100 Subject: [PATCH 1/4] add test for diamonds in generate_causal_tree() --- tests/test_DAG.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/test_DAG.py b/tests/test_DAG.py index 8ae10e9..10d71d7 100644 --- a/tests/test_DAG.py +++ b/tests/test_DAG.py @@ -240,6 +240,42 @@ def test_dag_from_temporal_network(): assert sorted(dag.routes_to_node('a_5')) == sorted([['c_2', 'a_5'], ['a_1', 'b_4', 'a_5']]) +def test_generate_causal_tree(): + """ + + (b,d,3)-(d,a,5) + / \ + (a,b,1) (a,e,6) + \ / + (b,c,2)-(c,a,4) + ---------------------------------> t + + (d,2) + / \ + (a,0)-(b,1) (a,3)-(e,4) + \ / + (c,2) + -------------------------------> depth + + """ + + tn = pp.TemporalNetwork() + tn.add_edge('a', 'b', 1) + tn.add_edge('b', 'c', 2) + tn.add_edge('b', 'd', 3) + tn.add_edge('c', 'a', 4) + tn.add_edge('d', 'a', 5) + tn.add_edge('a', 'e', 6) + + delta = 10 + + dag, node_map = pp.DAG.from_temporal_network(tn, delta) + root = list(dag.roots)[0] + + causal_tree, causal_mapping = pp.path_extraction.generate_causal_tree(dag, root, node_map) + assert set(causal_tree.edges.keys()) == set([('a_0', 'b_1'), ('b_1', 'd_2'), ('b_1', 'c_2'), ('d_2', 'a_3'), ('c_2', 'a_3'), ('a_3', 'e_4')]) + + @pytest.mark.networkx def test_strong_connected_components(random_network): from pathpy.classes.network import network_to_networkx From 1b3f84552a6dba70ed503b8e26ed0dc3ee29f0f5 Mon Sep 17 00:00:00 2001 From: chester-tan Date: Sun, 20 Mar 2022 15:22:33 +0100 Subject: [PATCH 2/4] fix for diamonds in generate_causal_tree() --- pathpy/path_extraction/temporal_paths.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pathpy/path_extraction/temporal_paths.py b/pathpy/path_extraction/temporal_paths.py index 7a13cd8..c8823fa 100644 --- a/pathpy/path_extraction/temporal_paths.py +++ b/pathpy/path_extraction/temporal_paths.py @@ -258,19 +258,20 @@ def generate_causal_tree(dag, root, node_map): x = '{0}_{1}'.format(node_map[v], depth) causal_mapping[x] = node_map[v] + if not visited[node_map[v], depth]: + visited[node_map[v], depth] = True + # process nodes at next level - for w in dag.successors[v]: - if (w, depth+1) not in queue: + for w in dag.successors[v]: + # add edge to causal tree + y = '{0}_{1}'.format(node_map[w], depth+1) + if (x, y) not in edges: + edges.append((x, y)) + causal_mapping[y] = node_map[w] + # only consider nodes that have not already + # been added to this level + if (w, depth+1) not in queue and not visited[node_map[w], depth+1]: queue.append((w, depth+1)) - # only consider nodes that have not already - # been added to this level - if not visited[node_map[w], depth+1]: - # add edge to causal tree - y = '{0}_{1}'.format(node_map[w], depth+1) - edges.append((x, y)) - - visited[node_map[w], depth+1] = True - causal_mapping[y] = node_map[w] # Adding all edges at once is more efficient! causal_tree.add_edges(edges) From 4cbc55e6f8c075a9f6b98d61dc9a3b73f0913d54 Mon Sep 17 00:00:00 2001 From: chester-tan Date: Tue, 22 Mar 2022 23:29:38 +0100 Subject: [PATCH 3/4] add test for trapeziums --- tests/test_DAG.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tests/test_DAG.py b/tests/test_DAG.py index 10d71d7..175261f 100644 --- a/tests/test_DAG.py +++ b/tests/test_DAG.py @@ -240,7 +240,7 @@ def test_dag_from_temporal_network(): assert sorted(dag.routes_to_node('a_5')) == sorted([['c_2', 'a_5'], ['a_1', 'b_4', 'a_5']]) -def test_generate_causal_tree(): +def test_generate_causal_tree_diamond(): """ (b,d,3)-(d,a,5) @@ -248,6 +248,7 @@ def test_generate_causal_tree(): (a,b,1) (a,e,6) \ / (b,c,2)-(c,a,4) + ---------------------------------> t (d,2) @@ -255,6 +256,7 @@ def test_generate_causal_tree(): (a,0)-(b,1) (a,3)-(e,4) \ / (c,2) + -------------------------------> depth """ @@ -276,6 +278,39 @@ def test_generate_causal_tree(): assert set(causal_tree.edges.keys()) == set([('a_0', 'b_1'), ('b_1', 'd_2'), ('b_1', 'c_2'), ('d_2', 'a_3'), ('c_2', 'a_3'), ('a_3', 'e_4')]) +def test_generate_causal_tree_trapezium(): + """ + + (b,c,2)-(c,b,3) + / \ + (a,b,1)-----------------(b,c,4)-(c,d,5) + + ---------------------------------> t + + (b,3)-(c,4)-(d,5) + / + (a,0)-(b,1)-(c,2)-(d,3) + + -------------------------------> depth + + """ + + tn = pp.TemporalNetwork() + tn.add_edge('a', 'b', 1) + tn.add_edge('b', 'c', 2) + tn.add_edge('c', 'b', 3) + tn.add_edge('b', 'c', 4) + tn.add_edge('c', 'd', 5) + + delta = 10 + + dag, node_map = pp.DAG.from_temporal_network(tn, delta) + root = list(dag.roots)[0] + + causal_tree, causal_mapping = pp.path_extraction.generate_causal_tree(dag, root, node_map) + assert set(causal_tree.edges.keys()) == set([('a_0', 'b_1'), ('b_1', 'c_2'), ('c_2', 'd_3'), ('c_2', 'b_3'), ('b_3', 'c_4'), ('c_4', 'd_5')]) + + @pytest.mark.networkx def test_strong_connected_components(random_network): from pathpy.classes.network import network_to_networkx From e460cc45bc452c54efff7f5ee75e55e22fae70f1 Mon Sep 17 00:00:00 2001 From: chester-tan Date: Tue, 22 Mar 2022 23:32:00 +0100 Subject: [PATCH 4/4] a better fix --- pathpy/path_extraction/temporal_paths.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/pathpy/path_extraction/temporal_paths.py b/pathpy/path_extraction/temporal_paths.py index c8823fa..ebf6c36 100644 --- a/pathpy/path_extraction/temporal_paths.py +++ b/pathpy/path_extraction/temporal_paths.py @@ -258,20 +258,17 @@ def generate_causal_tree(dag, root, node_map): x = '{0}_{1}'.format(node_map[v], depth) causal_mapping[x] = node_map[v] - if not visited[node_map[v], depth]: - visited[node_map[v], depth] = True - # process nodes at next level - for w in dag.successors[v]: - # add edge to causal tree + for w in dag.successors[v]: + if (w, depth+1) not in queue: + queue.append((w, depth+1)) + # only consider nodes that have not already + # been added to this level y = '{0}_{1}'.format(node_map[w], depth+1) - if (x, y) not in edges: + if not visited[x, y]: + # add edge to causal tree edges.append((x, y)) - causal_mapping[y] = node_map[w] - # only consider nodes that have not already - # been added to this level - if (w, depth+1) not in queue and not visited[node_map[w], depth+1]: - queue.append((w, depth+1)) + visited[x, y] = True # Adding all edges at once is more efficient! causal_tree.add_edges(edges)