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

Database adornment. More...

#include <MagicSet.h>

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

Public Member Functions

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

Private Types

using adorned_predicate = std::pair< QualifiedName, std::string >
 

Private Member Functions

Own< ClauseadornClause (const Clause *clause, const std::string &adornmentMarker)
 Returns the adorned version of a clause. More...
 
bool hasAdornmentToProcess () const
 Check if any more relations need to be adorned. More...
 
adorned_predicate nextAdornmentToProcess ()
 Pop off the next predicate adornment to process. More...
 
void queueAdornment (const QualifiedName &relName, const std::string &adornmentMarker)
 Add an adornment to the ToDo queue if it hasn't been processed before. More...
 
bool transform (TranslationUnit &translationUnit) override
 

Static Private Member Functions

static QualifiedName getAdornmentID (const QualifiedName &relName, const std::string &adornmentMarker)
 Get the unique identifier corresponding to an adorned predicate. More...
 

Private Attributes

VecOwn< ClauseadornedClauses
 
std::set< QualifiedNameheadAdornmentsSeen
 
std::set< adorned_predicateheadAdornmentsToDo
 
VecOwn< ClauseredundantClauses
 
std::set< QualifiedNameweaklyIgnoredRelations
 

Detailed Description

Database adornment.

Adorns the rules of a database with variable flow and binding information. Prerequisite for the magic set transformation.

Definition at line 230 of file MagicSet.h.

Member Typedef Documentation

◆ adorned_predicate

Definition at line 241 of file MagicSet.h.

Member Function Documentation

◆ adornClause()

Own< Clause > souffle::ast::transform::AdornDatabaseTransformer::adornClause ( const Clause clause,
const std::string &  adornmentMarker 
)
private

Returns the adorned version of a clause.

Definition at line 628 of file MagicSet.cpp.

