souffle  2.0.2-371-g6315b36
ParserUtils.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, Oracle and/or its affiliates. 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 ParserUtils.cpp
12  *
13  * Defines class RuleBody to represents rule bodies.
14  *
15  ***********************************************************************/
16 
17 #include "parser/ParserUtils.h"
18 #include "ast/Atom.h"
19 #include "ast/Clause.h"
20 #include "ast/Constraint.h"
21 #include "ast/Literal.h"
22 #include "ast/Negation.h"
23 #include "ast/Node.h"
24 #include "ast/utility/Utils.h"
28 #include <algorithm>
29 #include <memory>
30 #include <ostream>
31 #include <utility>
32 #include <vector>
33 
34 namespace souffle {
35 
36 RuleBody RuleBody::negated() const {
37  RuleBody res = getTrue();
38 
39  for (const clause& cur : dnf) {
40  RuleBody step;
41  for (const literal& lit : cur) {
42  step.dnf.push_back(clause());
43  step.dnf.back().emplace_back(literal{!lit.negated, clone(lit.atom)});
44  }
45 
46  res.conjunct(std::move(step));
47  }
48 
49  return res;
50 }
51 
52 void RuleBody::conjunct(RuleBody other) {
53  // avoid making clones if possible
54  if (dnf.size() == 1 && other.dnf.size() == 1) {
55  for (auto&& rhs : other.dnf[0]) {
56  insert(dnf[0], std::move(rhs));
57  }
58 
59  return;
60  }
61 
62  // compute the product of the disjunctions
63  std::vector<clause> res;
64 
65  for (const auto& clauseA : dnf) {
66  for (const auto& clauseB : other.dnf) {
67  clause cur;
68 
69  for (const auto& lit : clauseA) {
70  cur.emplace_back(lit.clone());
71  }
72  for (const auto& lit : clauseB) {
73  insert(cur, lit.clone());
74  }
75 
76  insert(res, std::move(cur));
77  }
78  }
79 
80  dnf = std::move(res);
81 }
82 
83 void RuleBody::disjunct(RuleBody other) {
84  // append the clauses of the other body to this body
85  for (auto& cur : other.dnf) {
86  insert(dnf, std::move(cur));
87  }
88 }
89 
91  // collect clause results
92  VecOwn<ast::Clause> bodies;
93  for (const clause& cur : dnf) {
94  bodies.push_back(mk<ast::Clause>());
95  ast::Clause& clause = *bodies.back();
96 
97  for (const literal& lit : cur) {
98  // extract literal
99  auto base = clone(lit.atom);
100  // negate if necessary
101  if (lit.negated) {
102  // negate
103  if (auto* atom = dynamic_cast<ast::Atom*>(&*base)) {
104  base.release();
105  base = mk<ast::Negation>(Own<ast::Atom>(atom));
106  base->setSrcLoc(atom->getSrcLoc());
107  } else if (auto* cstr = dynamic_cast<ast::Constraint*>(&*base)) {
109  }
110  }
111 
112  // add to result
113  clause.addToBody(std::move(base));
114  }
115  }
116 
117  // done
118  return bodies;
119 }
120 
121 // -- factory functions --
122 
123 RuleBody RuleBody::getTrue() {
124  RuleBody body;
125  body.dnf.push_back(clause());
126  return body;
127 }
128 
130  return RuleBody();
131 }
132 
134  RuleBody body;
135  body.dnf.push_back(clause());
136  body.dnf.back().emplace_back(literal{false, std::move(atom)});
137  return body;
138 }
139 
141  RuleBody body;
142  body.dnf.push_back(clause());
143  body.dnf.back().emplace_back(literal{false, std::move(constraint)});
144  return body;
145 }
146 
147 std::ostream& operator<<(std::ostream& out, const RuleBody& body) {
148  return out << join(body.dnf, ";", [](std::ostream& out, const RuleBody::clause& cur) {
149  out << join(cur, ",", [](std::ostream& out, const RuleBody::literal& l) {
150  if (l.negated) {
151  out << "!";
152  }
153  out << *l.atom;
154  });
155  });
156 }
157 
158 bool RuleBody::equal(const literal& a, const literal& b) {
159  return a.negated == b.negated && *a.atom == *b.atom;
160 }
161 
162 bool RuleBody::equal(const clause& a, const clause& b) {
163  if (a.size() != b.size()) {
164  return false;
165  }
166  for (const auto& i : a) {
167  bool found = false;
168  for (const auto& j : b) {
169  if (equal(i, j)) {
170  found = true;
171  break;
172  }
173  }
174  if (!found) {
175  return false;
176  }
177  }
178  return true;
179 }
180 
181 bool RuleBody::isSubsetOf(const clause& a, const clause& b) {
182  if (a.size() > b.size()) {
183  return false;
184  }
185  for (const auto& i : a) {
186  bool found = false;
187  for (const auto& j : b) {
188  if (equal(i, j)) {
189  found = true;
190  break;
191  }
192  }
193  if (!found) {
194  return false;
195  }
196  }
197  return true;
198 }
199 
200 void RuleBody::insert(clause& cl, literal&& lit) {
201  for (const auto& cur : cl) {
202  if (equal(cur, lit)) {
203  return;
204  }
205  }
206  cl.emplace_back(std::move(lit));
207 }
208 
209 void RuleBody::insert(std::vector<clause>& cnf, clause&& cls) {
210  for (const auto& cur : cnf) {
211  if (isSubsetOf(cur, cls)) {
212  return;
213  }
214  }
215  std::vector<clause> res;
216  for (auto& cur : cnf) {
217  if (!isSubsetOf(cls, cur)) {
218  res.push_back(std::move(cur));
219  }
220  }
221  res.swap(cnf);
222  cnf.push_back(std::move(cls));
223 }
224 
225 } // end of namespace souffle
souffle::RuleBody::disjunct
void disjunct(RuleBody other)
Definition: ParserUtils.cpp:89
souffle::RuleBody::toClauseBodies
VecOwn< ast::Clause > toClauseBodies() const
Definition: ParserUtils.cpp:96
souffle::RuleBody::conjunct
void conjunct(RuleBody other)
Definition: ParserUtils.cpp:58
souffle::RuleBody::literal::negated
bool negated
Definition: ParserUtils.h:74
souffle::RuleBody::negated
RuleBody negated() const
Definition: ParserUtils.cpp:42
souffle::RuleBody::literal
Definition: ParserUtils.h:70
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
MiscUtil.h
souffle::ast::Clause
Intermediate representation of a horn clause.
Definition: Clause.h:51
base
T & base
Definition: Reader.h:60
Constraint.h
souffle::RuleBody::getFalse
static RuleBody getFalse()
Definition: ParserUtils.cpp:135
rhs
Own< Argument > rhs
Definition: ResolveAliases.cpp:185
souffle::ast::Atom
An atom class.
Definition: Atom.h:51
j
var j
Definition: htmlJsChartistMin.h:15
Utils.h
ParserUtils.h
souffle::ast::analysis::Constraint
A generic base class for constraints on variables.
Definition: ConstraintSystem.h:44
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
i
size_t i
Definition: json11.h:663
ContainerUtil.h
souffle::RuleBody::atom
static RuleBody atom(Own< ast::Atom > atom)
Definition: ParserUtils.cpp:139
souffle::join
detail::joined_sequence< Iter, Printer > join(const Iter &a, const Iter &b, const std::string &sep, const Printer &p)
Creates an object to be forwarded to some output stream for printing sequences of elements interspers...
Definition: StreamUtil.h:175
Atom.h
Literal.h
Negation.h
souffle::RuleBody::RuleBody
RuleBody()=default
souffle::RuleBody::insert
static void insert(clause &cl, literal &&lit)
Definition: ParserUtils.cpp:206
Node.h
souffle::operator<<
std::ostream & operator<<(std::ostream &os, AggregateOp op)
Definition: AggregateOp.h:51
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
souffle::RuleBody::clause
std::vector< literal > clause
Definition: ParserUtils.h:84
StreamUtil.h
souffle::RuleBody::constraint
static RuleBody constraint(Own< ast::Constraint > constraint)
Definition: ParserUtils.cpp:146
souffle::ast::negateConstraintInPlace
void negateConstraintInPlace(Constraint &constraint)
Negate an ast constraint.
Definition: Utils.cpp:297
souffle::RuleBody::getTrue
static RuleBody getTrue()
Definition: ParserUtils.cpp:129
Clause.h
souffle
Definition: AggregateOp.h:25
souffle::RuleBody
Definition: ParserUtils.h:36
souffle::RuleBody::dnf
std::vector< clause > dnf
Definition: ParserUtils.h:86
souffle::VecOwn
std::vector< Own< A > > VecOwn
Definition: ContainerUtil.h:45