-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathsubgraphs.cpp
157 lines (127 loc) · 4.74 KB
/
subgraphs.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "AnalysisGraph.hpp"
#include "Node.hpp"
#include "utils.hpp"
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <range/v3/all.hpp>
using boost::for_each;
using delphi::utils::in;
using fmt::print;
using namespace std;
void AnalysisGraph::get_subgraph(int vert,
unordered_set<int>& vertices_to_keep,
int cutoff,
bool inward) {
// Mark the current vertex visited
(*this)[vert].visited = true;
vertices_to_keep.insert(vert);
if (cutoff != 0) {
cutoff--;
// Recursively process all the vertices adjacent to the current vertex
if (inward) {
for_each(this->predecessors(vert), [&](int v) {
if (!(*this)[v].visited) {
this->get_subgraph(v, vertices_to_keep, cutoff, inward);
}
});
}
else {
for_each(this->successors(vert), [&](int v) {
if (!(*this)[v].visited) {
this->get_subgraph(v, vertices_to_keep, cutoff, inward);
}
});
}
}
// Mark the current vertex unvisited
(*this)[vert].visited = false;
};
void AnalysisGraph::get_subgraph_between(int start,
int end,
vector<int>& path,
unordered_set<int>& vertices_to_keep,
int cutoff) {
// Mark the current vertex visited
(*this)[start].visited = true;
// Add this vertex to the path
path.push_back(start);
// If current vertex is the destination vertex, then
// we have found one path.
// Add this cell to the Tran_Mat_Object that is tracking
// this transition matrix cell.
if (start == end) {
vertices_to_keep.insert(path.begin(), path.end());
}
else if (cutoff != 0) {
cutoff--;
// Recursively process all the vertices adjacent to the current vertex
for_each(this->successors(start), [&](int v) {
if (!(*this)[v].visited) {
this->get_subgraph_between(v, end, path, vertices_to_keep, cutoff);
}
});
}
// Remove current vertex from the path and make it unvisited
path.pop_back();
(*this)[start].visited = false;
};
AnalysisGraph AnalysisGraph::get_subgraph_for_concept(string concept,
bool inward,
int depth) {
using ranges::to;
using namespace boost::adaptors;
// Mark all the vertices as not visited
for_each(this->nodes(), [](Node& node) { node.visited = false; });
int num_verts = this->num_vertices();
unordered_set<int> vertices_to_keep = unordered_set<int>();
this->get_subgraph(
this->get_vertex_id(concept), vertices_to_keep, depth, inward);
unordered_set<string> nodes_to_remove =
this->node_indices() |
filtered([&](int v) { return !in(vertices_to_keep, v); }) |
transformed([&](int v) { return (*this)[v].name; }) | to<unordered_set>();
if (vertices_to_keep.size() == 0) {
print("Subgraph has 0 nodes - returning an empty CAG!");
}
// Make a copy of current AnalysisGraph
// TODO: We have to make sure that we are making a deep copy.
// Test so far does not show suspicious behavior
AnalysisGraph G_sub = *this;
for_each(nodes_to_remove, [&](string n) { G_sub.remove_node(n); });
G_sub.clear_state();
return G_sub;
}
AnalysisGraph AnalysisGraph::get_subgraph_for_concept_pair(
string source_concept, string target_concept, int cutoff) {
int src_id = this->get_vertex_id(source_concept);
int tgt_id = this->get_vertex_id(target_concept);
unordered_set<int> vertices_to_keep;
unordered_set<string> vertices_to_remove;
vector<int> path;
// Mark all the vertices are not visited
for_each(this->node_indices(), [&](int v) { (*this)[v].visited = false; });
this->get_subgraph_between(src_id, tgt_id, path, vertices_to_keep, cutoff);
if (vertices_to_keep.size() == 0) {
print("AnalysisGraph::get_subgraph_for_concept_pair(): "
"There are no paths of length <= {0} from "
"source concept {1} --to-> target concept {2}. "
"Returning an empty CAG!",
cutoff,
source_concept,
target_concept);
}
// Determine the vertices to be removed
for (int vert_id : this->node_indices()) {
if (!in(vertices_to_keep, vert_id)) {
vertices_to_remove.insert((*this)[vert_id].name);
}
}
// Make a copy of current AnalysisGraph
// TODO: We have to make sure that we are making a deep copy.
// Test so far does not show suspicious behavior
AnalysisGraph G_sub = *this;
G_sub.remove_nodes(vertices_to_remove);
G_sub.clear_state();
return G_sub;
}