3 #include <carl-arith/core/Variable.h>
9 if (boost::get<Poly>(&term) !=
nullptr) {
10 result = boost::get<Poly>(term);
12 }
else if (boost::get<Rational>(&term) !=
nullptr) {
15 }
else if (boost::get<carl::Variable>(&term) !=
nullptr) {
16 switch (boost::get<carl::Variable>(term).
type()) {
17 case carl::VariableType::VT_REAL:
18 case carl::VariableType::VT_INT:
19 result =
Poly(boost::get<carl::Variable>(term));
21 case carl::VariableType::VT_BOOL:
23 result =
Poly(boost::get<carl::Variable>(term));
30 }
else if (allow_bool && boost::get<FormulaT>(&term) !=
nullptr) {
31 FormulaT formula = boost::get<FormulaT>(term);
35 carl::Variable
var = mappedFormulaIt->second;
38 carl::Variable
var = carl::fresh_boolean_variable();
54 SMTRAT_LOG_DEBUG(
"smtrat.parser",
"Converting arguments: " << arguments <<
" for operator " << op);
56 for (std::size_t i = 0; i < arguments.size(); i++) {
59 errors.
next() <<
"Operator \"" << op <<
"\" expects arguments to be polynomials, but argument " << (i + 1) <<
" is not: \"" << arguments[i] <<
"\".";
67 namespace arithmetic {
70 carl::carlVariables pVars;
71 carl::variables(p, pVars);
72 std::vector<carl::Variable>
vars;
73 while (!pVars.empty()) {
74 auto it = at.
mITEs.find(*pVars.begin());
75 pVars.erase(*pVars.begin());
76 if (it != at.
mITEs.end()) {
77 carl::variables(std::get<1>(it->second), pVars);
78 carl::variables(std::get<2>(it->second), pVars);
79 vars.push_back(it->first);
82 std::size_t n =
vars.size();
90 std::vector<Poly> polys({p});
92 std::vector<FormulasT> conds(1 << n);
93 unsigned repeat = 1 << (n - 1);
96 std::vector<Poly> ptmp;
97 for (
auto& p : polys) {
102 std::swap(polys, ptmp);
105 for (
size_t i = 0; i < (size_t)(1 << n); i++) {
106 conds[i].push_back(f[0]);
107 if ((i + 1) % repeat == 0) std::swap(f[0], f[1]);
113 for (
unsigned i = 0; i < polys.size(); i++) {
121 for (
const auto& v :
vars) {
122 auto t = at.
mITEs[v];
135 if (boost::get<carl::Relation>(&op) ==
nullptr)
return false;
137 for (
const auto& a : arguments) {
138 if (boost::get<carl::Variable>(&a) !=
nullptr) {
139 if (boost::get<carl::Variable>(a).
type() != carl::VariableType::VT_BOOL)
return false;
140 }
else if (boost::get<FormulaT>(&a) ==
nullptr) {
144 errors.
next() <<
"Operator \"" << op <<
"\" only has boolean variables which is handled by the core theory.";
150 if (arguments.size() != 1) {
151 errors.
next() <<
"to_real should have a single argument";
160 carl::SortManager& sm = carl::SortManager::getInstance();
161 sorts.add(
"Int", sm.getInterpreted(carl::VariableType::VT_INT));
162 sorts.add(
"Real", sm.getInterpreted(carl::VariableType::VT_REAL));
167 carl::SortManager& sm = carl::SortManager::getInstance();
168 sm.addInterpretedSort(
"Int", carl::VariableType::VT_INT);
169 sm.addInterpretedSort(
"Real", carl::VariableType::VT_REAL);
187 carl::SortManager& sm = carl::SortManager::getInstance();
188 switch (sm.getType(
sort)) {
189 case carl::VariableType::VT_INT:
190 case carl::VariableType::VT_REAL: {
192 carl::Variable
var = carl::fresh_variable(name, sm.getType(
sort));
198 errors.
next() <<
"The requested sort was neither \"Int\" nor \"Real\" but \"" <<
sort <<
"\".";
207 errors.
next() <<
"Failed to construct ITE, the then-term \"" << thenterm <<
"\" is unsupported.";
211 errors.
next() <<
"Failed to construct ITE, the else-term \"" << elseterm <<
"\" is unsupported.";
214 if (thenpoly == elsepoly) {
218 if (ifterm.type() == carl::FormulaType::CONSTRAINT) {
224 }
else if (ifterm.constraint().relation() == carl::Relation::NEQ) {
225 if (ifterm.constraint() ==
ConstraintT(thenpoly - elsepoly, carl::Relation::NEQ)) {
230 }
else if (ifterm.type() ==
carl::FormulaType::NOT && ifterm.subformula().type() == carl::FormulaType::CONSTRAINT) {
236 }
else if (ifterm.subformula().constraint().relation() == carl::Relation::NEQ) {
237 if (ifterm.subformula().constraint() ==
ConstraintT(thenpoly - elsepoly, carl::Relation::NEQ)) {
243 carl::Variable auxVar = carl::fresh_real_variable();
245 mITEs[auxVar] = std::make_tuple(ifterm, thenpoly, elsepoly);
250 std::vector<Poly> args;
252 if (!c(arguments, args, errors))
return false;
254 return FormulaT(a - b, carl::Relation::NEQ);
263 errors.
next() <<
"The variable is not an arithmetic variable.";
266 if ((v.type() != carl::VariableType::VT_INT) && (v.type() != carl::VariableType::VT_REAL)) {
267 errors.
next() <<
"Sort is neither \"Int\" nor \"Real\" but \"" << v.type() <<
"\".";
272 errors.
next() <<
"Could not convert argument \"" << replacement <<
"\" to an arithmetic expression.";
280 SMTRAT_LOG_DEBUG(
"smtrat.parser",
"Function call " << identifier.
symbol <<
" with arguments " << arguments);
281 std::vector<Poly> args;
282 if (identifier.
symbol ==
"to_int") {
283 if (arguments.size() != 1) {
284 errors.
next() <<
"to_int should have a single argument";
289 if (!c(arguments[0], arg)) {
290 errors.
next() <<
"to_int should be called with a variable";
293 carl::Variable v = carl::fresh_variable(carl::VariableType::VT_INT);
300 if (identifier.
symbol ==
"mod") {
301 if (arguments.size() != 2) {
302 errors.
next() <<
"mod should have exactly two arguments.";
307 if (!ci(arguments[1], modulus)) {
308 errors.
next() <<
"mod should be called with an integer as second argument.";
314 if (cv(arguments[0], arg)) {
315 carl::Variable v = carl::fresh_variable(carl::VariableType::VT_INT);
316 carl::Variable u = carl::fresh_variable(carl::VariableType::VT_INT);
323 }
else if (ci(arguments[0], rarg)) {
324 Integer lhs = carl::to_int<Integer>(rarg);
325 Integer rhs = carl::to_int<Integer>(modulus);
329 errors.
next() <<
"mod should be called with a variable as first argument.";
333 if (identifier.
symbol ==
"root") {
334 if (arguments.size() != 3) {
335 errors.
next() <<
"root should have exactly three arguments.";
340 errors.
next() <<
"root should be called with a polynomial as first argument.";
345 if (!ci(arguments[1], k)) {
346 errors.
next() <<
"root should be called with an integer as second argument.";
351 if (!cv(arguments[2],
var)) {
352 errors.
next() <<
"root should be called with a variable as third argument.";
355 result = carl::MultivariateRoot<Poly>(p, carl::to_int<std::size_t>(carl::get_num(k)),
var);
359 if (it ==
ops.end()) {
360 errors.
next() <<
"Invalid operator \"" << identifier <<
"\".";
364 if (boost::get<carl::Relation>(&op) !=
nullptr && arguments.size() == 3 && boost::get<FormulaT>(&arguments[0]) !=
nullptr && boost::get<carl::Variable>(&arguments[1]) !=
nullptr &&
boost::get<carl::MultivariateRoot<Poly>>(&arguments[2]) !=
nullptr) {
365 bool negated = boost::get<FormulaT>(arguments[0]).type() == carl::FormulaType::TRUE;
366 carl::Variable
var = boost::get<carl::Variable>(arguments[1]);
367 carl::MultivariateRoot<Poly> root = boost::get<carl::MultivariateRoot<Poly>>(arguments[2]);
368 carl::Relation rel = boost::get<carl::Relation>(op);
375 if (boost::get<Poly::ConstructorOperation>(&op) !=
nullptr) {
376 auto o = boost::get<Poly::ConstructorOperation>(op);
377 if (o == Poly::ConstructorOperation::DIV) {
378 if (args.size() != 2) {
379 errors.
next() <<
"Division needs to have two operands.";
382 if (carl::is_zero(args[1]) || !args[1].is_number()) {
391 std::stringstream name;
393 auto div_var_new = carl::fresh_variable(name.str(), carl::VariableType::VT_REAL);
394 auto p_new =
Poly(args[0]);
395 auto q_new =
Poly(args[1]);
403 SMTRAT_LOG_DEBUG(
"smtrat.parser",
"Adding division formula: " << div_formula);
408 const auto& [p_old, q_old] = div_pair_old;
418 SMTRAT_LOG_DEBUG(
"smtrat.parser",
"Adding division pairwise formula: " << div_formula_pairwise);
431 }
else if (boost::get<carl::Relation>(&op) !=
nullptr) {
432 if (args.size() < 2) {
433 errors.
next() <<
"Operator \"" << boost::get<carl::Relation>(op) <<
"\" expects at least two operands.";
435 }
else if (args.size() == 2) {
439 for (std::size_t i = 0; i < args.size()-1; i++) {
445 errors.
next() <<
"Invalid operator \"" << op <<
"\".";
452 SMTRAT_LOG_DEBUG(
"smtrat.parser",
"Declaring quantified term " << term <<
" with quantification " <<
type <<
" and variables " <<
vars);
453 std::vector<carl::Variable> variables;
454 for (
const auto& v :
vars) {
457 errors.
next() <<
"Variable " << v.first <<
" not declared.";
460 variables.push_back(boost::get<carl::Variable>(it->second));
void sort(T *array, int size, LessThan lt)
auto get(const It &it, level)
Numeric mod(const Numeric &_valueA, const Numeric &_valueB)
Calculates the result of the first argument modulo the second argument.
bool substitute(const FormulaT &constr, const carl::Variable var, const carl::vs::Term< Poly > &term, FormulaT &result)
bool isBooleanIdentity(const OperatorType &op, const std::vector< types::TermType > &arguments, TheoryError &errors)
FormulaT makeConstraint(ArithmeticTheory &at, const Poly &lhs, const Poly &rhs, carl::Relation rel)
boost::variant< Poly::ConstructorOperation, carl::Relation > OperatorType
carl::mpl_variant_of< TermTypes >::type TermType
Variant type for all terms.
carl::mpl_variant_of< VariableTypes >::type VariableType
Variant type for all variables.
QuantifierType type(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
std::vector< carl::Variable > vars(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Class to create the formulas for axioms.
carl::Formula< Poly > FormulaT
carl::MultivariatePolynomial< Rational > Poly
carl::Constraint< Poly > ConstraintT
carl::Formulas< Poly > FormulasT
carl::IntegralType< Rational >::type Integer
#define SMTRAT_LOG_DEBUG(channel, msg)
Base class for all theories.
FormulaT expandDistinct(const std::vector< T > &values, const Builder &neqBuilder)
Implements the theory of arithmetic, including LRA, LIA, NRA and NIA.
bool handleDistinct(const std::vector< types::TermType > &arguments, types::TermType &result, TheoryError &errors)
Resolve a distinct operator.
std::map< carl::Variable, std::tuple< FormulaT, Poly, Poly > > mITEs
bool instantiate(const types::VariableType &var, const types::TermType &replacement, types::TermType &result, TheoryError &errors)
Instantiate a variable within a term.
std::map< carl::Variable, std::tuple< Poly, Poly > > mKnownDivisions
bool functionCall(const Identifier &identifier, const std::vector< types::TermType > &arguments, types::TermType &result, TheoryError &errors)
Resolve another unknown function call.
std::map< FormulaT, carl::Variable > mappedFormulas
bool convertTerm(const types::TermType &term, Poly &result, bool allow_bool=false)
ArithmeticTheory(ParserState *state)
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.
bool convertArguments(const arithmetic::OperatorType &op, const std::vector< types::TermType > &arguments, std::vector< Poly > &result, TheoryError &errors)
std::map< std::string, arithmetic::OperatorType > ops
bool declareQuantifiedTerm(const std::vector< std::pair< std::string, carl::Sort >> &vars, const carl::FormulaType &type, const types::TermType &term, types::TermType &result, TheoryError &errors)
Resolve a quantified term.
bool handleITE(const FormulaT &ifterm, const types::TermType &thenterm, const types::TermType &elseterm, types::TermType &result, TheoryError &errors)
Resolve an if-then-else operator.
std::map< carl::Variable, std::tuple< Poly, Poly > > mNewDivisions
static void addSimpleSorts(qi::symbols< char, carl::Sort > &sorts)
bool instantiate(V v, const T &repl, types::TermType &subject)
void registerFunction(const std::string &name, const FunctionInstantiator *fi)
FormulasT global_formulas
bool isSymbolFree(const std::string &name, bool output=true)
std::map< std::string, types::VariableType > variables
std::vector< smtrat::ModelVariable > artificialVariables
bool operator()(const std::vector< types::TermType > &arguments, types::TermType &result, TheoryError &errors) const
Converts variants to some type using the Converter class.
Converts a vector of variants to a vector of some type using the Converter class.