635  : Suppose a new variable Y is marked as bound because of its appearance in a functor
636  * Y=X+1, and X was already found to be bound:
637  * (1) If X was bound through a body atom, then the behaviour of typical magic-set is exhibited, where
638  * the magic-set of Y is bounded by the values that X can take, which is bounded by induction.
639  * (2) If X was bound only through the head atom, then Y is only fixed to an appearance in a magic-atom.
640  * In the presence of recursion, this can potentially lead to an infinitely-sized magic-set for an atom.
641  *
642  * Therefore, bound head atom vars should be marked as weakly bound.
643  */
644  for (size_t i = 0; i < adornmentMarker.length(); i++) {
645  const auto* var = dynamic_cast<ast::Variable*>(headArgs[i]);
646  assert(var != nullptr && "expected only variables in head");
647  if (adornmentMarker[i] == 'b') {
648  variableBindings.bindVariableWeakly(var->getName());
649  }
650  }
651 
652  // Create the adorned clause with an empty body
653  auto adornedClause = mk<Clause>();
654 
655  // Copy over plans if needed
656  if (clause->getExecutionPlan() != nullptr) {
657  assert(contains(weaklyIgnoredRelations, clause->getHead()->getQualifiedName()) &&
658  "clauses with plans should be ignored");
659  adornedClause->setExecutionPlan(souffle::clone(clause->getExecutionPlan()));
660  }
661 
662  // Create the head atom
663  auto adornedHeadAtom = mk<Atom>(getAdornmentID(relName, adornmentMarker));
664  assert((adornmentMarker == "" || headArgs.size() == adornmentMarker.length()) &&
665  "adornment marker should correspond to head atom variables");
666  for (const auto* arg : headArgs) {
667  const auto* var = dynamic_cast<const ast::Variable*>(arg);
668  assert(var != nullptr && "expected only variables in head");
669  adornedHeadAtom->addArgument(souffle::clone(var));
670  }
671  adornedClause->setHead(std::move(adornedHeadAtom));
672 
673  // Add in adorned body literals
674  std::vector<Own<Literal>> adornedBodyLiterals;
675  for (const auto* lit : clause->getBodyLiterals()) {
676  if (const auto* negation = dynamic_cast<const Negation*>(lit)) {
677  // Negated atoms should not be adorned, but their clauses should be anyway
678  const auto negatedAtomName = negation->getAtom()->getQualifiedName();
679  assert(contains(weaklyIgnoredRelations, negatedAtomName) &&
680  "negated atoms should not be adorned");
681  queueAdornment(negatedAtomName, "");
682  }
683 
684  if (!isA<Atom>(lit)) {
685  // Non-atoms are added directly
686  adornedBodyLiterals.push_back(souffle::clone(lit));
687  continue;
688  }
689 
690  const auto* atom = dynamic_cast<const Atom*>(lit);
691  assert(atom != nullptr && "expected atom");
692 
693  // Form the appropriate adornment marker
694  std::stringstream atomAdornment;
695  if (!contains(weaklyIgnoredRelations, atom->getQualifiedName())) {
696  for (const auto* arg : atom->getArguments()) {
697  const auto* var = dynamic_cast<const ast::Variable*>(arg);
698  assert(var != nullptr && "expected only variables in atom");
699  atomAdornment << (variableBindings.isBound(var->getName()) ? "b" : "f");
700  }
701  }
702  auto currAtomAdornmentID = getAdornmentID(atom->getQualifiedName(), atomAdornment.str());
703 
704  // Add to the ToDo queue if needed
705  queueAdornment(atom->getQualifiedName(), atomAdornment.str());
706 
707  // Add the adorned version to the clause
708  auto adornedBodyAtom = souffle::clone(atom);
709  adornedBodyAtom->setQualifiedName(currAtomAdornmentID);
710  adornedBodyLiterals.push_back(std::move(adornedBodyAtom));
711 
712  // All arguments are now bound
713  for (const auto* arg : atom->getArguments()) {
714  const auto* var = dynamic_cast<const ast::Variable*>(arg);
715  assert(var != nullptr && "expected only variables in atom");
716  variableBindings.bindVariableStrongly(var->getName());
717  }
718  }
719  adornedClause->setBodyLiterals(std::move(adornedBodyLiterals));
720 
721  return adornedClause;
722 }
723 
724 bool AdornDatabaseTransformer::transform(TranslationUnit& translationUnit) {
725  Program& program = translationUnit.getProgram();
726  const auto& ioTypes = *translationUnit.getAnalysis<analysis::IOTypeAnalysis>();
728 

References souffle::ast::BindingStore::bindVariableWeakly(), and i.

Here is the call graph for this function:

◆ clone()

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

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

Definition at line 236 of file MagicSet.h.

236  {
237  return new AdornDatabaseTransformer();
238  }

◆ getAdornmentID()

QualifiedName souffle::ast::transform::AdornDatabaseTransformer::getAdornmentID ( const QualifiedName relName,
const std::string &  adornmentMarker 
)
staticprivate

Get the unique identifier corresponding to an adorned predicate.

Definition at line 618 of file MagicSet.cpp.

622  {
623  const auto& relName = clause->getHead()->getQualifiedName();
624  const auto& headArgs = clause->getHead()->getArguments();
625  BindingStore variableBindings(clause);
626 

Referenced by queueAdornment().

◆ getName()

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

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

Definition at line 232 of file MagicSet.h.

232  {
233  return "AdornDatabaseTransformer";
234  }

◆ hasAdornmentToProcess()

bool souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::hasAdornmentToProcess ( ) const
inlineprivate

Check if any more relations need to be adorned.

Definition at line 265 of file MagicSet.h.

265  {
266  return !headAdornmentsToDo.empty();
267  }

References headAdornmentsToDo.

Referenced by nextAdornmentToProcess().

◆ nextAdornmentToProcess()

adorned_predicate souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::nextAdornmentToProcess ( )
inlineprivate

Pop off the next predicate adornment to process.

Definition at line 270 of file MagicSet.h.

270  {
271  assert(hasAdornmentToProcess() && "no adornment to pop");
272  auto headAdornment = *(headAdornmentsToDo.begin());
273  headAdornmentsToDo.erase(headAdornmentsToDo.begin());
274  return headAdornment;
275  }

References hasAdornmentToProcess(), and headAdornmentsToDo.

Here is the call graph for this function:

◆ queueAdornment()

void souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::queueAdornment ( const QualifiedName relName,
const std::string &  adornmentMarker 
)
inlineprivate

Add an adornment to the ToDo queue if it hasn't been processed before.

Definition at line 256 of file MagicSet.h.

256  {
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  }

References souffle::contains(), getAdornmentID(), headAdornmentsSeen, and headAdornmentsToDo.

Here is the call graph for this function:

◆ transform()

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

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

Definition at line 730 of file MagicSet.cpp.

730  : program.getRelations()) {
731  if (ioTypes.isOutput(rel) || ioTypes.isPrintSize(rel)) {
732  queueAdornment(rel->getQualifiedName(), "");
733  }
734  }
735 
736  // Keep going while there's things to adorn
737  while (hasAdornmentToProcess()) {
738  // Pop off the next head adornment to do
739  const auto& [relName, adornmentMarker] = nextAdornmentToProcess();
740 
741  // Add the adorned relation if needed
742  if (adornmentMarker != "") {
743  const auto* rel = getRelation(program, relName);
744  assert(rel != nullptr && "relation does not exist");
745 
746  auto adornedRelation = mk<Relation>(getAdornmentID(relName, adornmentMarker));
747  for (const auto* attr : rel->getAttributes()) {
748  adornedRelation->addAttribute(souffle::clone(attr));
749  }
750  program.addRelation(std::move(adornedRelation));
751  }
752 
753  // Adorn every clause correspondingly
754  for (const auto* clause : getClauses(program, relName)) {
755  if (adornmentMarker == "") {
756  redundantClauses.push_back(souffle::clone(clause));
757  }
758  auto adornedClause = adornClause(clause, adornmentMarker);
759  adornedClauses.push_back(std::move(adornedClause));
760  }
761  }
762 
763  // Swap over the redundant clauses with the adorned clauses
764  for (const auto& clause : redundantClauses) {
765  program.removeClause(clause.get());
766  }
767 
768  for (auto& clause : adornedClauses) {
769  program.addClause(souffle::clone(clause));
770  }
771 
772  return !adornedClauses.empty() || !redundantClauses.empty();
773 }
774 
775 QualifiedName NegativeLabellingTransformer::getNegativeLabel(const QualifiedName& name) {
776  QualifiedName newName(name);
777  newName.prepend("@neglabel");
778  return newName;
779 }

