souffle  2.0.2-371-g6315b36
RemoveBooleanConstraints.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2018, 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 RemoveBooleanConstraints.cpp
12  *
13  ***********************************************************************/
14 
16 #include "ast/Aggregator.h"
17 #include "ast/BinaryConstraint.h"
18 #include "ast/BooleanConstraint.h"
19 #include "ast/Clause.h"
20 #include "ast/Literal.h"
21 #include "ast/Node.h"
22 #include "ast/NumericConstant.h"
23 #include "ast/Program.h"
24 #include "ast/Relation.h"
25 #include "ast/TranslationUnit.h"
26 #include "ast/utility/NodeMapper.h"
27 #include "ast/utility/Utils.h"
28 #include "ast/utility/Visitor.h"
31 #include <algorithm>
32 #include <memory>
33 #include <utility>
34 #include <vector>
35 
36 namespace souffle::ast::transform {
37 
38 bool RemoveBooleanConstraintsTransformer::transform(TranslationUnit& translationUnit) {
39  Program& program = translationUnit.getProgram();
40 
41  // If any boolean constraints exist, they will be removed
42  bool changed = false;
43  visitDepthFirst(program, [&](const BooleanConstraint&) { changed = true; });
44 
45  // Remove true and false constant literals from all aggregators
46  struct removeBools : public NodeMapper {
47  Own<Node> operator()(Own<Node> node) const override {
48  // Remove them from child nodes
49  node->apply(*this);
50 
51  if (auto* aggr = dynamic_cast<Aggregator*>(node.get())) {
52  bool containsTrue = false;
53  bool containsFalse = false;
54 
55  // Check if aggregator body contains booleans.
56  for (Literal* lit : aggr->getBodyLiterals()) {
57  if (auto* bc = dynamic_cast<BooleanConstraint*>(lit)) {
58  if (bc->isTrue()) {
59  containsTrue = true;
60  } else {
61  containsFalse = true;
62  }
63  }
64  }
65 
66  // Only keep literals that aren't boolean constraints
67  if (containsFalse || containsTrue) {
68  auto replacementAggregator = souffle::clone(aggr);
69  VecOwn<Literal> newBody;
70 
71  bool isEmpty = true;
72 
73  // Don't bother copying over body literals if any are false
74  if (!containsFalse) {
75  for (Literal* lit : aggr->getBodyLiterals()) {
76  // Don't add in boolean constraints
77  if (!isA<BooleanConstraint>(lit)) {
78  isEmpty = false;
79  newBody.push_back(souffle::clone(lit));
80  }
81  }
82 
83  // If the body is still empty and the original body contains true add it now.
84  if (containsTrue && isEmpty) {
85  newBody.push_back(mk<BinaryConstraint>(
86  BinaryConstraintOp::EQ, mk<NumericConstant>(1), mk<NumericConstant>(1)));
87 
88  isEmpty = false;
89  }
90  }
91 
92  if (containsFalse || isEmpty) {
93  // Empty aggregator body!
94  // Not currently handled, so add in a false literal in the body
95  // E.g. max x : { } =becomes=> max 1 : {0 = 1}
96  newBody.push_back(mk<BinaryConstraint>(
97  BinaryConstraintOp::EQ, mk<NumericConstant>(0), mk<NumericConstant>(1)));
98  }
99 
100  replacementAggregator->setBody(std::move(newBody));
101  return replacementAggregator;
102  }
103  }
104 
105  // no false or true, so return the original node
106  return node;
107  }
108  };
109 
110  removeBools update;
111  program.apply(update);
112 
113  // Remove true and false constant literals from all clauses
114  for (Relation* rel : program.getRelations()) {
115  for (Clause* clause : getClauses(program, *rel)) {
116  bool containsTrue = false;
117  bool containsFalse = false;
118 
119  for (Literal* lit : clause->getBodyLiterals()) {
120  if (auto* bc = dynamic_cast<BooleanConstraint*>(lit)) {
121  bc->isTrue() ? containsTrue = true : containsFalse = true;
122  }
123  }
124 
125  if (containsFalse) {
126  // Clause will always fail
127  program.removeClause(clause);
128  } else if (containsTrue) {
129  auto replacementClause = Own<Clause>(cloneHead(clause));
130 
131  // Only keep non-'true' literals
132  for (Literal* lit : clause->getBodyLiterals()) {
133  if (!isA<BooleanConstraint>(lit)) {
134  replacementClause->addToBody(souffle::clone(lit));
135  }
136  }
137 
138  program.removeClause(clause);
139  program.addClause(std::move(replacementClause));
140  }
141  }
142  }
143 
144  return changed;
145 }
146 
147 } // namespace souffle::ast::transform
souffle::ast::cloneHead
Clause * cloneHead(const Clause *clause)
Returns a clause which contains head of the given clause.
Definition: Utils.cpp:254
BinaryConstraintOps.h
TranslationUnit.h
souffle::ast::BooleanConstraint
Boolean constraint class.
Definition: BooleanConstraint.h:45
souffle::ast::NodeMapper
An abstract class for manipulating AST Nodes by substitution.
Definition: NodeMapper.h:36
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
souffle::BinaryConstraintOp::EQ
@ EQ
MiscUtil.h
BooleanConstraint.h
Relation.h
Utils.h
NodeMapper.h
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
Literal.h
souffle::ast::Literal
Defines an abstract class for literals in a horn clause.
Definition: Literal.h:36
souffle::ast::transform
Definition: Program.h:45
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
Node.h
Aggregator.h
souffle::ast::Aggregator
Defines the aggregator class.
Definition: Aggregator.h:53
Program.h
souffle::ast::transform::RemoveBooleanConstraintsTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: RemoveBooleanConstraints.cpp:42
RemoveBooleanConstraints.h
Visitor.h
Clause.h
BinaryConstraint.h
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
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
NumericConstant.h