SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
Theories.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "Attribute.h"
4 #include "Common.h"
5 #include "TheoryTypes.h"
6 #include "AbstractTheory.h"
7 #include "ParserState.h"
8 #include "Core.h"
9 #include "Arithmetic.h"
10 #ifdef PARSER_ENABLE_BITVECTOR
11 #include "Bitvector.h"
12 #endif
13 #ifdef PARSER_ENABLE_UNINTERPRETED
14 #include "Uninterpreted.h"
15 #endif
16 #include "BooleanEncoding.h"
17 
18 #include "../ParserSettings.h"
19 
20 #include <boost/mpl/for_each.hpp>
21 
22 namespace smtrat {
23 namespace parser {
24 
25 /**
26  * The Theories class combines all implemented theories and provides a single interface to interact with all theories at once.
27  */
28 struct Theories {
29 
30  typedef boost::mpl::vector<
31  CoreTheory*
32 #ifdef PARSER_ENABLE_ARITHMETIC
34 #endif
35 #ifdef PARSER_ENABLE_BITVECTOR
37 #endif
38 #ifdef PARSER_ENABLE_UNINTERPRETED
40 #endif
43 
44 
46  state(state),
47  theories()
48  {
49  theories.emplace("Core", new CoreTheory(state));
50 #ifdef PARSER_ENABLE_ARITHMETIC
51  theories.emplace("Arithmetic", new ArithmeticTheory(state));
52 #endif
53 #ifdef PARSER_ENABLE_BITVECTOR
54  theories.emplace("Bitvector", new BitvectorTheory(state));
55 #endif
56 #ifdef PARSER_ENABLE_UNINTERPRETED
57  theories.emplace("Uninterpreted", new UninterpretedTheory(state));
58 #endif
59  theories.emplace("BooleanEncoding", new BooleanEncodingTheory(state));
60  }
62  auto it = theories.begin();
63  while (it != theories.end()) {
64  delete it->second;
65  it = theories.erase(it);
66  }
67  }
68 
69  /**
70  * Helper functor for addConstants() method.
71  */
72  struct ConstantAdder {
73  qi::symbols<char, types::ConstType>& constants;
74  ConstantAdder(qi::symbols<char, types::ConstType>& constants): constants(constants) {}
75  template<typename T> void operator()(T*) {
76  T::addConstants(constants);
77  }
78  };
79  /**
80  * Collects constants from all theory modules.
81  */
82  static void addConstants(qi::symbols<char, types::ConstType>& constants) {
83  boost::mpl::for_each<Modules>(ConstantAdder(constants));
84  }
85 
86  /**
87  * Helper functor for addSimpleSorts() method.
88  */
89  struct SimpleSortAdder {
90  qi::symbols<char, carl::Sort>& sorts;
91  SimpleSortAdder(qi::symbols<char, carl::Sort>& sorts): sorts(sorts) {}
92  template<typename T> void operator()(T*) {
93  T::addSimpleSorts(sorts);
94  }
95  };
96  /**
97  * Collects simple sorts from all theory modules.
98  */
99  static void addSimpleSorts(qi::symbols<char, carl::Sort>& sorts) {
100  boost::mpl::for_each<Modules>(SimpleSortAdder(sorts));
101  }
102 
103  void addGlobalFormulas(FormulasT& formulas) {
104  SMTRAT_LOG_DEBUG("smtrat.parser", "Adding global formulas to formula set: " << state->global_formulas);
105  formulas.insert(formulas.end(), state->global_formulas.begin(), state->global_formulas.end());
106  state->global_formulas.clear();
107  }
108  void declareVariable(const std::string& name, const carl::Sort& sort) {
109  if (state->isSymbolFree(name)) {
111  TheoryError te;
112  for (auto& t: theories) {
113  if (t.second->declareVariable(name, sort, var, te(t.first))) return;
114  }
115  SMTRAT_LOG_ERROR("smtrat.parser", "Variable \"" << name << "\" was declared with an invalid sort \"" << sort << "\":" << te);
117  } else {
118  SMTRAT_LOG_ERROR("smtrat.parser", "Variable \"" << name << "\" will not be declared due to a name clash.");
120  }
121  }
122  void declareFunction(const std::string& name, const std::vector<carl::Sort>& args, const carl::Sort& sort) {
123  if (state->isSymbolFree(name)) {
124  std::vector<carl::Sort> our_args(args);
125  for (auto& a: our_args) {
126  if (carl::SortManager::getInstance().getType(a) == carl::VariableType::VT_BOOL) {
127  a = carl::SortManager::getInstance().getSort("UF_Bool");
128  }
129  }
130  if (carl::SortManager::getInstance().getType(sort) == carl::VariableType::VT_BOOL) {
131  state->declared_functions[name] = carl::newUninterpretedFunction(name, our_args, carl::SortManager::getInstance().getSort("UF_Bool"));
132  } else {
133  state->declared_functions[name] = carl::newUninterpretedFunction(name, our_args, sort);
134  }
135  } else {
136  SMTRAT_LOG_ERROR("smtrat.parser", "Function \"" << name << "\" will not be declared due to a name clash.");
138  }
139  }
140 
141  types::VariableType declareFunctionArgument(const std::pair<std::string, carl::Sort>& arg) {
142  if (state->isSymbolFree(arg.first)) {
143  TheoryError te;
145  for (auto& t: theories) {
146  if (t.second->declareVariable(arg.first, arg.second, result, te(t.first))) return result;
147  }
148  SMTRAT_LOG_ERROR("smtrat.parser", "Function argument \"" << arg.first << "\" could not be declared:" << te);
150  } else {
151  SMTRAT_LOG_ERROR("smtrat.parser", "Function argument \"" << arg.first << "\" will not be declared due to a name clash.");
153  }
154  return types::VariableType(carl::Variable::NO_VARIABLE);
155  }
156 
157  void defineFunction(const std::string& name, const std::vector<types::VariableType>& arguments, const carl::Sort& sort, const types::TermType& definition) {
158  if (state->isSymbolFree(name)) {
159  ///@todo check that definition matches the sort
160  if (arguments.size() == 0) {
161  state->constants.emplace(name, definition);
162  } else {
163  SMTRAT_LOG_DEBUG("smtrat.parser", "Defining function \"" << name << "\" as \"" << definition << "\".");
164  auto ufi = new UserFunctionInstantiator(arguments, sort, definition, state->auxiliary_variables);
165  addGlobalFormulas(ufi->globalFormulas);
166  state->registerFunction(name, ufi);
167  }
168  } else {
169  SMTRAT_LOG_ERROR("smtrat.parser", "Function \"" << name << "\" will not be defined due to a name clash.");
171  }
172  }
173 
174  types::TermType resolveSymbol(const Identifier& identifier) const {
175  SMTRAT_LOG_DEBUG("smtrat.parser", "Resolving symbol \"" << identifier << "\".");
177  if (settings_parser().disable_theory) return result;
178  if (identifier.indices == nullptr) {
179  if (state->resolveSymbol(identifier.symbol, result)) return result;
180  }
181  TheoryError te;
182  for (auto& t: theories) {
183  if (t.second->resolveSymbol(identifier, result, te(t.first))) return result;
184  }
185  SMTRAT_LOG_ERROR("smtrat.parser", "Tried to resolve symbol \"" << identifier << "\" which is unknown." << te);
187  return types::TermType();
188  }
189 
190  types::VariableType resolveVariable(const Identifier& identifier) const {
192  if (settings_parser().disable_theory) return result;
193  if (identifier.indices == nullptr) {
194  if (state->resolveSymbol(identifier.symbol, result)) return result;
195  }
197  return types::VariableType();
198  }
199 
200  void pushExpressionScope(std::size_t n) {
201  for (; n > 0; n--) state->pushExpressionScope();
202  }
203  void popExpressionScope(std::size_t n) {
204  for (; n > 0; n--) state->popExpressionScope();
205  }
206  void pushScriptScope(std::size_t n) {
207  for (; n > 0; n--) state->pushScriptScope();
208  }
209  void popScriptScope(std::size_t n) {
210  for (; n > 0; n--) state->popScriptScope();
211  }
212 
213  const auto& annotateTerm(const types::TermType& term, const std::vector<Attribute>& attributes) {
214  if (settings_parser().disable_theory) return term;
215  FormulaT subject;
217  if (!converter(term, subject)) {
218  SMTRAT_LOG_WARN("smtrat.parser", "Ignoring annotation on unsupported expression. We only annotated formulas.");
219  return term;
220  }
221  for (const auto& attr: attributes) {
222  if (attr.key == "named") {
223  if (carl::variant_is_type<std::string>(attr.value)) {
224  const std::string& value = boost::get<std::string>(attr.value);
225  SMTRAT_LOG_DEBUG("smtrat.parser", "Naming term: " << value << " = " << term);
226  state->handler.annotateName(subject, value);
227  } else {
228  SMTRAT_LOG_WARN("smtrat.parser", "Ignoring naming with unsupported value type for term " << term);
229  }
230  } else {
231  SMTRAT_LOG_WARN("smtrat.parser", "Ignoring unsupported annotation " << attr << " for term " << term);
232  }
233  }
234  return term;
235  }
236 
237  void handleLet(const std::string& symbol, const types::TermType& term) {
238  if (settings_parser().disable_theory) return;
239  state->bindings.emplace(symbol, term);
240  }
241 
242  types::TermType handleITE(const std::vector<types::TermType>& arguments) {
243  if (settings_parser().disable_theory) return FormulaT();
245  if (arguments.size() != 3) {
246  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to construct ITE expression, only exactly three arguments are allowed, but \"" << arguments << "\" were given.");
248  return result;
249  }
250  FormulaT ifterm;
252  if (!converter(arguments[0], ifterm)) {
253  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to construct ITE expression, the first argument must be a formula, but \"" << arguments[0] << "\" was given.");
255  return result;
256  }
257  if (ifterm.is_true()) return arguments[1];
258  if (ifterm.is_false()) return arguments[2];
259  TheoryError te;
260  for (auto& t: theories) {
261  if (t.second->handleITE(ifterm, arguments[1], arguments[2], result, te(t.first))) return result;
262  }
263  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to construct ITE \"" << ifterm << "\" ? \"" << arguments[1] << "\" : \"" << arguments[2] << "\": " << te);
265  return result;
266  }
267 
268  types::TermType handleDistinct(const std::vector<types::TermType>& arguments) {
269  if (settings_parser().disable_theory) return FormulaT();
271  TheoryError te;
272  for (auto& t: theories) {
273  if (t.second->handleDistinct(arguments, result, te(t.first))) return result;
274  }
275  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to construct distinct for \"" << arguments << "\": " << te);
277  return result;
278  }
279 
280  bool instantiate(const UserFunctionInstantiator& function, const types::VariableType& var, const types::TermType& repl, types::TermType& subject) {
281  if (settings_parser().disable_theory) return true;
282  TheoryError errors;
283  bool wasInstantiated = false;
284  for (auto& t: theories) {
285  if (t.second->instantiate(var, repl, subject, errors(t.first))) {
286  for (const auto& f: function.globalFormulas) {
287  types::TermType tmp = f;
288  bool res = t.second->instantiate(var, repl, tmp, errors);
289  assert(res);
290  state->global_formulas.push_back(boost::get<FormulaT>(tmp));
291  }
292  wasInstantiated = true;
293  break;
294  }
295  }
296  if (!wasInstantiated) {
297  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to instantiate function: " << errors);
299  return false;
300  }
301  return true;
302  }
303 
304  bool instantiateUserFunction(const UserFunctionInstantiator& function, const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) {
305  if (settings_parser().disable_theory) {
306  result = FormulaT();
307  return true;
308  }
309  if (function.arguments.size() != arguments.size()) {
310  errors.next() << "Function was expected to have " << function.arguments.size() << " arguments, but was instantiated with " << arguments.size() << ".";
311  return false;
312  }
313  result = function.definition;
314  for (const auto& aux: function.auxiliaries) {
315  TheoryError te;
316  bool wasRefreshed = false;
317  types::VariableType repl;
318  for (auto& t: theories) {
319  if (t.second->refreshVariable(aux, repl, te(t.first))) {
320  wasRefreshed = true;
321  break;
322  }
323  }
324  if (!wasRefreshed) {
325  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to refresh auxiliary variable \"" << aux << "\": " << te);
327  return false;
328  }
329  if (!instantiate(function, aux, repl, result)) return false;
330  }
331  for (std::size_t i = 0; i < arguments.size(); i++) {
332  if (!instantiate(function, function.arguments[i], arguments[i], result)) return false;
333  }
334  return true;
335  }
336 
337  types::TermType functionCall(const Identifier& identifier, const std::vector<types::TermType>& arguments) {
338  if (settings_parser().disable_theory) return FormulaT();
340  TheoryError te;
341  if (identifier.symbol == "ite") {
342  if (identifier.indices != nullptr) {
343  SMTRAT_LOG_ERROR("smtrat.parser", "The function \"" << identifier << "\" should not have indices.");
345  return result;
346  }
347  return handleITE(arguments);
348  } else if (identifier.symbol == "distinct") {
349  if (identifier.indices != nullptr) {
350  SMTRAT_LOG_ERROR("smtrat.parser", "The function \"" << identifier << "\" should not have indices.");
352  return result;
353  }
354  return handleDistinct(arguments);
355  }
356  auto deffunit = state->defined_functions.find(identifier.symbol);
357  if (deffunit != state->defined_functions.end()) {
358  if (identifier.indices != nullptr) {
359  SMTRAT_LOG_ERROR("smtrat.parser", "The function \"" << identifier << "\" should not have indices.");
361  return result;
362  }
363  SMTRAT_LOG_DEBUG("smtrat.parser", "Trying to call function \"" << identifier << "\" with arguments " << arguments << ".");
364  if ((*deffunit->second)(arguments, result, te(identifier.symbol))) {
365  SMTRAT_LOG_DEBUG("smtrat.parser", "Success, result is \"" << result << "\".");
366  return result;
367  }
368  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to call function \"" << identifier << "\" with arguments " << arguments << ":" << te);
370  return result;
371  }
372  auto ideffunit = state->defined_indexed_functions.find(identifier.symbol);
373  if (ideffunit != state->defined_indexed_functions.end()) {
374  if (identifier.indices == nullptr) {
375  SMTRAT_LOG_ERROR("smtrat.parser", "The function \"" << identifier << "\" should have indices.");
377  return result;
378  }
379  SMTRAT_LOG_DEBUG("smtrat.parser", "Trying to call function \"" << identifier << "\" with arguments " << arguments << ".");
380  if ((*ideffunit->second)(*identifier.indices, arguments, result, te(identifier.symbol))) {
381  SMTRAT_LOG_DEBUG("smtrat.parser", "Success, result is \"" << result << "\".");
382  return result;
383  }
384  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to call function \"" << identifier << "\" with arguments " << arguments << ":" << te);
386  return result;
387  }
388  auto udeffunit = state->defined_user_functions.find(identifier.symbol);
389  if (udeffunit != state->defined_user_functions.end()) {
390  if (identifier.indices != nullptr) {
391  SMTRAT_LOG_ERROR("smtrat.parser", "The function \"" << identifier << "\" should not have indices.");
393  return result;
394  }
395  SMTRAT_LOG_DEBUG("smtrat.parser", "Trying to call function \"" << identifier << "\" with arguments " << arguments << ".");
396  if (instantiateUserFunction(*udeffunit->second, arguments, result, te(identifier.symbol))) {
397  SMTRAT_LOG_DEBUG("smtrat.parser", "Success, result is \"" << result << "\".");
398  return result;
399  }
400  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to call function \"" << identifier << "\" with arguments " << arguments << ":" << te);
402  return result;
403  }
404  for (auto& t: theories) {
405  if (t.second->functionCall(identifier, arguments, result, te(t.first))) return result;
406  }
407  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to call \"" << identifier << "\" with arguments " << arguments << ":" << te);
409  return result;
410  }
411 
412  types::TermType quantifiedTerm(const std::vector<std::pair<std::string, carl::Sort>>& vars, const types::TermType& term, bool universal){
413  SMTRAT_LOG_DEBUG("smtrat.parser", "Declaring " << (universal ? "universal" : "existential") << " variables " << vars << " and term " << term);
414  TheoryError te;
416  carl::FormulaType type = universal ? carl::FormulaType::FORALL : carl::FormulaType::EXISTS;
417  for (auto& t: theories) {
418  if (t.second->declareQuantifiedTerm(vars, type, term, result, te)) return result;
419  }
420  SMTRAT_LOG_ERROR("smtrat.parser", "Failed to declare " << (universal ? "universal" : "existential") << " variables " << vars << " and term " << term << ":" << te);
422  return result;
423  }
424 
425  bool isVariableDeclared(const std::string& name) const {
426  return state->variables.find(name) != state->variables.end();
427  }
428 
429 private:
431  std::map<std::string, AbstractTheory*> theories;
432 };
433 
434 }
435 }
#define HANDLE_ERROR
Definition: Common.h:35
virtual void annotateName(const FormulaT &f, const std::string &name)=0
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:67
int var(Lit p)
Definition: SolverTypes.h:64
carl::mpl_variant_of< TermTypes >::type TermType
Variant type for all terms.
Definition: TheoryTypes.h:160
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
std::vector< carl::Variable > vars(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Definition: QEQuery.h:43
Class to create the formulas for axioms.
carl::Formula< Poly > FormulaT
Definition: types.h:37
carl::Formulas< Poly > FormulasT
Definition: types.h:39
const auto & settings_parser()
#define SMTRAT_LOG_WARN(channel, msg)
Definition: logging.h:33
#define SMTRAT_LOG_ERROR(channel, msg)
Definition: logging.h:32
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
Implements the theory of arithmetic, including LRA, LIA, NRA and NIA.
Definition: Arithmetic.h:16
Implements the theory of bitvectors.
Definition: Bitvector.h:13
Implements the theory of bitvectors.
Implements the core theory of the booleans.
Definition: Core.h:15
std::string symbol
Definition: Common.h:37
std::vector< std::size_t > * indices
Definition: Common.h:38
void registerFunction(const std::string &name, const FunctionInstantiator *fi)
Definition: ParserState.h:163
std::map< std::string, const FunctionInstantiator * > defined_functions
Definition: ParserState.h:68
std::map< std::string, types::TermType > constants
Definition: ParserState.h:65
bool isSymbolFree(const std::string &name, bool output=true)
Definition: ParserState.h:129
std::map< std::string, const IndexedFunctionInstantiator * > defined_indexed_functions
Definition: ParserState.h:69
std::map< std::string, types::VariableType > variables
Definition: ParserState.h:66
std::set< types::VariableType > auxiliary_variables
Definition: ParserState.h:63
std::map< std::string, types::TermType > bindings
Definition: ParserState.h:64
bool resolveSymbol(const std::string &name, const std::map< std::string, T > &map, Res &result) const
Definition: ParserState.h:145
InstructionHandler & handler
Definition: ParserState.h:74
std::map< std::string, const UserFunctionInstantiator * > defined_user_functions
Definition: ParserState.h:70
std::map< std::string, carl::UninterpretedFunction > declared_functions
Definition: ParserState.h:67
Helper functor for addConstants() method.
Definition: Theories.h:72
qi::symbols< char, types::ConstType > & constants
Definition: Theories.h:73
ConstantAdder(qi::symbols< char, types::ConstType > &constants)
Definition: Theories.h:74
Helper functor for addSimpleSorts() method.
Definition: Theories.h:89
qi::symbols< char, carl::Sort > & sorts
Definition: Theories.h:90
SimpleSortAdder(qi::symbols< char, carl::Sort > &sorts)
Definition: Theories.h:91
The Theories class combines all implemented theories and provides a single interface to interact with...
Definition: Theories.h:28
std::map< std::string, AbstractTheory * > theories
Definition: Theories.h:431
void addGlobalFormulas(FormulasT &formulas)
Definition: Theories.h:103
void defineFunction(const std::string &name, const std::vector< types::VariableType > &arguments, const carl::Sort &sort, const types::TermType &definition)
Definition: Theories.h:157
ParserState * state
Definition: Theories.h:430
types::VariableType resolveVariable(const Identifier &identifier) const
Definition: Theories.h:190
boost::mpl::vector< CoreTheory *, ArithmeticTheory *, BitvectorTheory *, UninterpretedTheory *, BooleanEncodingTheory * >::type Modules
Definition: Theories.h:42
void handleLet(const std::string &symbol, const types::TermType &term)
Definition: Theories.h:237
types::TermType functionCall(const Identifier &identifier, const std::vector< types::TermType > &arguments)
Definition: Theories.h:337
types::TermType resolveSymbol(const Identifier &identifier) const
Definition: Theories.h:174
void declareVariable(const std::string &name, const carl::Sort &sort)
Definition: Theories.h:108
void pushScriptScope(std::size_t n)
Definition: Theories.h:206
const auto & annotateTerm(const types::TermType &term, const std::vector< Attribute > &attributes)
Definition: Theories.h:213
types::TermType handleDistinct(const std::vector< types::TermType > &arguments)
Definition: Theories.h:268
void popScriptScope(std::size_t n)
Definition: Theories.h:209
types::VariableType declareFunctionArgument(const std::pair< std::string, carl::Sort > &arg)
Definition: Theories.h:141
bool instantiate(const UserFunctionInstantiator &function, const types::VariableType &var, const types::TermType &repl, types::TermType &subject)
Definition: Theories.h:280
void popExpressionScope(std::size_t n)
Definition: Theories.h:203
bool instantiateUserFunction(const UserFunctionInstantiator &function, const std::vector< types::TermType > &arguments, types::TermType &result, TheoryError &errors)
Definition: Theories.h:304
types::TermType quantifiedTerm(const std::vector< std::pair< std::string, carl::Sort >> &vars, const types::TermType &term, bool universal)
Definition: Theories.h:412
bool isVariableDeclared(const std::string &name) const
Definition: Theories.h:425
static void addSimpleSorts(qi::symbols< char, carl::Sort > &sorts)
Collects simple sorts from all theory modules.
Definition: Theories.h:99
Theories(ParserState *state)
Definition: Theories.h:45
types::TermType handleITE(const std::vector< types::TermType > &arguments)
Definition: Theories.h:242
static void addConstants(qi::symbols< char, types::ConstType > &constants)
Collects constants from all theory modules.
Definition: Theories.h:82
void pushExpressionScope(std::size_t n)
Definition: Theories.h:200
void declareFunction(const std::string &name, const std::vector< carl::Sort > &args, const carl::Sort &sort)
Definition: Theories.h:122
TheoryError & next()
Definition: Common.h:25
Implements the theory of equalities and uninterpreted functions.
Definition: Uninterpreted.h:13
Converts variants to some type using the Converter class.
Definition: Conversions.h:99