References rel().

Here is the call graph for this function:

Field Documentation

◆ adornedClauses

VecOwn<Clause> souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::adornedClauses
private

Definition at line 246 of file MagicSet.h.

◆ headAdornmentsSeen

std::set<QualifiedName> souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::headAdornmentsSeen
private

Definition at line 244 of file MagicSet.h.

Referenced by queueAdornment().

◆ headAdornmentsToDo

std::set<adorned_predicate> souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::headAdornmentsToDo
private

Definition at line 243 of file MagicSet.h.

Referenced by hasAdornmentToProcess(), nextAdornmentToProcess(), and queueAdornment().

◆ redundantClauses

VecOwn<Clause> souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::redundantClauses
private

Definition at line 247 of file MagicSet.h.

◆ weaklyIgnoredRelations

std::set<QualifiedName> souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::weaklyIgnoredRelations
private

Definition at line 248 of file MagicSet.h.


The documentation for this class was generated from the following files:
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::LabelDatabaseTransformer::NegativeLabellingTransformer::getNegativeLabel
static QualifiedName getNegativeLabel(const QualifiedName &name)
Provide a unique name for negatively-labelled relations.
Definition: MagicSet.cpp:781
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::AdornDatabaseTransformer::hasAdornmentToProcess
bool hasAdornmentToProcess() const
Check if any more relations need to be adorned.
Definition: MagicSet.h:265
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::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::AdornDatabaseTransformer
MagicSetTransformer::AdornDatabaseTransformer AdornDatabaseTransformer
Definition: MagicSet.cpp:62
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
souffle::as
auto as(A *x)
Helpers for dynamic_casting without having to specify redundant type qualifiers.
Definition: MiscUtil.h:157
i
size_t i
Definition: json11.h:663
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::AdornDatabaseTransformer::headAdornmentsToDo
std::set< adorned_predicate > headAdornmentsToDo
Definition: MagicSet.h:243
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: MagicSet.cpp:730
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::transform::MagicSetTransformer::AdornDatabaseTransformer::weaklyIgnoredRelations
std::set< QualifiedName > weaklyIgnoredRelations
Definition: MagicSet.h:248
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::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::which
std::string which(const std::string &name)
Simple implementation of a which tool.
Definition: FileUtil.h:104
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::adornedClauses
VecOwn< Clause > adornedClauses
Definition: MagicSet.h:246
souffle::ast::transform::MagicSetTransformer::AdornDatabaseTransformer::nextAdornmentToProcess
adorned_predicate nextAdornmentToProcess()
Pop off the next predicate adornment to process.
Definition: MagicSet.h:270
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086