souffle  2.0.2-371-g6315b36
Data Structures | Public Member Functions | Private Member Functions | Static Private Member Functions
souffle::ast::transform::MagicSetTransformer Class Reference

Magic Set Transformation. More...

#include <MagicSet.h>

Inheritance diagram for souffle::ast::transform::MagicSetTransformer:
Inheritance graph
Collaboration diagram for souffle::ast::transform::MagicSetTransformer:
Collaboration graph

Data Structures

class  AdornDatabaseTransformer
 Database adornment. More...
 
class  LabelDatabaseTransformer
 Database labeller. More...
 
class  MagicSetCoreTransformer
 Core section of the magic set transformer. More...
 
class  NormaliseDatabaseTransformer
 Database normaliser for MST. More...
 

Public Member Functions

MagicSetTransformerclone () const override
 
std::string getName () const override
 
 MagicSetTransformer ()
 
- Public Member Functions inherited from souffle::ast::transform::PipelineTransformer
PipelineTransformerclone () const override
 
void disableTransformers (const std::set< std::string > &transforms) override
 
std::string getName () const override
 
std::vector< Transformer * > getSubtransformers () const override
 
template<typename... Args>
 PipelineTransformer (Args... args)
 
 PipelineTransformer (VecOwn< Transformer > pipeline)
 
void setDebugReport () override
 
void setVerbosity (bool verbose) override
 
- Public Member Functions inherited from souffle::ast::transform::MetaTransformer
bool applySubtransformer (TranslationUnit &translationUnit, Transformer *transformer)
 
- Public Member Functions inherited from souffle::ast::transform::Transformer
bool apply (TranslationUnit &translationUnit)
 
virtual ~Transformer ()=default
 

Private Member Functions

bool transform (TranslationUnit &tu) override
 

Static Private Member Functions

static std::set< QualifiedNamegetRelationsToNotLabel (const TranslationUnit &tu)
 Gets the set of relations to not label. More...
 
static std::set< QualifiedNamegetStronglyIgnoredRelations (const TranslationUnit &tu)
 Gets the set of relations to strongly ignore during the MST process. More...
 
static std::set< QualifiedNamegetTriviallyIgnoredRelations (const TranslationUnit &tu)
 Gets the set of relations that are trivially computable, and so should not be magic-set. More...
 
static std::set< QualifiedNamegetWeaklyIgnoredRelations (const TranslationUnit &tu)
 Gets the set of relations to weakly ignore during the MST process. More...
 
static bool shouldRun (const TranslationUnit &tu)
 Determines whether any part of the MST should be run. More...
 

Additional Inherited Members

- Protected Member Functions inherited from souffle::ast::transform::PipelineTransformer
bool transform (TranslationUnit &translationUnit) override
 
- Protected Attributes inherited from souffle::ast::transform::PipelineTransformer
VecOwn< Transformerpipeline
 
- Protected Attributes inherited from souffle::ast::transform::MetaTransformer
bool verbose = false
 

Detailed Description

Magic Set Transformation.

Involves four stages: (1) NormaliseDatabaseTransformer, for assumptions to hold (2) LabelDatabaseTransformer, to support negation (3) AdornDatabaseTransformer, to annotate information flow (4) MagicSetCoreTransformer, to perform the core magifying transformation

Definition at line 51 of file MagicSet.h.

Constructor & Destructor Documentation

◆ MagicSetTransformer()

souffle::ast::transform::MagicSetTransformer::MagicSetTransformer ( )
inline

Definition at line 58 of file MagicSet.h.

59  : PipelineTransformer(mk<NormaliseDatabaseTransformer>(), mk<LabelDatabaseTransformer>(),
60  mk<RemoveRedundantRelationsTransformer>(), mk<AdornDatabaseTransformer>(),
61  mk<RemoveRedundantRelationsTransformer>(), mk<MagicSetCoreTransformer>()) {}

Referenced by clone().

Member Function Documentation

◆ clone()

MagicSetTransformer* souffle::ast::transform::MagicSetTransformer::clone ( ) const
inlineoverridevirtual

Implements souffle::ast::transform::MetaTransformer.

Definition at line 67 of file MagicSet.h.

67  {
68  return new MagicSetTransformer();
69  }

References MagicSetTransformer().

Here is the call graph for this function:

◆ getName()

std::string souffle::ast::transform::MagicSetTransformer::getName ( ) const
inlineoverridevirtual

Implements souffle::ast::transform::Transformer.

Definition at line 63 of file MagicSet.h.

63  {
64  return "MagicSetTransformer";
65  }

◆ getRelationsToNotLabel()

std::set< QualifiedName > souffle::ast::transform::MagicSetTransformer::getRelationsToNotLabel ( const TranslationUnit tu)
staticprivate

