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

Replaces literals containing single-valued aggregates with a synthesised relation. More...

#include <MaterializeSingletonAggregation.h>

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

Public Member Functions

MaterializeSingletonAggregationTransformerclone () 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

void groundInjectedParameters (const TranslationUnit &translationUnit, Clause &aggClause, const Clause &originalClause)
 Modify the aggClause by adding in grounding literals for every variable that appears in the clause ungrounded. More...
 
bool transform (TranslationUnit &translationUnit) override
 

Static Private Member Functions

static bool isSingleValued (const TranslationUnit &tu, const Aggregator &agg, const Clause &clause)
 Determines whether an aggregate is single-valued, ie the aggregate does not depend on the outer scope. More...
 

Detailed Description

Replaces literals containing single-valued aggregates with a synthesised relation.

Definition at line 40 of file MaterializeSingletonAggregation.h.

Member Function Documentation

◆ clone()

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

◆ getName()

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

◆ groundInjectedParameters()

void souffle::ast::transform::MaterializeSingletonAggregationTransformer::groundInjectedParameters ( const TranslationUnit translationUnit,
Clause aggClause,
const Clause originalClause 
)
private

Modify the aggClause by adding in grounding literals for every variable that appears in the clause ungrounded.

The source of literals to copy from is the originalClause.

◆ isSingleValued()

bool souffle::ast::transform::MaterializeSingletonAggregationTransformer::isSingleValued ( const TranslationUnit tu,
const Aggregator agg,
const Clause clause 
)
staticprivate

Determines whether an aggregate is single-valued, ie the aggregate does not depend on the outer scope.

Definition at line 141 of file MaterializeSingletonAggregation.cpp.

◆ transform()

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

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

Definition at line 49 of file MaterializeSingletonAggregation.cpp.

52  {
53  visitDepthFirst(agg, [&](const Aggregator& innerAgg) {
54  if (agg != innerAgg) {
55  innerAggregates.insert(&innerAgg);
56  }
57  });
58  });
59 
60  // collect references to clause / aggregate pairs
61  visitDepthFirst(program, [&](const Clause& clause) {
62  visitDepthFirst(clause, [&](const Aggregator& agg) {
63  // only unroll one level at a time
64  if (innerAggregates.find(&agg) != innerAggregates.end()) {
65  return;
66  }
67  // if the aggregate isn't single valued
68  // (ie it relies on a grounding from the outer scope)
69  // or it's a constituent of the only atom in the clause,
70  // then there's no point materialising it!
71  if (!isSingleValued(translationUnit, agg, clause) || clause.getBodyLiterals().size() == 1) {
72  return;
73  }
74  auto* foundAggregate = const_cast<Aggregator*>(&agg);
75  auto* foundClause = const_cast<Clause*>(&clause);
76  pairs.insert(std::make_pair(foundAggregate, foundClause));
77  });
78  });
79  for (auto pair : pairs) {
80  // Clone the aggregate that we're going to be deleting.
81  auto aggregate = souffle::clone(pair.first);
82  Clause* clause = pair.second;
83  // synthesise an aggregate relation
84  // __agg_rel_0()
85  auto aggRel = mk<Relation>();
86  auto aggHead = mk<Atom>();
87  auto aggClause = mk<Clause>();
88 
89  std::string aggRelName = analysis::findUniqueRelationName(program, "__agg");
90  aggRel->setQualifiedName(aggRelName);
91  aggHead->setQualifiedName(aggRelName);
92 
93  // create a synthesised variable to replace the aggregate term!
94  std::string variableName = analysis::findUniqueVariableName(*clause, "z");
95  auto variable = mk<ast::Variable>(variableName);
96 
97  // __agg_rel_0(z) :- ...
98  aggHead->addArgument(souffle::clone(variable));
99  aggRel->addAttribute(mk<Attribute>(variableName, "number"));
100  aggClause->setHead(souffle::clone(aggHead));
101 
102  // A(x) :- x = sum .., B(x).
103  // -> A(x) :- x = z, B(x), __agg_rel_0(z).
104  auto equalityLiteral = mk<BinaryConstraint>(
105  BinaryConstraintOp::EQ, souffle::clone(variable), souffle::clone(aggregate));
106  // __agg_rel_0(z) :- z = sum ...
107  aggClause->addToBody(std::move(equalityLiteral));
108  program.addRelation(std::move(aggRel));
109  program.addClause(std::move(aggClause));
110 
111  // the only thing left to do is just replace the aggregate terms in the original
112  // clause with the synthesised variable
113  struct replaceAggregate : public NodeMapper {
114  const Aggregator& aggregate;
115  const Own<ast::Variable> variable;
116  replaceAggregate(const Aggregator& aggregate, Own<ast::Variable> variable)
117  : aggregate(aggregate), variable(std::move(variable)) {}
118  Own<Node> operator()(Own<Node> node) const override {
119  if (auto* current = dynamic_cast<Aggregator*>(node.get())) {
120  if (*current == aggregate) {
121  auto replacement = souffle::clone(variable);
122  assert(replacement != nullptr);
123  return replacement;
124  }
125  }
126  node->apply(*this);
127  return node;
128  }
129  };
130  replaceAggregate update(*aggregate, std::move(variable));
131  clause->apply(update);
132  clause->addToBody(std::move(aggHead));
133  }
134  return pairs.size() > 0;
135 }
136 
138  const TranslationUnit& tu, const Aggregator& agg, const Clause& clause) {
139  // An aggregate is single valued as long as it is not complex.

References souffle::ast::visitDepthFirst().

Here is the call graph for this function:

The documentation for this class was generated from the following files:
souffle::BinaryConstraintOp::EQ
@ EQ
souffle::ast::transform::MaterializeSingletonAggregationTransformer::isSingleValued
static bool isSingleValued(const TranslationUnit &tu, const Aggregator &agg, const Clause &clause)
Determines whether an aggregate is single-valued, ie the aggregate does not depend on the outer scope...
Definition: MaterializeSingletonAggregation.cpp:141
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
souffle::ast::analysis::findUniqueRelationName
std::string findUniqueRelationName(const Program &program, std::string base)
Find a new relation name.
Definition: Aggregate.cpp:190
std
Definition: Brie.h:3053
souffle::ast::analysis::findUniqueVariableName
std::string findUniqueVariableName(const Clause &clause, std::string base)
Find a variable name using base to form a string like base1 Use this when you need to limit the scope...
Definition: Aggregate.cpp:179
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