-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGraph.h
197 lines (183 loc) · 4.68 KB
/
Graph.h
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#pragma once
#include <vector>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <stack>
#include <iterator>
#include "DatalogProgram.h"
#include "header.h"
using namespace std;
class graphNode {
public:
int number;
set<int> dependents;
bool visited;
bool reversed;
RuleItem thisRule;
graphNode(RuleItem rule, int num, set<int> depend, DatalogProgram* program) {
number = num;
for (unsigned int i = 0; i < rule.predicates.size(); i++) {
dependents = depend;
thisRule = rule;
visited = false;
reversed = false;
}
}
};
class Graph {
public:
set<int> tempIndex;
int numRules;
int currNodeNum;
vector<set<int>> depList;
vector<RuleItem> rulesToProcess;
map<int, graphNode> graph;
vector<set<int>> SCC;
vector<set<int>> reverse;
vector<QueryItem> queriesToGraph;
vector<int> postOrder;
bool predicateInRule(vector<RuleItem> rules, QueryItem pred) {
tempIndex.clear();
for (unsigned int i = 0; i < rules.size(); i++) {
if (pred.table == rules.at(i).headPredicate.table) {
tempIndex.insert(i);
}
}
return (tempIndex.size() != 0);
}
set<int> getDependents(vector<RuleItem> rules, int i) {
set<int> toReturn;
RuleItem current = rules.at(i);
for (unsigned int j = 0; j < current.predicates.size(); j++) {
QueryItem predToFind = current.predicates.at(j);
if (predicateInRule(rules, predToFind)) {
for (int dependent : tempIndex) {
toReturn.insert(dependent);
}
}
}
return toReturn;
}
void printDependencies() {
cout << "Dependency Graph" << endl;
for (int i = 0; i < numRules; i++) {
set<int> currentSet;
depList.push_back(currentSet);
cout << "R" << to_string(i) << ":";
int count = 0;
for (int child : graph.at(i).dependents) {
if (count) {
cout << ",";
}
cout << "R" << to_string(child);
depList.at(i).insert(child);
count++;
}
cout << endl;
}
}
void reverseDependencies(DatalogProgram* program) {
// create empty sets
for (unsigned int i = 0; i < depList.size(); i++) {
set<int> emptySet;
reverse.push_back(emptySet);
}
// add reverse dependencies
for (unsigned int i = 0; i < depList.size(); i++) {
// for each dependent
for (int child : depList.at(i)) {
// add to the revere set (indexed at the child) the parent
reverse.at(child).insert(i);
}
}
}
Graph(DatalogProgram* program) {
rulesToProcess = program->rules->getRules();
numRules = rulesToProcess.size();
// create graph
for (unsigned int i = 0; i < rulesToProcess.size(); i++) {
set<int> depend = getDependents(rulesToProcess, i);
graphNode node(rulesToProcess.at(i), i, depend, program);
graph.insert(pair<int, graphNode>(i, node));
}
// print the output of the dependency graph
printDependencies();
}
void getReversePostOrder() {
map<int, bool> visitedPost;
bool pushed = false;
stack<int> DFS;
for (unsigned int i = 0; i < reverse.size(); i++) {
// if not visited
if (visitedPost.find(i) == visitedPost.end()) {
visitedPost[i] = true;
DFS.push(i);
while (!DFS.empty()) {
for (int child : reverse.at(DFS.top())) {
// hasn't been visited so add it
if (visitedPost.find(child) == visitedPost.end()) {
pushed = true;
DFS.push(child);
visitedPost[child] = true;
}
}
// check if anything was added
if (!pushed) {
// it is next on the post order
postOrder.push_back(DFS.top());
DFS.pop();
}
else {
// reset counter
pushed = false;
}
}
}
}
}
void getSCC() {
/*
The first SCC is found by running a depth-first search on the original dependency graph
starting from the node with the largest post-order number.
Any node visited during the DFS is part of the SCC.*/
map<int, bool> visitedSCC;
bool pushed = false;
stack<int> DFS;
int SSCCount = -1;
for (int i = (int)postOrder.size() - 1; i >= 0; i--) {
// if not visited
if (visitedSCC.find(postOrder.at(i)) == visitedSCC.end()) {
// new SCC, push back a new set
SSCCount++;
set<int> currentSet;
SCC.push_back(currentSet);
// mark the node as visited and push it
visitedSCC[postOrder.at(i)] = true;
DFS.push(postOrder.at(i));
// begin the depth search
while (!DFS.empty()) {
for (int child : depList.at(DFS.top())) {
// hasn't been visited so add it
if (visitedSCC.find(child) == visitedSCC.end()) {
pushed = true;
DFS.push(child);
visitedSCC[child] = true;
}
}
// check if anything was added
if (!pushed) {
// it is next on the post order
SCC.at(SSCCount).insert(DFS.top());
DFS.pop();
}
else {
// reset counter
pushed = false;
}
}
}
}
}
};