souffle  2.0.2-371-g6315b36
SCCGraph.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file SCCGraph.cpp
12  *
13  * Implements method of precedence graph to build the precedence graph,
14  * compute strongly connected components of the precedence graph, and
15  * build the strongly connected component graph.
16  *
17  ***********************************************************************/
18 
19 #include "ast/analysis/SCCGraph.h"
20 #include "Global.h"
21 #include "GraphUtils.h"
22 #include "ast/Program.h"
23 #include "ast/QualifiedName.h"
24 #include "ast/Relation.h"
25 #include "ast/TranslationUnit.h"
26 #include "ast/analysis/IOType.h"
28 #include <algorithm>
29 #include <cassert>
30 #include <memory>
31 #include <set>
32 #include <string>
33 
34 namespace souffle::ast::analysis {
35 
36 void SCCGraphAnalysis::run(const TranslationUnit& translationUnit) {
37  precedenceGraph = translationUnit.getAnalysis<PrecedenceGraphAnalysis>();
38  ioType = translationUnit.getAnalysis<IOTypeAnalysis>();
39  sccToRelation.clear();
40  relationToScc.clear();
41  predecessors.clear();
42  successors.clear();
43 
44  /* Compute SCC */
45  Program& program = translationUnit.getProgram();
46  std::vector<Relation*> relations = program.getRelations();
47  size_t counter = 0;
48  size_t numSCCs = 0;
49  std::stack<const Relation*> S;
50  std::stack<const Relation*> P;
51  std::map<const Relation*, size_t> preOrder; // Pre-order number of a node (for Gabow's Algo)
52  for (const Relation* relation : relations) {
53  relationToScc[relation] = preOrder[relation] = (size_t)-1;
54  }
55  for (const Relation* relation : relations) {
56  if (preOrder[relation] == (size_t)-1) {
57  scR(relation, preOrder, counter, S, P, numSCCs);
58  }
59  }
60 
61  /* Build SCC graph */
62  successors.resize(numSCCs);
63  predecessors.resize(numSCCs);
64  for (const Relation* u : relations) {
65  for (const Relation* v : precedenceGraph->graph().predecessors(u)) {
66  auto scc_u = relationToScc[u];
67  auto scc_v = relationToScc[v];
68  assert(scc_u < numSCCs && "Wrong range");
69  assert(scc_v < numSCCs && "Wrong range");
70  if (scc_u != scc_v) {
71  predecessors[scc_u].insert(scc_v);
72  successors[scc_v].insert(scc_u);
73  }
74  }
75  }
76 
77  /* Store the relations for each SCC */
78  sccToRelation.resize(numSCCs);
79  for (const Relation* relation : relations) {
81  }
82 }
83 
84 /* Compute strongly connected components using Gabow's algorithm (cf. Algorithms in
85  * Java by Robert Sedgewick / Part 5 / Graph * algorithms). The algorithm has linear
86  * runtime. */
87 void SCCGraphAnalysis::scR(const Relation* w, std::map<const Relation*, size_t>& preOrder, size_t& counter,
88  std::stack<const Relation*>& S, std::stack<const Relation*>& P, size_t& numSCCs) {
89  preOrder[w] = counter++;
90  S.push(w);
91  P.push(w);
92  for (const Relation* t : precedenceGraph->graph().predecessors(w)) {
93  if (preOrder[t] == (size_t)-1) {
94  scR(t, preOrder, counter, S, P, numSCCs);
95  } else if (relationToScc[t] == (size_t)-1) {
96  while (preOrder[P.top()] > preOrder[t]) {
97  P.pop();
98  }
99  }
100  }
101  if (P.top() == w) {
102  P.pop();
103  } else {
104  return;
105  }
106 
107  const Relation* v;
108  do {
109  v = S.top();
110  S.pop();
111  relationToScc[v] = numSCCs;
112  } while (v != w);
113  numSCCs++;
114 }
115 
116 void SCCGraphAnalysis::print(std::ostream& os) const {
117  const std::string& name = Global::config().get("name");
118  std::stringstream ss;
119  /* Print SCC graph */
120  ss << "digraph {" << std::endl;
121  /* Print nodes of SCC graph */
122  for (size_t scc = 0; scc < getNumberOfSCCs(); scc++) {
123  ss << "\t" << name << "_" << scc << "[label = \"";
124  ss << join(getInternalRelations(scc), ",\\n",
125  [](std::ostream& out, const Relation* rel) { out << rel->getQualifiedName(); });
126  ss << "\" ];" << std::endl;
127  }
128  for (size_t scc = 0; scc < getNumberOfSCCs(); scc++) {
129  for (auto succ : getSuccessorSCCs(scc)) {
130  ss << "\t" << name << "_" << scc << " -> " << name << "_" << succ << ";" << std::endl;
131  }
132  }
133  ss << "}";
134  printHTMLGraph(os, ss.str(), getName());
135 }
136 
137 } // namespace souffle::ast::analysis
TranslationUnit.h
IOType.h
S
#define S(x)
Definition: test.h:179
souffle::ast::analysis::SCCGraphAnalysis::run
void run(const TranslationUnit &translationUnit) override
run analysis for a Ast translation unit
Definition: SCCGraph.cpp:44
relation
Relation & relation
Definition: Reader.h:130
souffle::ast::analysis::SCCGraphAnalysis::print
void print(std::ostream &os) const override
Print the SCC graph.
Definition: SCCGraph.cpp:124
souffle::ast::Relation
Defines a relation with a name, attributes, qualifiers, and internal representation.
Definition: Relation.h:49
souffle::ast::analysis::PrecedenceGraphAnalysis::graph
const Graph< const Relation *, NameComparison > & graph() const
Definition: PrecedenceGraph.h:54
souffle::ast::analysis::SCCGraphAnalysis::scR
void scR(const Relation *relation, std::map< const Relation *, size_t > &preOrder, size_t &counter, std::stack< const Relation * > &S, std::stack< const Relation * > &P, size_t &numSCCs)
Recursive scR method for computing SCC.
Definition: SCCGraph.cpp:95
relations
std::vector< Own< Relation > > relations
Definition: ComponentInstantiation.cpp:65
Relation.h
souffle::ast::analysis::SCCGraphAnalysis::predecessors
std::vector< std::set< size_t > > predecessors
Predecessor set for the SCC graph.
Definition: SCCGraph.h:225
souffle::ast::analysis::SCCGraphAnalysis::precedenceGraph
PrecedenceGraphAnalysis * precedenceGraph
Definition: SCCGraph.h:216
souffle::printHTMLGraph
void printHTMLGraph(std::ostream &out, const std::string &dotSpec, const std::string &id)
Definition: GraphUtils.h:226
SCCGraph.h
souffle::ast::analysis::Analysis::getName
virtual const std::string & getName() const
get name of the analysis
Definition: Analysis.h:50
Global.h
souffle::ast::analysis::SCCGraphAnalysis::successors
std::vector< std::set< size_t > > successors
Adjacency lists for the SCC graph.
Definition: SCCGraph.h:222
souffle::ast::Program
The program class consists of relations, clauses and types.
Definition: Program.h:52
souffle::Relation
Object-oriented wrapper class for Souffle's templatized relations.
Definition: SouffleInterface.h:49
souffle::join
detail::joined_sequence< Iter, Printer > join(const Iter &a, const Iter &b, const std::string &sep, const Printer &p)
Creates an object to be forwarded to some output stream for printing sequences of elements interspers...
Definition: StreamUtil.h:175
souffle::ast::analysis::SCCGraphAnalysis::name
static constexpr const char * name
Definition: SCCGraph.h:52
souffle::ast::analysis::SCCGraphAnalysis::sccToRelation
std::vector< std::set< const Relation * > > sccToRelation
Relations contained in a SCC.
Definition: SCCGraph.h:228
GraphUtils.h
souffle::ast::analysis::SCCGraphAnalysis::getNumberOfSCCs
size_t getNumberOfSCCs() const
Get the number of SCCs in the graph.
Definition: SCCGraph.h:59
souffle::ast::Program::getRelations
std::vector< Relation * > getRelations() const
Return relations.
Definition: Program.h:60
souffle::Global::config
static MainConfig & config()
Definition: Global.h:141
QualifiedName.h
Program.h
StreamUtil.h
souffle::ast::analysis::SCCGraphAnalysis::relationToScc
std::map< const Relation *, size_t > relationToScc
Map from node number to SCC number.
Definition: SCCGraph.h:219
souffle::ast::analysis
Definition: Aggregate.cpp:39
souffle::ast::analysis::SCCGraphAnalysis::getSuccessorSCCs
const std::set< size_t > & getSuccessorSCCs(const size_t scc) const
Get all successor SCCs of a given SCC.
Definition: SCCGraph.h:69
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::ast::analysis::SCCGraphAnalysis::getInternalRelations
const std::set< const Relation * > & getInternalRelations(const size_t scc) const
Get all internal relations of a given SCC.
Definition: SCCGraph.h:105
souffle::ast::analysis::SCCGraphAnalysis::ioType
IOTypeAnalysis * ioType
Definition: SCCGraph.h:234
souffle::profile::ss
class souffle::profile::Tui ss
Definition: Tui.h:336