SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
Bitvector.cpp
Go to the documentation of this file.
1 #include "Bitvector.h"
2 #include "ParserState.h"
3 #include "Conversions.h"
4 #include "FunctionInstantiator.h"
5 
6 #define BOOST_SPIRIT_USE_PHOENIX_V3
7 #include <boost/spirit/include/qi.hpp>
8 
9 namespace smtrat {
10 namespace parser {
11 
13  bool operator()(const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) const {
14  std::vector<types::BVTerm> args;
15  if (!convert(arguments, args)) {
16  errors.next() << "Failed to convert arguments.";
17  return false;
18  }
19  return apply(args, result, errors);
20  }
21  virtual bool apply(const std::vector<types::BVTerm>& arguments, types::TermType& result, TheoryError& errors) const = 0;
22  };
24  bool operator()(const std::vector<std::size_t>& indices, const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) const {
25  std::vector<types::BVTerm> args;
26  if (!convert(arguments, args)) {
27  errors.next() << "Failed to convert arguments.";
28  return false;
29  }
30  return apply(indices, args, result, errors);
31  }
32  virtual bool apply(const std::vector<std::size_t>& indices, const std::vector<types::BVTerm>& arguments, types::TermType& result, TheoryError& errors) const = 0;
33  };
34  template<carl::BVTermType type>
36  bool apply(const std::vector<types::BVTerm>& arguments, types::TermType& result, TheoryError& errors) const {
37  if (arguments.size() != 1) {
38  errors.next() << "The operator \"" << type << "\" expects exactly one argument.";
39  return false;
40  }
41  result = types::BVTerm(type, arguments[0]);
42  return true;
43  }
44  };
45  template<carl::BVTermType type>
47  bool apply(const std::vector<types::BVTerm>& arguments, types::TermType& result, TheoryError& errors) const {
48  if (arguments.size() != 2) {
49  errors.next() << "The operator \"" << type << "\" expects exactly two arguments.";
50  return false;
51  }
52  result = types::BVTerm(type, arguments[0], arguments[1]);
53  return true;
54  }
55  };
56  template<carl::BVCompareRelation type>
58  bool apply(const std::vector<types::BVTerm>& arguments, types::TermType& result, TheoryError& errors) const {
59  if (arguments.size() != 2) {
60  errors.next() << "The operator \"" << type << "\" expects exactly two arguments.";
61  return false;
62  }
63  result = FormulaT(types::BVConstraint::create(type, arguments[0], arguments[1]));
64  return true;
65  }
66  };
67  template<carl::BVTermType type>
69  bool apply(const std::vector<std::size_t>& indices, const std::vector<types::BVTerm>& arguments, types::TermType& result, TheoryError& errors) const {
70  if (arguments.size() != 1) {
71  errors.next() << "The operator \"" << type << "\" expects exactly one argument.";
72  return false;
73  }
74  if (indices.size() != 1) {
75  errors.next() << "The operator \"" << type << "\" expects exactly one index.";
76  return false;
77  }
78  result = types::BVTerm(type, arguments[0], indices[0]);
79  return true;
80  }
81  };
83  bool apply(const std::vector<std::size_t>& indices, const std::vector<types::BVTerm>& arguments, types::TermType& result, TheoryError& errors) const {
84  if (arguments.size() != 1) {
85  errors.next() << "The operator \"extract\" expects exactly one argument.";
86  return false;
87  }
88  if (indices.size() != 2) {
89  errors.next() << "The operator \"extract\" expects exactly two indices.";
90  return false;
91  }
92  result = types::BVTerm(carl::BVTermType::EXTRACT, arguments[0], indices[0], indices[1]);
93  return true;
94  }
95  };
96 
97  void BitvectorTheory::addSimpleSorts(qi::symbols<char, carl::Sort>& sorts) {
98  carl::SortManager& sm = carl::SortManager::getInstance();
99  sorts.add("BitVec", sm.getInterpreted(carl::VariableType::VT_BOOL));
100  }
101 
103  carl::SortManager& sm = carl::SortManager::getInstance();
104  this->bvSort = sm.addSort("BitVec", carl::VariableType::VT_UNINTERPRETED);
105  sm.makeSortIndexable(this->bvSort, 1, carl::VariableType::VT_BITVECTOR);
106 
109 
112 
132 
138 
147  }
148 
149  bool BitvectorTheory::declareVariable(const std::string& name, const carl::Sort& sort, types::VariableType& result, TheoryError& errors) {
150  carl::SortManager& sm = carl::SortManager::getInstance();
151  switch (sm.getType(sort)) {
152  case carl::VariableType::VT_BITVECTOR: {
153  assert(state->isSymbolFree(name));
154  if ((sm.getIndices(sort) == nullptr) || (sm.getIndices(sort)->size() != 1)) {
155  errors.next() << "The sort \"" << sort << "\" should have a single index, being the bit size.";
156  return false;
157  }
158  carl::Variable v = carl::fresh_variable(name, carl::VariableType::VT_BITVECTOR);
160  state->variables[name] = bvv;
161  result = bvv;
162  return true;
163  }
164  default:
165  errors.next() << "The requested sort is not a bitvector sort but \"" << sort << "\".";
166  return false;
167  }
168  }
169 
170  struct BitvectorConstantParser: public qi::grammar<std::string::const_iterator, Integer()> {
171  BitvectorConstantParser(): BitvectorConstantParser::base_type(main, "bitvector literal") {
172  main = "bv" > number;
173  }
174  qi::uint_parser<Integer,10,1,-1> number;
175  qi::rule<std::string::const_iterator, Integer()> main;
176  };
177 
179  Integer integer;
180  const std::string& s = identifier.symbol;
181  if (qi::parse(s.begin(), s.end(), BitvectorConstantParser(), integer)) {
182  if (identifier.indices == nullptr) {
183  errors.next() << "Found a possible bitvector symbol \"" << identifier << "\" but no bit size was specified.";
184  return false;
185  }
186  if (identifier.indices->size() != 1) {
187  errors.next() << "Found a possible bitvector symbol \"" << identifier << "\" but did not find a single index specifying the bit size.";
188  return false;
189  }
190  std::size_t bitsize = identifier.indices->at(0);
191  carl::BVValue value(bitsize, integer);
192  result = types::BVTerm(carl::BVTermType::CONSTANT, value);
193  return true;
194  }
195  return false;
196  }
197 
198  bool BitvectorTheory::handleITE(const FormulaT& ifterm, const types::TermType& thenterm, const types::TermType& elseterm, types::TermType& result, TheoryError& errors) {
199  types::BVTerm thent;
200  types::BVTerm elset;
201  if (!termConverter(thenterm, thent)) {
202  errors.next() << "Failed to construct ITE, the then-term \"" << thenterm << "\" is unsupported.";
203  return false;
204  }
205  if (!termConverter(elseterm, elset)) {
206  errors.next() << "Failed to construct ITE, the else-term \"" << elseterm << "\" is unsupported.";
207  return false;
208  }
209  if (thent.width() != elset.width()) {
210  errors.next() << "Failed to construct ITE, the then-term \"" << thent << "\" and the else-term \"" << elset << "\" have different widths.";
211  return false;
212  }
213  if (ifterm.is_true()) { result = thent; return true; }
214  if (ifterm.is_false()) { result = elset; return true; }
215  carl::SortManager& sm = carl::SortManager::getInstance();
216  carl::Variable var = carl::fresh_variable(carl::VariableType::VT_BITVECTOR);
217  state->artificialVariables.emplace_back(var);
218  carl::BVVariable bvvar(var, sm.index(this->bvSort, {thent.width()}));
219  state->auxiliary_variables.insert(bvvar);
220  types::BVTerm vart = types::BVTerm(carl::BVTermType::VARIABLE, bvvar);
221 
222  FormulaT consThen = FormulaT(types::BVConstraint::create(carl::BVCompareRelation::EQ, vart, thent));
223  FormulaT consElse = FormulaT(types::BVConstraint::create(carl::BVCompareRelation::EQ, vart, elset));
224 
225  state->global_formulas.emplace_back(FormulaT(carl::FormulaType::IMPLIES, {ifterm, consThen}));
226  state->global_formulas.emplace_back(FormulaT(carl::FormulaType::IMPLIES, {!ifterm, consElse}));
227  result = vart;
228  return true;
229  }
230  bool BitvectorTheory::handleDistinct(const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) {
231  std::vector<carl::BVTerm> args;
232  if (!vectorConverter(arguments, args, errors)) return false;
233  result = expandDistinct(args, [](const carl::BVTerm& a, const carl::BVTerm& b){
234  return FormulaT(carl::BVConstraint::create(carl::BVCompareRelation::NEQ, a, b));
235  });
236  return true;
237  }
238 
242  if (!c(var, v)) {
243  errors.next() << "The variable is not a bitvector variable.";
244  return false;
245  }
246  carl::BVTerm repl;
247  if (!termConverter(replacement, repl)) {
248  errors.next() << "Could not convert argument \"" << replacement << "\" to a bitvector term.";
249  return false;
250  }
252  return instantiator.instantiate(v, repl, subject);
253  }
257  if (!c(var, v)) {
258  errors.next() << "The variable is not a bitvector variable.";
259  return false;
260  }
261  subject = carl::BVVariable(carl::fresh_variable(carl::VariableType::VT_BITVECTOR), v.sort());
262  return true;
263 
264  }
265  bool BitvectorTheory::functionCall(const Identifier& identifier, const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) {
266  if (identifier.symbol == "=") {
267  if (arguments.size() == 2) {
268  std::vector<types::BVTerm> args;
269  if (!vectorConverter(arguments, args, errors)) return false;
270  result = FormulaT(types::BVConstraint::create(carl::BVCompareRelation::EQ, args[0], args[1]));
271  return true;
272  }
273  errors.next() << "Operator \"" << identifier << "\" expects exactly two arguments, but got " << arguments.size() << ".";
274  return false;
275  }
276  errors.next() << "Invalid operator \"" << identifier << "\".";
277  return false;
278  }
279 
280 }
281 }
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:67
int var(Lit p)
Definition: SolverTypes.h:64
carl::BVVariable BVVariable
Definition: TheoryTypes.h:78
carl::mpl_variant_of< TermTypes >::type TermType
Variant type for all terms.
Definition: TheoryTypes.h:160
carl::BVTerm BVTerm
Typedef for bitvector term.
Definition: TheoryTypes.h:77
carl::mpl_variant_of< VariableTypes >::type VariableType
Variant type for all variables.
Definition: TheoryTypes.h:132
QuantifierType type(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Definition: QEQuery.h:39
Class to create the formulas for axioms.
carl::Formula< Poly > FormulaT
Definition: types.h:37
carl::IntegralType< Rational >::type Integer
Definition: types.h:21
Base class for all theories.
FormulaT expandDistinct(const std::vector< T > &values, const Builder &neqBuilder)
bool apply(const std::vector< types::BVTerm > &arguments, types::TermType &result, TheoryError &errors) const
Definition: Bitvector.cpp:47
qi::uint_parser< Integer, 10, 1,-1 > number
Definition: Bitvector.cpp:174
qi::rule< std::string::const_iterator, Integer()> main
Definition: Bitvector.cpp:175
virtual bool apply(const std::vector< types::BVTerm > &arguments, types::TermType &result, TheoryError &errors) const =0
bool operator()(const std::vector< types::TermType > &arguments, types::TermType &result, TheoryError &errors) const
Definition: Bitvector.cpp:13
bool apply(const std::vector< types::BVTerm > &arguments, types::TermType &result, TheoryError &errors) const
Definition: Bitvector.cpp:58
bool handleITE(const FormulaT &ifterm, const types::TermType &thenterm, const types::TermType &elseterm, types::TermType &result, TheoryError &errors)
Resolve an if-then-else operator.
Definition: Bitvector.cpp:198
bool resolveSymbol(const Identifier &identifier, types::TermType &result, TheoryError &errors)
Resolve a symbol that was not declared within the ParserState.
Definition: Bitvector.cpp:178
bool handleDistinct(const std::vector< types::TermType > &arguments, types::TermType &result, TheoryError &errors)
Resolve a distinct operator.
Definition: Bitvector.cpp:230
conversion::VectorVariantConverter< types::BVTerm > vectorConverter
Definition: Bitvector.h:15
BitvectorTheory(ParserState *state)
Definition: Bitvector.cpp:102
bool refreshVariable(const types::VariableType &var, types::VariableType &subject, TheoryError &errors)
Definition: Bitvector.cpp:254
bool declareVariable(const std::string &name, const carl::Sort &sort, types::VariableType &result, TheoryError &errors)
Declare a new variable with the given name and the given sort.
Definition: Bitvector.cpp:149
conversion::VariantConverter< types::BVTerm > termConverter
Definition: Bitvector.h:16
bool instantiate(const types::VariableType &var, const types::TermType &replacement, types::TermType &subject, TheoryError &errors)
Instantiate a variable within a term.
Definition: Bitvector.cpp:239
static void addSimpleSorts(qi::symbols< char, carl::Sort > &sorts)
Definition: Bitvector.cpp:97
bool functionCall(const Identifier &identifier, const std::vector< types::TermType > &arguments, types::TermType &result, TheoryError &errors)
Resolve another unknown function call.
Definition: Bitvector.cpp:265
bool apply(const std::vector< std::size_t > &indices, const std::vector< types::BVTerm > &arguments, types::TermType &result, TheoryError &errors) const
Definition: Bitvector.cpp:83
bool convert(const std::vector< types::TermType > &from, std::vector< T > &to) const
std::string symbol
Definition: Common.h:37
std::vector< std::size_t > * indices
Definition: Common.h:38
virtual bool apply(const std::vector< std::size_t > &indices, const std::vector< types::BVTerm > &arguments, types::TermType &result, TheoryError &errors) const =0
bool operator()(const std::vector< std::size_t > &indices, const std::vector< types::TermType > &arguments, types::TermType &result, TheoryError &errors) const
Definition: Bitvector.cpp:24
bool convert(const std::vector< types::TermType > &from, std::vector< T > &to) const
bool instantiate(V v, const T &repl, types::TermType &subject)
void registerFunction(const std::string &name, const FunctionInstantiator *fi)
Definition: ParserState.h:163
bool isSymbolFree(const std::string &name, bool output=true)
Definition: ParserState.h:129
std::map< std::string, types::VariableType > variables
Definition: ParserState.h:66
std::set< types::VariableType > auxiliary_variables
Definition: ParserState.h:63
std::vector< smtrat::ModelVariable > artificialVariables
Definition: ParserState.h:72
bool apply(const std::vector< std::size_t > &indices, const std::vector< types::BVTerm > &arguments, types::TermType &result, TheoryError &errors) const
Definition: Bitvector.cpp:69
TheoryError & next()
Definition: Common.h:25
bool apply(const std::vector< types::BVTerm > &arguments, types::TermType &result, TheoryError &errors) const
Definition: Bitvector.cpp:36
Converts variants to some type using the Converter class.
Definition: Conversions.h:99