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

Core section of the magic set transformer. More...

#include <MagicSet.h>

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

Public Member Functions

MagicSetCoreTransformerclone () const override
 
std::string getName () const override
 
- Public Member Functions inherited from souffle::ast::transform::Transformer
bool apply (TranslationUnit &translationUnit)
 
virtual ~Transformer ()=default
 

Private Member Functions

bool transform (TranslationUnit &translationUnit) override
 

Static Private Member Functions

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. More...
 
static Own< AtomcreateMagicAtom (const Atom *atom)
 Creates the magic atom associatd with the given (rel, adornment) pair. More...
 
static Own< ClausecreateMagicClause (const Atom *atom, const VecOwn< Atom > &constrainingAtoms, const std::vector< const BinaryConstraint * > eqConstraints)
 Creates the magic clause centred around the given magic atom. More...
 
static std::string getAdornment (const QualifiedName &name)
 Retrieves an adornment encoded in a given relation name. More...
 
static std::vector< const BinaryConstraint * > getBindingEqualityConstraints (const Clause *clause)
 Get all potentially-binding equality constraints in a clause. More...
 
static QualifiedName getMagicName (const QualifiedName &name)
 Gets a unique magic identifier for a given adorned relation name. More...
 
static bool isAdorned (const QualifiedName &name)
 Checks if a given relation name is adorned. More...
 

Detailed Description

Core section of the magic set transformer.

Creates all magic rules and relations based on the preceding adornment, and adds them into rules as needed. Assumes that Normalisation, Labelling, and Adornment have all been performed.

Definition at line 286 of file MagicSet.h.

Member Function Documentation

◆ addRelevantVariables()

void souffle::ast::transform::MagicSetCoreTransformer::addRelevantVariables ( std::set< std::string > &  variables,
const std::vector< const BinaryConstraint * >  eqConstraints 
)
staticprivate

Get the closure of the given set of variables under appearance in the given eq constraints.

Definition at line 1046 of file MagicSet.cpp.

