souffle  2.0.2-371-g6315b36
MagicSet.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2017, The Souffle Developers. 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 MagicSet.h
12  *
13  * Define classes and functionality related to the magic set transformation.
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
19 #include "ast/Atom.h"
20 #include "ast/BinaryConstraint.h"
21 #include "ast/Clause.h"
22 #include "ast/QualifiedName.h"
23 #include "ast/transform/Pipeline.h"
27 #include <algorithm>
28 #include <cassert>
29 #include <cstddef>
30 #include <memory>
31 #include <set>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 namespace souffle::ast {
37 class Program;
38 class TranslationUnit;
39 } // namespace souffle::ast
40 
41 namespace souffle::ast::transform {
42 
43 /**
44  * Magic Set Transformation.
45  * Involves four stages:
46  * (1) NormaliseDatabaseTransformer, for assumptions to hold
47  * (2) LabelDatabaseTransformer, to support negation
48  * (3) AdornDatabaseTransformer, to annotate information flow
49  * (4) MagicSetCoreTransformer, to perform the core magifying transformation
50  */
52 public:
57 
62 
63  std::string getName() const override {
64  return "MagicSetTransformer";
65  }
66 
67  MagicSetTransformer* clone() const override {
68  return new MagicSetTransformer();
69  }
70 
71 private:
72  bool transform(TranslationUnit& tu) override {
73  return shouldRun(tu) ? PipelineTransformer::transform(tu) : false;
74  }
75 
76  /** Determines whether any part of the MST should be run. */
77  static bool shouldRun(const TranslationUnit& tu);
78 
79  /**
80  * Gets the set of relations that are trivially computable,
81  * and so should not be magic-set.
82  */
83  static std::set<QualifiedName> getTriviallyIgnoredRelations(const TranslationUnit& tu);
84 
85  /**
86  * Gets the set of relations to weakly ignore during the MST process.
87  * Weakly-ignored relations cannot be adorned/magic'd.
88  * Superset of strongly-ignored relations.
89  */
90  static std::set<QualifiedName> getWeaklyIgnoredRelations(const TranslationUnit& tu);
91 
92  /**
93  * Gets the set of relations to strongly ignore during the MST process.
94  * Strongly-ignored relations cannot be safely duplicated without affecting semantics.
95  */
96  static std::set<QualifiedName> getStronglyIgnoredRelations(const TranslationUnit& tu);
97 
98  /**
99  * Gets the set of relations to not label.
100  * The union of strongly and trivially ignored.
101  */
102  static std::set<QualifiedName> getRelationsToNotLabel(const TranslationUnit& tu);
103 };
104 
105 /**
106  * Database normaliser for MST.
107  * Effects:
108  * - Partitions database into [input|intermediate|queries]
109  * - Normalises all arguments and constraints
110  * Prerequisite for adornment.
111  */
113 public:
114  std::string getName() const override {
115  return "NormaliseDatabaseTransformer";
116  }
117 
119  return new NormaliseDatabaseTransformer();
120  }
121 
122 private:
123  bool transform(TranslationUnit& translationUnit) override;
124 
125  /**
126  * Partitions the input and output relations.
127  * Program will no longer have relations that are both input and output.
128  */
129  static bool partitionIO(TranslationUnit& translationUnit);
130 
131  /**
132  * Separates the IDB from the EDB, so that they are disjoint.
133  * Program will no longer have input relations that appear as the head of clauses.
134  */
135  static bool extractIDB(TranslationUnit& translationUnit);
136 
137  /**
138  * Extracts output relations into separate simple query relations,
139  * so that they are unused in any other rules.
140  * Programs will only contain output relations which:
141  * (1) have exactly one rule defining them
142  * (2) do not appear in other rules
143  */
144  static bool querifyOutputRelations(TranslationUnit& translationUnit);
145 
146  /**
147  * Normalise all arguments within each clause.
148  * All arguments in all clauses will now be either:
149  * (1) a variable, or
150  * (2) the RHS of a `<var> = <arg>` constraint
151  */
152  static bool normaliseArguments(TranslationUnit& translationUnit);
153 };
154 
155 /**
156  * Database labeller. Runs the magic-set labelling algorithm.
157  * Necessary for supporting negation in MST.
158  */
160 public:
163 
166 
167  std::string getName() const override {
168  return "LabelDatabaseTransformer";
169  }
170 
171  LabelDatabaseTransformer* clone() const override {
172  return new LabelDatabaseTransformer();
173  }
174 
175 private:
176  /** Check if a relation is negatively labelled. */
177  static bool isNegativelyLabelled(const QualifiedName& name);
178 };
179 
180 /**
181  * Runs the first stage of the labelling algorithm.
182  * Separates out negated appearances of relations from the main SCC graph, preventing them from affecting
183  * stratification once magic dependencies are added.
184  */
186 public:
187  std::string getName() const override {
188  return "NegativeLabellingTransformer";
189  }
190 
192  return new NegativeLabellingTransformer();
193  }
194 
195 private:
196  bool transform(TranslationUnit& translationUnit) override;
197 
198  /** Provide a unique name for negatively-labelled relations. */
199  static QualifiedName getNegativeLabel(const QualifiedName& name);
200 };
201 
202 /**
203  * Runs the second stage of the labelling algorithm.
204  * Separates out the dependencies of negatively labelled atoms from the main SCC graph, preventing them from
205  * affecting stratification after magic.
206  * Note: Negative labelling must have been run first.
207  */
209 public:
210  std::string getName() const override {
211  return "PositiveLabellingTransformer";
212  }
213 
215  return new PositiveLabellingTransformer();
216  }
217 
218 private:
219  bool transform(TranslationUnit& translationUnit) override;
220 
221  /** Provide a unique name for a positively labelled relation copy. */
222  static QualifiedName getPositiveLabel(const QualifiedName& name, size_t count);
223 };
224 
225 /**
226  * Database adornment.
227  * Adorns the rules of a database with variable flow and binding information.
228  * Prerequisite for the magic set transformation.
229  */
231 public:
232  std::string getName() const override {
233  return "AdornDatabaseTransformer";
234  }
235 
236  AdornDatabaseTransformer* clone() const override {
237  return new AdornDatabaseTransformer();
238  }
239 
240 private:
241  using adorned_predicate = std::pair<QualifiedName, std::string>;
242 
243  std::set<adorned_predicate> headAdornmentsToDo;
244  std::set<QualifiedName> headAdornmentsSeen;
245 
248  std::set<QualifiedName> weaklyIgnoredRelations;
249 
250  bool transform(TranslationUnit& translationUnit) override;
251 
252  /** Get the unique identifier corresponding to an adorned predicate. */
253  static QualifiedName getAdornmentID(const QualifiedName& relName, const std::string& adornmentMarker);
254 
255  /** Add an adornment to the ToDo queue if it hasn't been processed before. */
256  void queueAdornment(const QualifiedName& relName, const std::string& adornmentMarker) {
257  auto adornmentID = getAdornmentID(relName, adornmentMarker);
258  if (!contains(headAdornmentsSeen, adornmentID)) {
259  headAdornmentsToDo.insert(std::make_pair(relName, adornmentMarker));
260  headAdornmentsSeen.insert(adornmentID);
261  }
262  }
263 
264  /** Check if any more relations need to be adorned. */
265  bool hasAdornmentToProcess() const {
266  return !headAdornmentsToDo.empty();
267  }
268 
269  /** Pop off the next predicate adornment to process. **/
271  assert(hasAdornmentToProcess() && "no adornment to pop");
272  auto headAdornment = *(headAdornmentsToDo.begin());
273  headAdornmentsToDo.erase(headAdornmentsToDo.begin());
274  return headAdornment;
275  }
276 
277  /** Returns the adorned version of a clause. */
278  Own<Clause> adornClause(const Clause* clause, const std::string& adornmentMarker);
279 };
280 
281 /**
282  * Core section of the magic set transformer.
283  * Creates all magic rules and relations based on the preceding adornment, and adds them into rules as needed.
284  * Assumes that Normalisation, Labelling, and Adornment have all been performed.
285  */
287 public:
288  std::string getName() const override {
289  return "MagicSetCoreTransformer";
290  }
291 
292  MagicSetCoreTransformer* clone() const override {
293  return new MagicSetCoreTransformer();
294  }
295 
296 private:
297  bool transform(TranslationUnit& translationUnit) override;
298 
299  /** Gets a unique magic identifier for a given adorned relation name */
300  static QualifiedName getMagicName(const QualifiedName& name);
301 
302  /** Checks if a given relation name is adorned */
303  static bool isAdorned(const QualifiedName& name);
304 
305  /** Retrieves an adornment encoded in a given relation name */
306  static std::string getAdornment(const QualifiedName& name);
307 
308  /** Get all potentially-binding equality constraints in a clause */
309  static std::vector<const BinaryConstraint*> getBindingEqualityConstraints(const Clause* clause);
310 
311  /** Get the closure of the given set of variables under appearance in the given eq constraints */
312  static void addRelevantVariables(
313  std::set<std::string>& variables, const std::vector<const BinaryConstraint*> eqConstraints);
314 
315  /** Creates the magic atom associatd with the given (rel, adornment) pair */
316  static Own<Atom> createMagicAtom(const Atom* atom);
317 
318  /** Creates the magic clause centred around the given magic atom */
319  static Own<Clause> createMagicClause(const Atom* atom, const VecOwn<Atom>& constrainingAtoms,
320  const std::vector<const BinaryConstraint*> eqConstraints);
321 };
322 
323 } // namespace souffle::ast::transform
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::clone
LabelDatabaseTransformer * clone() const override
Definition: MagicSet.h:171
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::adornClause
Own< Clause > adornClause(const Clause *clause, const std::string &adornmentMarker)
Returns the adorned version of a clause.
Definition: MagicSet.cpp:628
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::createMagicAtom
static Own< Atom > createMagicAtom(const Atom *atom)
Creates the magic atom associatd with the given (rel, adornment) pair.
Definition: MagicSet.cpp:1030
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::getName
std::string getName() const override
Definition: MagicSet.h:167
souffle::ast::transform::MagicSetTransformer::NormaliseDatabaseTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: MagicSet.cpp:290
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::NegativeLabellingTransformer::getName
std::string getName() const override
Definition: MagicSet.h:187
souffle::ast::transform::MagicSetTransformer::clone
MagicSetTransformer * clone() const override
Definition: MagicSet.h:67
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::adorned_predicate
std::pair< QualifiedName, std::string > adorned_predicate
Definition: MagicSet.h:241
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::PositiveLabellingTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: MagicSet.cpp:868
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::getName
std::string getName() const override
Definition: MagicSet.h:288
souffle::ast::transform::PipelineTransformer
Transformer that holds an arbitrary number of sub-transformations.
Definition: Pipeline.h:44
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::NegativeLabellingTransformer::getNegativeLabel
static QualifiedName getNegativeLabel(const QualifiedName &name)
Provide a unique name for negatively-labelled relations.
Definition: MagicSet.cpp:781
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::getBindingEqualityConstraints
static std::vector< const BinaryConstraint * > getBindingEqualityConstraints(const Clause *clause)
Get all potentially-binding equality constraints in a clause.
Definition: MagicSet.cpp:1133
souffle::ast::transform::MagicSetTransformer::NormaliseDatabaseTransformer
Database normaliser for MST.
Definition: MagicSet.h:112
souffle::ast::transform::MagicSetTransformer::NormaliseDatabaseTransformer::querifyOutputRelations
static bool querifyOutputRelations(TranslationUnit &translationUnit)
Extracts output relations into separate simple query relations, so that they are unused in any other ...
Definition: MagicSet.cpp:443
RemoveRedundantRelations.h
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::getAdornment
static std::string getAdornment(const QualifiedName &name)
Retrieves an adornment encoded in a given relation name.
Definition: MagicSet.cpp:1012
souffle::ast::transform::PipelineTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: Pipeline.h:109
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer
Database labeller.
Definition: MagicSet.h:159
souffle::ast::transform::MagicSetTransformer::NormaliseDatabaseTransformer::normaliseArguments
static bool normaliseArguments(TranslationUnit &translationUnit)
Normalise all arguments within each clause.
Definition: MagicSet.cpp:517
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::isNegativelyLabelled
static bool isNegativelyLabelled(const QualifiedName &name)
Check if a relation is negatively labelled.
Definition: MagicSet.cpp:795
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::LabelDatabaseTransformer::NegativeLabellingTransformer::clone
NegativeLabellingTransformer * clone() const override
Definition: MagicSet.h:191
souffle::ast::transform::MagicSetTransformer::NormaliseDatabaseTransformer::partitionIO
static bool partitionIO(TranslationUnit &translationUnit)
Partitions the input and output relations.
Definition: MagicSet.cpp:312
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::hasAdornmentToProcess
bool hasAdornmentToProcess() const
Check if any more relations need to be adorned.
Definition: MagicSet.h:265
souffle::ast::transform::MagicSetTransformer
Magic Set Transformation.
Definition: MagicSet.h:51
Transformer.h
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
Pipeline.h
souffle::ast::Clause
Intermediate representation of a horn clause.
Definition: Clause.h:51
souffle::ast::transform::NormaliseDatabaseTransformer
MagicSetTransformer::NormaliseDatabaseTransformer NormaliseDatabaseTransformer
Definition: MagicSet.cpp:60
souffle::ast::transform::MagicSetTransformer::NormaliseDatabaseTransformer::getName
std::string getName() const override
Definition: MagicSet.h:114
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::PositiveLabellingTransformer::getName
std::string getName() const override
Definition: MagicSet.h:210
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::getAdornmentID
static QualifiedName getAdornmentID(const QualifiedName &relName, const std::string &adornmentMarker)
Get the unique identifier corresponding to an adorned predicate.
Definition: MagicSet.cpp:618
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::clone
AdornDatabaseTransformer * clone() const override
Definition: MagicSet.h:236
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::queueAdornment
void queueAdornment(const QualifiedName &relName, const std::string &adornmentMarker)
Add an adornment to the ToDo queue if it hasn't been processed before.
Definition: MagicSet.h:256
souffle::ast::transform::MagicSetTransformer::transform
bool transform(TranslationUnit &tu) override
Definition: MagicSet.h:72
souffle::ast::Atom
An atom class.
Definition: Atom.h:51
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::PositiveLabellingTransformer
Runs the second stage of the labelling algorithm.
Definition: MagicSet.h:208
souffle::ast::transform::MagicSetTransformer::NormaliseDatabaseTransformer::extractIDB
static bool extractIDB(TranslationUnit &translationUnit)
Separates the IDB from the EDB, so that they are disjoint.
Definition: MagicSet.cpp:380
souffle::ast::transform::AdornDatabaseTransformer
MagicSetTransformer::AdornDatabaseTransformer AdornDatabaseTransformer
Definition: MagicSet.cpp:62
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::NegativeLabellingTransformer
Runs the first stage of the labelling algorithm.
Definition: MagicSet.h:185
souffle::ast::transform::Transformer
Definition: Transformer.h:30
souffle::mk
Own< A > mk(Args &&... xs)
Definition: ContainerUtil.h:48
souffle::ast::transform::MagicSetTransformer::MagicSetTransformer
MagicSetTransformer()
Definition: MagicSet.h:58
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::getMagicName
static QualifiedName getMagicName(const QualifiedName &name)
Gets a unique magic identifier for a given adorned relation name.
Definition: MagicSet.cpp:1023
ContainerUtil.h
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::headAdornmentsToDo
std::set< adorned_predicate > headAdornmentsToDo
Definition: MagicSet.h:243
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::AdornDatabaseTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: MagicSet.cpp:730
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::LabelDatabaseTransformer
LabelDatabaseTransformer()
Definition: MagicSet.h:164
Atom.h
souffle::ast::TranslationUnit
Translation unit class for the translation pipeline.
Definition: TranslationUnit.h:51
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::test::count
int count(const C &c)
Definition: table_test.cpp:40
souffle::ast::transform::MagicSetTransformer::NormaliseDatabaseTransformer::clone
NormaliseDatabaseTransformer * clone() const override
Definition: MagicSet.h:118
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::weaklyIgnoredRelations
std::set< QualifiedName > weaklyIgnoredRelations
Definition: MagicSet.h:248
souffle::ast::transform
Definition: Program.h:45
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::headAdornmentsSeen
std::set< QualifiedName > headAdornmentsSeen
Definition: MagicSet.h:244
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::redundantClauses
VecOwn< Clause > redundantClauses
Definition: MagicSet.h:247
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::clone
MagicSetCoreTransformer * clone() const override
Definition: MagicSet.h:292
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer
Core section of the magic set transformer.
Definition: MagicSet.h:286
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::ast::transform::MagicSetCoreTransformer
MagicSetTransformer::MagicSetCoreTransformer MagicSetCoreTransformer
Definition: MagicSet.cpp:63
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer
Database adornment.
Definition: MagicSet.h:230
souffle::ast::transform::NegativeLabellingTransformer
MagicSetTransformer::LabelDatabaseTransformer::NegativeLabellingTransformer NegativeLabellingTransformer
Definition: MagicSet.cpp:66
QualifiedName.h
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::getName
std::string getName() const override
Definition: MagicSet.h:232
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::adornedClauses
VecOwn< Clause > adornedClauses
Definition: MagicSet.h:246
souffle::ast::transform::RemoveRedundantRelationsTransformer
Transformation pass to remove relations which are redundant (do not contribute to output).
Definition: RemoveRedundantRelations.h:30
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: MagicSet.cpp:1150
Clause.h
souffle::ast::transform::MagicSetTransformer::getName
std::string getName() const override
Definition: MagicSet.h:63
BinaryConstraint.h
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::NegativeLabellingTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: MagicSet.cpp:801
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::addRelevantVariables
static void addRelevantVariables(std::set< std::string > &variables, const std::vector< const BinaryConstraint * > eqConstraints)
Get the closure of the given set of variables under appearance in the given eq constraints.
Definition: MagicSet.cpp:1046
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::createMagicClause
static Own< Clause > createMagicClause(const Atom *atom, const VecOwn< Atom > &constrainingAtoms, const std::vector< const BinaryConstraint * > eqConstraints)
Creates the magic clause centred around the given magic atom.
Definition: MagicSet.cpp:1099
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::ast
Definition: Aggregator.h:35
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::nextAdornmentToProcess
adorned_predicate nextAdornmentToProcess()
Pop off the next predicate adornment to process.
Definition: MagicSet.h:270
souffle::ast::QualifiedName
Qualified Name class defines fully/partially qualified names to identify objects in components.
Definition: QualifiedName.h:39
souffle::VecOwn
std::vector< Own< A > > VecOwn
Definition: ContainerUtil.h:45
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::PositiveLabellingTransformer::clone
PositiveLabellingTransformer * clone() const override
Definition: MagicSet.h:214
souffle::ast::transform::PositiveLabellingTransformer
MagicSetTransformer::LabelDatabaseTransformer::PositiveLabellingTransformer PositiveLabellingTransformer
Definition: MagicSet.cpp:68
souffle::ast::transform::MagicSetTransformer::LabelDatabaseTransformer::PositiveLabellingTransformer::getPositiveLabel
static QualifiedName getPositiveLabel(const QualifiedName &name, size_t count)
Provide a unique name for a positively labelled relation copy.
Definition: MagicSet.cpp:787
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::isAdorned
static bool isAdorned(const QualifiedName &name)
Checks if a given relation name is adorned.
Definition: MagicSet.cpp:992