-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nonlin LA preds #790
base: master
Are you sure you want to change the base?
Nonlin LA preds #790
Changes from all commits
06306c8
59c9152
9afd418
9555791
b64f03b
b617b20
2f49d40
9bc9c8a
046a7b9
fab2f08
a236b36
2eedd00
8ff3d59
d8ecbb6
d8953ac
3829c5c
68ac42d
1668eff
adaea42
cdb3164
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
* Copyright (c) 2024, Konstantin Britikov <[email protected]> | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#ifndef OPENSMT_NONLINEXCEPTION_H | ||
#define OPENSMT_NONLINEXCEPTION_H | ||
|
||
namespace opensmt { | ||
class NonLinException : public std::runtime_error { | ||
public: | ||
NonLinException(std::string_view const reason_) : runtime_error(std::string(reason_)) { | ||
msg = "Term " + std::string(reason_) + " is non-linear"; | ||
} | ||
virtual char const * what() const noexcept override { return msg.c_str(); } | ||
|
||
private: | ||
std::string msg; | ||
}; | ||
} | ||
|
||
#endif // OPENSMT_NONLINEXCEPTION_H |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,16 +8,6 @@ | |
#include <numeric> | ||
|
||
namespace opensmt { | ||
class LANonLinearException : public std::runtime_error { | ||
public: | ||
LANonLinearException(char const * reason_) : runtime_error(reason_) { | ||
msg = "Term " + std::string(reason_) + " is non-linear"; | ||
} | ||
virtual char const * what() const noexcept override { return msg.c_str(); } | ||
|
||
private: | ||
std::string msg; | ||
}; | ||
BritikovKI marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
class ArithDivisionByZeroException : public std::runtime_error { | ||
public: | ||
|
@@ -105,6 +95,10 @@ class ArithLogic : public Logic { | |
|
||
SymRef get_sym_Int_TIMES() const { return sym_Int_TIMES; } | ||
SymRef get_sym_Real_TIMES() const { return sym_Real_TIMES; } | ||
SymRef get_sym_Int_TIMES_LIN() const { return sym_Int_TIMES_LIN; } | ||
SymRef get_sym_Real_TIMES_LIN() const { return sym_Real_TIMES_LIN; } | ||
SymRef get_sym_Int_TIMES_NONLIN() const { return sym_Int_TIMES_NONLIN; } | ||
SymRef get_sym_Real_TIMES_NONLIN() const { return sym_Real_TIMES_NONLIN; } | ||
BritikovKI marked this conversation as resolved.
Show resolved
Hide resolved
|
||
SymRef get_sym_Int_DIV() const { return sym_Int_DIV; } | ||
SymRef get_sym_Int_MOD() const { return sym_Int_MOD; } | ||
SymRef get_sym_Real_DIV() const { return sym_Real_DIV; } | ||
|
@@ -170,10 +164,22 @@ class ArithLogic : public Logic { | |
bool isIntNeg(SymRef sr) const { return sr == sym_Int_NEG; } | ||
bool isRealNeg(SymRef sr) const { return sr == sym_Real_NEG; } | ||
|
||
bool isTimes(SymRef sr) const { return isIntTimes(sr) or isRealTimes(sr); } | ||
bool isTimes(SymRef sr) const { return isTimesLin(sr) or isTimesNonlin(sr) or isIntTimes(sr) or isRealTimes(sr); }; | ||
bool isTimesLinOrNonlin(SymRef sr) const { return isTimesLin(sr) or isTimesNonlin(sr); }; | ||
bool isTimesLin(SymRef sr) const { return isIntTimesLin(sr) or isRealTimesLin(sr); } | ||
bool isTimesNonlin(SymRef sr) const { return isIntTimesNonlin(sr) or isRealTimesNonlin(sr); } | ||
bool isTimes(PTRef tr) const { return isTimes(getPterm(tr).symb()); } | ||
bool isIntTimes(PTRef tr) const { return isIntTimes(getPterm(tr).symb()); } | ||
bool isRealTimes(PTRef tr) const { return isRealTimes(getPterm(tr).symb()); } | ||
bool isTimesLinOrNonlin(PTRef tr) const { return isTimesLinOrNonlin(getPterm(tr).symb()); }; | ||
bool isTimesLin(PTRef tr) const { return isTimesLin(getPterm(tr).symb()); } | ||
bool isTimesNonlin(PTRef tr) const { return isTimesNonlin(getPterm(tr).symb()); } | ||
bool isIntTimesLin(PTRef tr) const { return isIntTimesLin(getPterm(tr).symb()); } | ||
bool isIntTimesNonlin(PTRef tr) const { return isIntTimesNonlin(getPterm(tr).symb()); } | ||
bool isRealTimesLin(PTRef tr) const { return isRealTimesLin(getPterm(tr).symb()); } | ||
bool isRealTimesNonlin(PTRef tr) const { return isRealTimesNonlin(getPterm(tr).symb()); } | ||
bool isIntTimesLin(SymRef sr) const { return sr == sym_Int_TIMES_LIN; } | ||
bool isIntTimesNonlin(SymRef sr) const { return sr == sym_Int_TIMES_NONLIN; } | ||
bool isRealTimesLin(SymRef sr) const { return sr == sym_Real_TIMES_LIN; } | ||
bool isRealTimesNonlin(SymRef sr) const { return sr == sym_Real_TIMES_NONLIN; } | ||
bool isIntTimes(SymRef sr) const { return sr == sym_Int_TIMES; } | ||
bool isRealTimes(SymRef sr) const { return sr == sym_Real_TIMES; } | ||
|
||
|
@@ -222,10 +228,10 @@ class ArithLogic : public Logic { | |
|
||
bool isNumVar(SymRef sr) const { return isVar(sr) and (yieldsSortInt(sr) or yieldsSortReal(sr)); } | ||
bool isNumVar(PTRef tr) const { return isNumVar(getPterm(tr).symb()); } | ||
bool isNumVarLike(SymRef sr) const { | ||
return yieldsSortNum(sr) and not isPlus(sr) and not isTimes(sr) and not isNumConst(sr); | ||
bool isMonomial(PTRef tr) const { | ||
SymRef sr = getPterm(tr).symb(); | ||
return yieldsSortNum(sr) and not isPlus(sr) and not isTimesLin(sr) and not isNumConst(sr); | ||
} | ||
bool isNumVarLike(PTRef tr) const { return isNumVarLike(getPterm(tr).symb()); } | ||
|
||
bool isZero(SymRef sr) const { return isIntZero(sr) or isRealZero(sr); } | ||
bool isZero(PTRef tr) const { return isZero(getSymRef(tr)); } | ||
|
@@ -267,7 +273,8 @@ class ArithLogic : public Logic { | |
} | ||
|
||
SymRef getPlusForSort(SRef sort) const; | ||
SymRef getTimesForSort(SRef sort) const; | ||
SymRef getTimesLinForSort(SRef sort) const; | ||
SymRef getTimesNonlinForSort(SRef sort) const; | ||
SymRef getMinusForSort(SRef sort) const; | ||
|
||
PTRef getZeroForSort(SRef sort) const; | ||
|
@@ -346,7 +353,8 @@ class ArithLogic : public Logic { | |
bool isLinearTerm(PTRef tr) const; | ||
bool isLinearFactor(PTRef tr) const; | ||
pair<Number, vec<PTRef>> getConstantAndFactors(PTRef sum) const; | ||
pair<PTRef, PTRef> splitTermToVarAndConst(PTRef term) const; | ||
// Given a term `t` is splits the term into monomial and its coefficient | ||
pair<PTRef, PTRef> splitPolyTerm(PTRef term) const; | ||
BritikovKI marked this conversation as resolved.
Show resolved
Hide resolved
|
||
PTRef normalizeMul(PTRef mul); | ||
// Given a sum term 't' returns a normalized inequality 'c <= s' equivalent to '0 <= t' | ||
PTRef sumToNormalizedInequality(PTRef sum); | ||
|
@@ -380,6 +388,9 @@ class ArithLogic : public Logic { | |
PTRef mkBinaryGeq(PTRef lhs, PTRef rhs) { return mkBinaryLeq(rhs, lhs); } | ||
PTRef mkBinaryLt(PTRef lhs, PTRef rhs) { return mkNot(mkBinaryGeq(lhs, rhs)); } | ||
PTRef mkBinaryGt(PTRef lhs, PTRef rhs) { return mkNot(mkBinaryLeq(lhs, rhs)); } | ||
SymRef declareFun_Multiplication_LinNonlin(std::string const & s, SRef rsort, vec<SRef> const & args) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a better place for this method than between |
||
return sym_store.newInternalSymb(s.c_str(), rsort, args, SymConf::CommutativeNoScopingLeftAssoc); | ||
} | ||
PTRef mkBinaryEq(PTRef lhs, PTRef rhs) override; | ||
pair<Number, PTRef> sumToNormalizedPair(PTRef sum); | ||
pair<Number, PTRef> sumToNormalizedIntPair(PTRef sum); | ||
|
@@ -431,6 +442,8 @@ class ArithLogic : public Logic { | |
SymRef sym_Real_MINUS; | ||
SymRef sym_Real_PLUS; | ||
SymRef sym_Real_TIMES; | ||
SymRef sym_Real_TIMES_LIN; | ||
SymRef sym_Real_TIMES_NONLIN; | ||
SymRef sym_Real_DIV; | ||
SymRef sym_Real_EQ; | ||
SymRef sym_Real_LEQ; | ||
|
@@ -451,6 +464,8 @@ class ArithLogic : public Logic { | |
SymRef sym_Int_MINUS; | ||
SymRef sym_Int_PLUS; | ||
SymRef sym_Int_TIMES; | ||
SymRef sym_Int_TIMES_LIN; | ||
SymRef sym_Int_TIMES_NONLIN; | ||
SymRef sym_Int_DIV; | ||
SymRef sym_Int_MOD; | ||
SymRef sym_Int_EQ; | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -11,6 +11,7 @@ | |||||
#include "CutCreator.h" | ||||||
|
||||||
#include <common/Random.h> | ||||||
#include <common/NonLinException.h> | ||||||
#include <models/ModelBuilder.h> | ||||||
#include <simplifiers/LA.h> | ||||||
|
||||||
|
@@ -91,9 +92,7 @@ void LASolver::isProperLeq(PTRef tr) | |||||
assert(logic.isLeq(tr)); | ||||||
auto [cons, sum] = logic.leqToConstantAndTerm(tr); | ||||||
assert(logic.isConstant(cons)); | ||||||
assert(logic.isNumVar(sum) || logic.isPlus(sum) || logic.isTimes(sum)); | ||||||
assert(!logic.isTimes(sum) || ((logic.isNumVar(logic.getPterm(sum)[0]) && logic.isOne(logic.mkNeg(logic.getPterm(sum)[1]))) || | ||||||
(logic.isNumVar(logic.getPterm(sum)[1]) && logic.isOne(logic.mkNeg(logic.getPterm(sum)[0]))))); | ||||||
assert(logic.isNumVar(sum) || logic.isPlus(sum) || logic.isTimesLinOrNonlin(sum)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this express the cases better?
Suggested change
|
||||||
(void) cons; (void)sum; | ||||||
} | ||||||
|
||||||
|
@@ -244,7 +243,7 @@ LVRef LASolver::getVarForLeq(PTRef ref) const { | |||||
} | ||||||
|
||||||
LVRef LASolver::getLAVar_single(PTRef expr_in) { | ||||||
|
||||||
if (logic.isTimesNonlin(expr_in)) throw NonLinException(logic.pp(expr_in)); | ||||||
assert(logic.isLinearTerm(expr_in)); | ||||||
PTId id = logic.getPterm(expr_in).getId(); | ||||||
|
||||||
|
@@ -262,7 +261,7 @@ std::unique_ptr<Tableau::Polynomial> LASolver::expressionToLVarPoly(PTRef term) | |||||
auto poly = std::make_unique<Tableau::Polynomial>(); | ||||||
bool negated = laVarMapper.isNegated(term); | ||||||
for (int i = 0; i < logic.getPterm(term).size(); i++) { | ||||||
auto [v,c] = logic.splitTermToVarAndConst(logic.getPterm(term)[i]); | ||||||
auto [v,c] = logic.splitPolyTerm(logic.getPterm(term)[i]); | ||||||
LVRef var = getLAVar_single(v); | ||||||
Real coeff = getNum(c); | ||||||
if (negated) { | ||||||
|
@@ -296,11 +295,11 @@ LVRef LASolver::registerArithmeticTerm(PTRef expr) { | |||||
} | ||||||
} | ||||||
|
||||||
if (logic.isNumVar(expr) || logic.isTimes(expr)) { | ||||||
if (logic.isNumVar(expr) || logic.isTimesLin(expr)) { | ||||||
// Case (1), (2a), and (2b) | ||||||
auto [v,c] = logic.splitTermToVarAndConst(expr); | ||||||
assert(logic.isNumVar(v) || (laVarMapper.isNegated(v) && logic.isNumVar(logic.mkNeg(v)))); | ||||||
auto [v,c] = logic.splitPolyTerm(expr); | ||||||
x = getLAVar_single(v); | ||||||
assert(logic.isNumVar(v) || (laVarMapper.isNegated(v) && logic.isNumVar(logic.mkNeg(v)))); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why has the assert moved? Just keep it in the original place, no? |
||||||
simplex.newNonbasicVar(x); | ||||||
notifyVar(x); | ||||||
} | ||||||
|
@@ -847,7 +846,7 @@ std::pair<SparseLinearSystem,std::vector<PTRef>> linearSystemFromConstraints(std | |||||
PTRef poly = defConstraint.lhs; | ||||||
fillTerms(poly, terms); | ||||||
for (PTRef arg : terms) { | ||||||
auto [var, constant] = logic.splitTermToVarAndConst(arg); | ||||||
auto [var, constant] = logic.splitPolyTerm(arg); | ||||||
assert(var != PTRef_Undef); | ||||||
if (varIndices.find(var) == varIndices.end()) { | ||||||
varIndices.insert({var, columns++}); | ||||||
|
@@ -866,7 +865,7 @@ std::pair<SparseLinearSystem,std::vector<PTRef>> linearSystemFromConstraints(std | |||||
PTRef poly = constraints[row].lhs; | ||||||
fillTerms(poly, terms); | ||||||
for (PTRef arg : terms) { | ||||||
auto [var, constant] = logic.splitTermToVarAndConst(arg); | ||||||
auto [var, constant] = logic.splitPolyTerm(arg); | ||||||
auto col = varIndices[var]; | ||||||
columnPolynomials[col].addTerm(IndexType{row}, logic.getNumConst(constant)); | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
(set-logic QF_LIA) | ||
(define-fun uninterp_mul ((a Int) (b Int)) Int (* a b)) | ||
(assert (= (uninterp_mul 1 2) 2)) | ||
(check-sat) | ||
(exit) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sat |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
(set-logic QF_LRA) | ||
(define-fun uninterp_div ((a Real) (b Real)) Real (* a b)) | ||
(assert (= (uninterp_div 0.25 2) 0.5)) | ||
(check-sat) | ||
(exit) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sat |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
(set-logic QF_LIA) | ||
(declare-fun x () Int) | ||
(define-fun uninterp_mul ((a Int) (b Int)) Int (* 2 a b)) | ||
(assert (= (uninterp_mul 5 x) 10)) | ||
(check-sat) | ||
(get-model) | ||
(exit) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
sat | ||
( | ||
(define-fun x () Int | ||
1) | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
(set-logic QF_LIA) | ||
(declare-fun x () Int) | ||
(define-fun uninterp_mul ((a Int) (b Int)) Int (* a b)) | ||
(assert (= (uninterp_mul 2 x) (+ x x))) | ||
(check-sat) | ||
(get-model) | ||
(exit) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
sat | ||
( | ||
(define-fun x () Int | ||
0) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this some formatter thing? The two catch clauses should not be on the same line.