1046  { fullyBound &= contains(variables, var.getName()); });
1047  return fullyBound;
1048  };
1049 
1050  // Helper method to add all newly relevant variables given a lhs = rhs constraint
1051  auto addLocallyRelevantVariables = [&](const Argument* lhs, const Argument* rhs) {
1052  const auto* lhsVar = dynamic_cast<const ast::Variable*>(lhs);
1053  if (lhsVar == nullptr) return true;
1054 
1055  // if the rhs is fully bound, lhs is now bound
1056  if (!contains(variables, lhsVar->getName())) {
1057  if (isFullyBound(rhs)) {
1058  variables.insert(lhsVar->getName());
1059  return false;
1060  } else {
1061  return true;
1062  }
1063  }
1064 
1065  // if the rhs is a record, and lhs is a bound var, then all rhs vars are bound
1066  bool fixpointReached = true;
1067  if (const auto* rhsRec = dynamic_cast<const RecordInit*>(rhs)) {
1068  for (const auto* arg : rhsRec->getArguments()) {
1069  const auto* subVar = dynamic_cast<const ast::Variable*>(arg);
1070  assert(subVar != nullptr && "expected only variable arguments");
1071  if (!contains(variables, subVar->getName())) {
1072  fixpointReached = false;
1073  variables.insert(subVar->getName());
1074  }
1075  }
1076  }
1077 
1078  return fixpointReached;
1079  };
1080 
1081  // Keep adding in relevant variables until we reach a fixpoint
1082  bool fixpointReached = false;
1083  while (!fixpointReached) {
1084  fixpointReached = true;
1085  for (const auto* eqConstraint : eqConstraints) {
1086  assert(isEqConstraint(eqConstraint->getBaseOperator()) && "expected only eq constraints");
1087  fixpointReached &= addLocallyRelevantVariables(eqConstraint->getLHS(), eqConstraint->getRHS());
1088  fixpointReached &= addLocallyRelevantVariables(eqConstraint->getRHS(), eqConstraint->getLHS());
1089  }
1090  }
1091 }
1092 
1093 Own<Clause> MagicSetCoreTransformer::createMagicClause(const Atom* atom,
1094  const std::vector<Own<Atom>>& constrainingAtoms,
1095  const std::vector<const BinaryConstraint*> eqConstraints) {
1096  auto magicHead = createMagicAtom(atom);
1097  auto magicClause = mk<Clause>();

References souffle::contains().

Here is the call graph for this function:

◆ clone()

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

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

Definition at line 292 of file MagicSet.h.

292  {
293  return new MagicSetCoreTransformer();
294  }

◆ createMagicAtom()

Own< Atom > souffle::ast::transform::MagicSetCoreTransformer::createMagicAtom ( const Atom atom)
staticprivate

Creates the magic atom associatd with the given (rel, adornment) pair.

Definition at line 1030 of file MagicSet.cpp.

1031  {
1032  if (adornmentMarker[i] == 'b') {
1033  magicAtom->addArgument(souffle::clone(args[i]));
1034  }
1035  }
1036 
1037  return magicAtom;
1038 }
1039 
1041  std::set<std::string>& variables, const std::vector<const BinaryConstraint*> eqConstraints) {
1042  // Helper method to check if all variables in an argument are bound
1043  auto isFullyBound = [&](const Argument* arg) {
1044  bool fullyBound = true;

◆ createMagicClause()

Own< Clause > souffle::ast::transform::MagicSetCoreTransformer::createMagicClause ( const Atom atom,
const VecOwn< Atom > &  constrainingAtoms,
const std::vector< const BinaryConstraint * >  eqConstraints 
)
staticprivate

Creates the magic clause centred around the given magic atom.

Definition at line 1099 of file MagicSet.cpp.

1100  : constrainingAtoms) {
1101  magicClause->addToBody(souffle::clone(bindingAtom));
1102  }
1103 
1104  // Get the set of all variables that will be relevant to the magic clause
1105  std::set<std::string> relevantVariables;
1107  constrainingAtoms, [&](const ast::Variable& var) { relevantVariables.insert(var.getName()); });
1108  visitDepthFirst(*magicHead, [&](const ast::Variable& var) { relevantVariables.insert(var.getName()); });
1109  addRelevantVariables(relevantVariables, eqConstraints);
1110 
1111  // Add in all eq constraints containing ONLY relevant variables
1112  for (const auto* eqConstraint : eqConstraints) {
1113  bool addConstraint = true;
1114  visitDepthFirst(*eqConstraint, [&](const ast::Variable& var) {
1115  if (!contains(relevantVariables, var.getName())) {
1116  addConstraint = false;
1117  }
1118  });
1119 
1120  if (addConstraint) magicClause->addToBody(souffle::clone(eqConstraint));
1121  }
1122 
1123  magicClause->setHead(std::move(magicHead));
1124  return magicClause;
1125 }
1126 
1127 std::vector<const BinaryConstraint*> MagicSetCoreTransformer::getBindingEqualityConstraints(
1128  const Clause* clause) {
1129  std::vector<const BinaryConstraint*> equalityConstraints;
1130  for (const auto* lit : clause->getBodyLiterals()) {
1131  const auto* bc = dynamic_cast<const BinaryConstraint*>(lit);

References souffle::clone().

Here is the call graph for this function:

◆ getAdornment()

std::string souffle::ast::transform::MagicSetCoreTransformer::getAdornment ( const QualifiedName name)
staticprivate

Retrieves an adornment encoded in a given relation name.

Definition at line 1012 of file MagicSet.cpp.

1017  {
1018  assert(isAdorned(name) && "cannot magify unadorned predicates");
1019  QualifiedName magicRelName(name);
1020  magicRelName.prepend("@magic");
1021  return magicRelName;

◆ getBindingEqualityConstraints()

std::vector< const BinaryConstraint * > souffle::ast::transform::MagicSetCoreTransformer::getBindingEqualityConstraints ( const Clause clause)
staticprivate

Get all potentially-binding equality constraints in a clause.

Definition at line 1133 of file MagicSet.cpp.

1133  {
1134  bool containsAggrs = false;
1135  visitDepthFirst(*bc, [&](const Aggregator& /* aggr */) { containsAggrs = true; });
1136  if (!containsAggrs) {
1137  equalityConstraints.push_back(bc);
1138  }
1139  }
1140  }
1141  return equalityConstraints;
1142 }
1143 
1144 bool MagicSetCoreTransformer::transform(TranslationUnit& translationUnit) {
1145  Program& program = translationUnit.getProgram();
1146  std::set<Own<Clause>> clausesToRemove;
1147  std::set<Own<Clause>> clausesToAdd;
1148 

References souffle::ast::visitDepthFirst().

Here is the call graph for this function:

◆ getMagicName()

QualifiedName souffle::ast::transform::MagicSetCoreTransformer::getMagicName ( const QualifiedName name)
staticprivate

Gets a unique magic identifier for a given adorned relation name.

Definition at line 1023 of file MagicSet.cpp.

1024  {
1025  auto origRelName = atom->getQualifiedName();
1026  auto args = atom->getArguments();
1027 
1028  auto magicAtom = mk<Atom>(getMagicName(origRelName));

References souffle::ast::Atom::getArguments(), and souffle::ast::Atom::getQualifiedName().

Here is the call graph for this function:

◆ getName()

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

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

Definition at line 288 of file MagicSet.h.

288  {
289  return "MagicSetCoreTransformer";
290  }

◆ isAdorned()

bool souffle::ast::transform::MagicSetCoreTransformer::isAdorned ( const QualifiedName name)
staticprivate

Checks if a given relation name is adorned.

Definition at line 992 of file MagicSet.cpp.

994  {' && finalQualifier[finalQualifier.length() - 1] == '}') {
995  for (size_t i = 1; i < finalQualifier.length() - 1; i++) {
996  char curBindingType = finalQualifier[i];
997  if (curBindingType != 'b' && curBindingType != 'f') {
998  return false;
999  }
1000  }
1001  return true;
1002  }
1003  return false;
1004 }
1005 
1006 std::string MagicSetCoreTransformer::getAdornment(const QualifiedName& name) {
1007  assert(isAdorned(name) && "relation not adorned");
1008  auto qualifiers = name.getQualifiers();
1009  auto finalQualifier = qualifiers[qualifiers.size() - 1];
1010  std::stringstream binding;

References i.

◆ transform()

bool souffle::ast::transform::MagicSetCoreTransformer::transform ( TranslationUnit translationUnit)
overrideprivatevirtual

Perform the Magic Set Transformation

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

Definition at line 1150 of file MagicSet.cpp.

1150  : program.getClauses()) {
1151  clausesToRemove.insert(souffle::clone(clause));
1152 
1153  const auto* head = clause->getHead();
1154  auto relName = head->getQualifiedName();
1155 
1156  // (1) Add the refined clause
1157  if (!isAdorned(relName)) {
1158  // Unadorned relations need not be refined, as every possible tuple is relevant
1159  clausesToAdd.insert(souffle::clone(clause));
1160  } else {
1161  // Refine the clause with a prepended magic atom
1162  auto magicAtom = createMagicAtom(head);
1163  auto refinedClause = mk<Clause>();
1164  refinedClause->setHead(souffle::clone(head));
1165  refinedClause->addToBody(souffle::clone(magicAtom));
1166  for (auto* literal : clause->getBodyLiterals()) {
1167  refinedClause->addToBody(souffle::clone(literal));
1168  }
1169  clausesToAdd.insert(std::move(refinedClause));
1170  }
1171 
1172  // (2) Add the associated magic rules
1173  std::vector<const BinaryConstraint*> eqConstraints = getBindingEqualityConstraints(clause);
1174  std::vector<Own<Atom>> atomsToTheLeft;
1175  if (isAdorned(relName)) {
1176  // Add the specialising head atom
1177  // Output relations are not specialised, and so the head will not contribute to specialisation
1178  atomsToTheLeft.push_back(createMagicAtom(clause->getHead()));
1179  }
1180  for (const auto* lit : clause->getBodyLiterals()) {
1181  const auto* atom = dynamic_cast<const Atom*>(lit);
1182  if (atom == nullptr) continue;
1183  if (!isAdorned(atom->getQualifiedName())) {
1184  atomsToTheLeft.push_back(souffle::clone(atom));
1185  continue;
1186  }
1187 
1188  // Need to create a magic rule
1189  auto magicClause = createMagicClause(atom, atomsToTheLeft, eqConstraints);
1190  atomsToTheLeft.push_back(souffle::clone(atom));
1191  clausesToAdd.insert(std::move(magicClause));
1192  }
1193  }
1194 
1195  for (auto& clause : clausesToAdd) {
1196  program.addClause(souffle::clone(clause));
1197  }
1198  for (const auto& clause : clausesToRemove) {
1199  program.removeClause(clause.get());
1200  }
1201 
1202  // Add in the magic relations
1203  bool changed = false;
1204  for (const auto* rel : program.getRelations()) {
1205  const auto& origName = rel->getQualifiedName();
1206  if (!isAdorned(origName)) continue;
1207  auto magicRelation = mk<Relation>(getMagicName(origName));
1208  auto attributes = getRelation(program, origName)->getAttributes();
1209  auto adornmentMarker = getAdornment(origName);
1210  for (size_t i = 0; i < attributes.size(); i++) {
1211  if (adornmentMarker[i] == 'b') {
1212  magicRelation->addAttribute(souffle::clone(attributes[i]));
1213  }
1214  }
1215  changed = true;
1216  program.addRelation(std::move(magicRelation));
1217  }
1218  return changed;
1219 }
1220 
1221 } // namespace souffle::ast::transform

References souffle::clone().

Here is the call graph for this function:

The documentation for this class was generated from the following files:
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::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::MagicSetCoreTransformer::getAdornment
static std::string getAdornment(const QualifiedName &name)
Retrieves an adornment encoded in a given relation name.
Definition: MagicSet.cpp:1012
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::Relation::getAttributes
std::vector< Attribute * > getAttributes() const
Get relation attributes.
Definition: Relation.h:83
rhs
Own< Argument > rhs
Definition: ResolveAliases.cpp:185
lhs
Own< Argument > lhs
Definition: ResolveAliases.cpp:184
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
i
size_t i
Definition: json11.h:663
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
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::isEqConstraint
bool isEqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:124
souffle::ast::transform::MagicSetCoreTransformer
MagicSetTransformer::MagicSetCoreTransformer MagicSetCoreTransformer
Definition: MagicSet.cpp:63
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: MagicSet.cpp:1150
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::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
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::ast::transform::MagicSetTransformer::MagicSetCoreTransformer::isAdorned
static bool isAdorned(const QualifiedName &name)
Checks if a given relation name is adorned.
Definition: MagicSet.cpp:992