Gets the set of relations to not label.

The union of strongly and trivially ignored.

Definition at line 270 of file MagicSet.cpp.

275  {
276  const Program& program = tu.getProgram();
277  if (Global::config().has("magic-transform")) return true;
278  for (const auto* rel : program.getRelations()) {
279  if (rel->hasQualifier(RelationQualifier::MAGIC)) return true;

◆ getStronglyIgnoredRelations()

std::set< QualifiedName > souffle::ast::transform::MagicSetTransformer::getStronglyIgnoredRelations ( const TranslationUnit tu)
staticprivate

Gets the set of relations to strongly ignore during the MST process.

Strongly-ignored relations cannot be safely duplicated without affecting semantics.

Definition at line 219 of file MagicSet.cpp.

220  : program.getClauses()) {
221  bool containsCounter = false;
222  visitDepthFirst(*clause, [&](const Counter& /* counter */) { containsCounter = true; });
223  if (containsCounter) {
224  stronglyIgnoredRelations.insert(clause->getHead()->getQualifiedName());
225  }
226  }
227 
228  bool fixpointReached = false;
229  while (!fixpointReached) {
230  fixpointReached = true;
231  // - To prevent poslabelling issues, all dependent strata should also be strongly ignored
232  std::set<QualifiedName> dependentRelations;
233  for (const auto& relName : stronglyIgnoredRelations) {
234  precedenceGraph.visitDepthFirst(getRelation(program, relName), [&](const auto* dependentRel) {
235  dependentRelations.insert(dependentRel->getQualifiedName());
236  });
237  }
238  for (const auto& depRel : dependentRelations) {
239  if (!contains(stronglyIgnoredRelations, depRel)) {
240  fixpointReached = false;
241  stronglyIgnoredRelations.insert(depRel);
242  }
243  }
244 
245  // - Since we can't duplicate the rules, nothing should be labelled in the bodies as well
246  std::set<QualifiedName> bodyRelations;
247  for (const auto& relName : stronglyIgnoredRelations) {
248  for (const auto* clause : relDetail.getClauses(relName)) {
250  *clause, [&](const Atom& atom) { bodyRelations.insert(atom.getQualifiedName()); });
251  }
252  }
253  for (const auto& bodyRel : bodyRelations) {
254  if (!contains(stronglyIgnoredRelations, bodyRel)) {
255  fixpointReached = false;
256  stronglyIgnoredRelations.insert(bodyRel);
257  }
258  }
259  }
260 
261  return stronglyIgnoredRelations;
262 }
263 
264 std::set<QualifiedName> MagicSetTransformer::getRelationsToNotLabel(const TranslationUnit& tu) {
265  std::set<QualifiedName> result;
266  for (const auto& name : getTriviallyIgnoredRelations(tu)) {
267  result.insert(name);
268  }

References souffle::ast::visitDepthFirst().

Here is the call graph for this function:

◆ getTriviallyIgnoredRelations()

std::set< QualifiedName > souffle::ast::transform::MagicSetTransformer::getTriviallyIgnoredRelations ( const TranslationUnit tu)
staticprivate

Gets the set of relations that are trivially computable, and so should not be magic-set.

Definition at line 70 of file MagicSet.cpp.

70  : program.getRelations()) {
71  // Input relations
72  if (ioTypes.isInput(rel)) {
73  triviallyIgnoredRelations.insert(rel->getQualifiedName());
74  continue;
75  }
76 
77  // Any relations not dependent on any atoms
78  bool hasRules = false;
79  for (const auto* clause : getClauses(program, rel->getQualifiedName())) {
80  visitDepthFirst(clause->getBodyLiterals(), [&](const Atom& /* atom */) { hasRules = true; });
81  }
82  if (!hasRules) {
83  triviallyIgnoredRelations.insert(rel->getQualifiedName());
84  }
85  }
86 
87  return triviallyIgnoredRelations;
88 }
89 
90 std::set<QualifiedName> MagicSetTransformer::getWeaklyIgnoredRelations(const TranslationUnit& tu) {
91  const auto& program = tu.getProgram();
92  const auto& precedenceGraph = tu.getAnalysis<analysis::PrecedenceGraphAnalysis>()->graph();
93  const auto& polyAnalysis = *tu.getAnalysis<analysis::PolymorphicObjectsAnalysis>();
94  std::set<QualifiedName> weaklyIgnoredRelations;

References souffle::ast::getClauses(), rel(), and souffle::ast::visitDepthFirst().

Here is the call graph for this function:

◆ getWeaklyIgnoredRelations()

std::set< QualifiedName > souffle::ast::transform::MagicSetTransformer::getWeaklyIgnoredRelations ( const TranslationUnit tu)
staticprivate

Gets the set of relations to weakly ignore during the MST process.

Weakly-ignored relations cannot be adorned/magic'd. Superset of strongly-ignored relations.

Definition at line 96 of file MagicSet.cpp.

101  : configRels) {
102  std::vector<std::string> qualifiers = splitString(relStr, '.');
103  specifiedRelations.push_back(QualifiedName(qualifiers));
104  }
105 
106  // Pick up specified relations from relation tags
107  for (const auto* rel : program.getRelations()) {
108  if (rel->hasQualifier(RelationQualifier::MAGIC)) {
109  specifiedRelations.push_back(rel->getQualifiedName());
110  }
111  }
112 
113  // Get the complement if not everything is magic'd
114  if (!contains(configRels, "*")) {
115  for (const Relation* rel : program.getRelations()) {
116  if (!contains(specifiedRelations, rel->getQualifiedName())) {
117  weaklyIgnoredRelations.insert(rel->getQualifiedName());
118  }
119  }
120  }
121 
122  // - Add trivially computable relations
123  for (const auto& relName : getTriviallyIgnoredRelations(tu)) {
124  weaklyIgnoredRelations.insert(relName);
125  }
126 
127  // - Any relation with a neglabel
128  visitDepthFirst(program, [&](const Atom& atom) {
129  const auto& qualifiers = atom.getQualifiedName().getQualifiers();
130  if (!qualifiers.empty() && qualifiers[0] == "@neglabel") {
131  weaklyIgnoredRelations.insert(atom.getQualifiedName());
132  }
133  });
134 
135  // - Any relation with a clause containing float-related binary constraints
136  const std::set<BinaryConstraintOp> floatOps(
139  for (const auto* clause : program.getClauses()) {
140  visitDepthFirst(*clause, [&](const BinaryConstraint& bc) {
141  if (contains(floatOps, polyAnalysis.getOverloadedOperator(&bc))) {
142  weaklyIgnoredRelations.insert(clause->getHead()->getQualifiedName());
143  }
144  });
145  }
146 
147  // - Any relation with a clause containing order-dependent functors
148  const std::set<FunctorOp> orderDepFuncOps(
150  for (const auto* clause : program.getClauses()) {
151  visitDepthFirst(*clause, [&](const IntrinsicFunctor& functor) {
152  if (contains(orderDepFuncOps, polyAnalysis.getOverloadedFunctionOp(&functor))) {
153  weaklyIgnoredRelations.insert(clause->getHead()->getQualifiedName());
154  }
155  });
156  }
157 
158  // - Any eqrel relation
159  for (auto* rel : program.getRelations()) {
160  if (rel->getRepresentation() == RelationRepresentation::EQREL) {
161  weaklyIgnoredRelations.insert(rel->getQualifiedName());
162  }
163  }
164 
165  // - Any relation with execution plans
166  for (auto* clause : program.getClauses()) {
167  if (clause->getExecutionPlan() != nullptr) {
168  weaklyIgnoredRelations.insert(clause->getHead()->getQualifiedName());
169  }
170  }
171 
172  // - Any atom appearing in a clause containing a counter
173  for (auto* clause : program.getClauses()) {
174  bool containsCounter = false;
175  visitDepthFirst(*clause, [&](const Counter& /* counter */) { containsCounter = true; });
176  if (containsCounter) {
177  visitDepthFirst(*clause,
178  [&](const Atom& atom) { weaklyIgnoredRelations.insert(atom.getQualifiedName()); });
179  }
180  }
181 
182  // - Deal with strongly ignored relations
183  const auto& stronglyIgnoredRelations = getStronglyIgnoredRelations(tu);
184 
185  // Add them in directly
186  for (const auto& relName : stronglyIgnoredRelations) {
187  weaklyIgnoredRelations.insert(relName);
188  }
189 
190  // Add in any atoms whose magic rules might cause a need for neglabelling
191  // - Essentially, suppose R is strongly-ignored and A depends on R. Then, we must weakly ignore
192  // any relation that appears after A in any clause, otherwise a magic-set might be created that
193  // requires R to be neglabelled.
194  for (const auto& relName : stronglyIgnoredRelations) {
195  precedenceGraph.visitDepthFirst(getRelation(program, relName), [&](const auto* dependentRel) {
196  const auto& depName = dependentRel->getQualifiedName();
197  for (const auto* clause : program.getClauses()) {
198  const auto& atoms = getBodyLiterals<Atom>(*clause);
199  bool startIgnoring = false;
200  for (const auto& atom : atoms) {
201  startIgnoring |= (atom->getQualifiedName() == depName);
202  if (startIgnoring) {
203  weaklyIgnoredRelations.insert(atom->getQualifiedName());
204  }
205  }
206  }
207  });
208  }
209 
210  return weaklyIgnoredRelations;
211 }
212 
213 std::set<QualifiedName> MagicSetTransformer::getStronglyIgnoredRelations(const TranslationUnit& tu) {
214  const auto& program = tu.getProgram();
215  const auto& relDetail = *tu.getAnalysis<analysis::RelationDetailCacheAnalysis>();
216  const auto& precedenceGraph = tu.getAnalysis<analysis::PrecedenceGraphAnalysis>()->graph();
217  std::set<QualifiedName> stronglyIgnoredRelations;

◆ shouldRun()

bool souffle::ast::transform::MagicSetTransformer::shouldRun ( const TranslationUnit tu)
staticprivate

Determines whether any part of the MST should be run.

Definition at line 281 of file MagicSet.cpp.

284  {
285  bool changed = false;
286 
287  /** (1) Partition input and output relations */
288  changed |= partitionIO(translationUnit);

Referenced by transform().

◆ transform()

bool souffle::ast::transform::MagicSetTransformer::transform ( TranslationUnit tu)
inlineoverrideprivatevirtual

Implements souffle::ast::transform::Transformer.

Definition at line 72 of file MagicSet.h.

72  {
73  return shouldRun(tu) ? PipelineTransformer::transform(tu) : false;
74  }

References shouldRun(), and souffle::ast::transform::PipelineTransformer::transform().

Here is the call graph for this function:

The documentation for this class was generated from the following files:
souffle::FunctorOp::DIV
@ DIV
souffle::FunctorOp::FDIV
@ FDIV
souffle::BinaryConstraintOp::FGE
@ FGE
souffle::BinaryConstraintOp::FNE
@ FNE
souffle::RelationRepresentation::EQREL
@ EQREL
souffle::ast::transform::PipelineTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: Pipeline.h:109
souffle::ast::transform::PipelineTransformer::PipelineTransformer
PipelineTransformer(Args... args)
Definition: Pipeline.h:53
souffle::contains
bool contains(const C &container, const typename C::value_type &element)
A utility to check generically whether a given element is contained in a given container.
Definition: ContainerUtil.h:75
souffle::ast::transform::MagicSetTransformer::getTriviallyIgnoredRelations
static std::set< QualifiedName > getTriviallyIgnoredRelations(const TranslationUnit &tu)
Gets the set of relations that are trivially computable, and so should not be magic-set.
Definition: MagicSet.cpp:70
souffle::BinaryConstraintOp::FEQ
@ FEQ
souffle::FunctorOp::MOD
@ MOD
souffle::BinaryConstraintOp::FLT
@ FLT
souffle::BinaryConstraintOp::FLE
@ FLE
souffle::RelationQualifier::MAGIC
@ MAGIC
souffle::ast::transform::MagicSetTransformer::MagicSetTransformer
MagicSetTransformer()
Definition: MagicSet.h:58
souffle::ast::getRelation
Relation * getRelation(const Program &program, const QualifiedName &name)
Returns the relation with the given name in the program.
Definition: Utils.cpp:101
souffle::ast::transform::MagicSetTransformer::getStronglyIgnoredRelations
static std::set< QualifiedName > getStronglyIgnoredRelations(const TranslationUnit &tu)
Gets the set of relations to strongly ignore during the MST process.
Definition: MagicSet.cpp:219
souffle::ast::transform::MagicSetTransformer::getWeaklyIgnoredRelations
static std::set< QualifiedName > getWeaklyIgnoredRelations(const TranslationUnit &tu)
Gets the set of relations to weakly ignore during the MST process.
Definition: MagicSet.cpp:96
souffle::ast::getClauses
std::vector< Clause * > getClauses(const Program &program, const QualifiedName &relationName)
Returns a vector of clauses in the program describing the relation with the given name.
Definition: Utils.cpp:77
souffle::ast::transform::MagicSetTransformer::shouldRun
static bool shouldRun(const TranslationUnit &tu)
Determines whether any part of the MST should be run.
Definition: MagicSet.cpp:281
souffle::Global::config
static MainConfig & config()
Definition: Global.h:141
souffle::FunctorOp::UMOD
@ UMOD
souffle::ast::Relation::getQualifiedName
const QualifiedName & getQualifiedName() const
Get qualified relation name.
Definition: Relation.h:57
souffle::splitString
std::vector< std::string > splitString(const std::string &str, char delimiter)
Splits a string given a delimiter.
Definition: StringUtil.h:321
souffle::ast::visitDepthFirst
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
Definition: Visitor.h:273
souffle::ast::transform::MagicSetTransformer::getRelationsToNotLabel
static std::set< QualifiedName > getRelationsToNotLabel(const TranslationUnit &tu)
Gets the set of relations to not label.
Definition: MagicSet.cpp:270
souffle::BinaryConstraintOp::FGT
@ FGT
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086