3 * @author YOUR NAME <YOUR EMAIL ADDRESS>
6 * Created on 2017-05-03.
9 #include "PBGaussModule.h"
13 template<class Settings>
14 PBGaussModule<Settings>::PBGaussModule(const ModuleInput* _formula, Conditionals& _conditionals, Manager* _manager):
15 Module( _formula, _conditionals, _manager )
18 template<class Settings>
19 PBGaussModule<Settings>::~PBGaussModule()
22 template<class Settings>
23 bool PBGaussModule<Settings>::informCore( const FormulaT& )
29 template<class Settings>
30 void PBGaussModule<Settings>::init()
33 template<class Settings>
34 bool PBGaussModule<Settings>::addCore( ModuleInput::const_iterator )
39 template<class Settings>
40 void PBGaussModule<Settings>::removeCore( ModuleInput::const_iterator )
43 template<class Settings>
44 void PBGaussModule<Settings>::updateModel() const
47 if( solverState() == Answer::SAT )
53 template<class Settings>
54 Answer PBGaussModule<Settings>::checkCore()
56 for(const auto& subformula : rReceivedFormula()){
57 const FormulaT& f = subformula.formula();
58 if(f.type() == carl::FormulaType::CONSTRAINT){
59 const ConstraintT& c = f.constraint();
60 for (const auto& var : c.variables()) {
61 mVariables.insert(var);
64 if(c.relation() == carl::Relation::EQ){
65 mEquations.push_back(c);
66 }else if(c.relation() == carl::Relation::LEQ || c.relation() == carl::Relation::GEQ
67 || c.relation() == carl::Relation::LESS || c.relation() == carl::Relation::GREATER){
68 mInequalities.push_back(c);
70 addSubformulaToPassedFormula(f);
73 addSubformulaToPassedFormula(f);
78 if(mEquations.size() > 1){
79 formula = gaussAlgorithm();
80 SMTRAT_LOG_DEBUG("smtrat.gauss", "Gaussing resulted in " << formula);
82 FormulasT subformulas;
83 for(const auto& it : mInequalities){
84 subformulas.push_back(FormulaT(it));
86 if(mEquations.size() == 1){
87 subformulas.push_back(FormulaT(mEquations.front()));
89 formula = FormulaT(carl::FormulaType::AND, std::move(subformulas));
92 addSubformulaToPassedFormula(formula);
93 Answer answer = runBackends();
94 if (answer == Answer::UNSAT) {
95 generateTrivialInfeasibleSubset();
101 template<class Settings>
102 FormulaT PBGaussModule<Settings>::gaussAlgorithm(){
103 SMTRAT_LOG_DEBUG("smtrat.gauss", "Gaussing " << mEquations);
104 if(mEquations.size() == 0){
105 return FormulaT(carl::FormulaType::TRUE);
106 }else if(mEquations.size() == 1){
107 return FormulaT(mEquations.front());
110 // Collect all variables
111 carl::Variables eqVarSet;
112 for(const auto& it : mEquations){
113 for (const auto& var : it.variables()) {
114 eqVarSet.insert(var);
117 std::vector<carl::Variable> eqVars(eqVarSet.begin(), eqVarSet.end());
119 // Collect all coefficients and rhs
120 std::vector<Rational> coef;
121 for(const auto& it : mEquations){
122 for (const auto& var : eqVars) {
123 // if var in equation, choose coeff, otherwise 0
125 for (const auto& term: it.lhs()) {
126 if (term.is_constant()) continue;
128 if (term.single_variable() == var) {
130 coef.push_back(term.coeff());
140 coef.push_back(-it.lhs().constant_part());
143 std::size_t rows = mEquations.size();
144 std::size_t columns = eqVars.size();
146 MatrixT matrix = MatrixT::Map(coef.data(), (long) columns + 1, (long) rows).transpose();
148 SMTRAT_LOG_DEBUG("smtrat.gauss", matrix);
151 Eigen::FullPivLU<MatrixT> lu(matrix);
153 const MatrixT& u = lu.matrixLU().triangularView<Eigen::Upper>();
154 const MatrixT& q = lu.permutationQ();
155 const MatrixT& p = lu.permutationP();
157 //newUpper with rhs and origin rows and columns order
158 MatrixT newUpper = p.inverse() * u * q.inverse();
159 VectorT newB = newUpper.col(newUpper.cols() - 1);
160 newUpper.conservativeResize(newUpper.rows(), newUpper.cols() - 1);
162 std::vector<carl::Relation> rels((std::size_t) newUpper.rows(), carl::Relation::EQ);
163 if(mInequalities.size() == 0){
164 return reconstructEqSystem(newUpper, newB, eqVarSet, rels);
166 return reduce(newUpper, newB, eqVarSet);
170 template<class Settings>
171 FormulaT PBGaussModule<Settings>::reconstructEqSystem(const MatrixT& m, const VectorT& b, const carl::Variables& vars, const std::vector<carl::Relation>& rels){
172 FormulasT subformulas;
173 std::vector<carl::Variable> varsVec(vars.begin(), vars.end());
174 for(long i = 0; i < m.rows(); i++){
176 const VectorT& r = m.row(i);
178 // Compute least common multiple of all denominators
180 for (long rid = 0; rid < r.size(); rid++) {
181 if (!carl::is_integer(r[rid])){
182 mpl = carl::lcm(mpl, carl::get_denom(r[rid]));
186 for(long j = 0; j < r.size(); j++){
187 if (carl::is_zero(r[j])) continue;
188 newLHS += TermT(Rational(mpl * r[j]) * varsVec[(std::size_t) j]);
190 subformulas.emplace_back(ConstraintT(newLHS + Rational(b[i] * -mpl), rels[std::size_t(i)]));
192 return FormulaT(carl::FormulaType::AND, std::move(subformulas));
196 template<class Settings>
197 FormulaT PBGaussModule<Settings>::reduce(const MatrixT& u, const VectorT& b, const carl::Variables vars){
199 std::vector<Rational> normUVec;
200 for(auto i = 0; i < u.rows(); i++){
201 for(auto rid = 0; rid < u.row(i).size(); rid++){
202 if(u.row(i)[i] != 0){
203 normUVec.push_back(carl::div(u.row(i)[rid], u.row(i)[i]));
205 normUVec.push_back(u.row(i)[rid]);
211 MatrixT normU = MatrixT::Map(normUVec.data(), (long) u.cols(), (long) u.rows()).transpose();
212 std::vector<Rational> bVector(b.data(), b.data() + b.size());
214 //Resize normU and add b
215 std::vector<Rational> upperCoef;
216 for(auto i = 0; i < normU.rows(); i++){
217 VectorT r = normU.row(i);
218 std::vector<Rational> row(r.data(), r.data() + r.size());
219 for(auto j : mVariables){
220 auto elem = vars.find(j);
221 if(elem != vars.end()){
222 upperCoef.push_back(row[(std::size_t) std::distance(vars.begin(), elem)]);
224 upperCoef.push_back((Rational) 0);
227 upperCoef.push_back(bVector[(std::size_t) i]);
230 MatrixT uMatrix = MatrixT::Map(upperCoef.data(), (long) mVariables.size() + 1, (long) mEquations.size()).transpose();
232 //Inequalities to matrix
233 std::vector<carl::Relation> ineqRels;
234 std::vector<Rational> ineqCoef;
235 for(const auto& i : mInequalities){
236 ineqRels.push_back(i.relation());
238 for(const auto& j : mVariables){
239 auto elem = std::find_if(iLHS.begin(), iLHS.end(),
240 [&] (const TermT& elem){
241 std::cout << elem << std::endl;
242 return !elem.is_constant() && elem.single_variable() == j;
244 if(elem != iLHS.end()){
245 ineqCoef.push_back(elem->coeff());
247 ineqCoef.push_back(0);
250 ineqCoef.push_back(i.lhs().constant_part());
254 MatrixT ineqMatrix = MatrixT::Map(ineqCoef.data(), (long) mVariables.size() + 1, (long) mInequalities.size()).transpose();
256 MatrixT result(mVariables.size() + 1, 0);
257 for(auto i = 0; i < ineqMatrix.rows();){
258 const VectorT& row = ineqMatrix.row(i);
260 //Check if possible to simplify
263 for(auto j = 0; j < row.size(); j++){
270 if(column >= 0 && column < u.rows()){
273 //Look for row in u which can reduce the inequality
275 for(auto it = 0; it < uMatrix.rows(); it++){
276 const VectorT& r = uMatrix.row(it);
277 std::vector<Rational> testrowVec(r.data(), r.data() + r.size());
278 for(auto colIterator = column; colIterator < row.size(); colIterator++){
279 if(row(colIterator) == 0){
284 if(colIterator == 0){
286 eqRow = uMatrix.row(it);
287 std::vector<Rational> eqRowVec(eqRow.data(), eqRow.data() + eqRow.size());
288 //Check which sign the multiplier must have
289 if((eqRow(colIterator) > 0 && row(colIterator) > 0) || (eqRow(colIterator) < 0 && row(colIterator) < 0)){
290 multiplier = - row(colIterator);
292 multiplier = row(colIterator);
298 if(r(colIterator) == 1){
299 //Check if entries before column-th column are 0
301 for(auto k = 0; k < colIterator; k++){
308 eqRow = uMatrix.row(it);
309 std::vector<Rational> eqRowVec(eqRow.data(), eqRow.data() + eqRow.size());
310 //Check which sign the multiplier must have
311 if((eqRow(colIterator) > 0 && row(colIterator) > 0) || (eqRow(colIterator) < 0 && row(colIterator) < 0)){
312 multiplier = - row(colIterator);
314 multiplier = row(colIterator);
328 std::vector<Rational> rowVec(row.data(), row.data() + row.size());
329 std::vector<Rational> eqRowVec(eqRow.data(), eqRow.data() + eqRow.size());
331 if(eqRowVec.size() != 0){
332 ineqMatrix.row(i) = (multiplier * eqRow) + row;
334 if(mInequalities[(std::size_t) i].relation() == carl::Relation::LESS){
335 ineqRels[(std::size_t) i] = carl::Relation::LEQ;
336 }else if(mInequalities[(std::size_t) i].relation() == carl::Relation::GREATER){
337 ineqRels[(std::size_t) i] = carl::Relation::GEQ;
339 // Try again with this (simplified) row
346 //It is not possible to simplify.
347 result.conservativeResize(result.rows(), result.cols() + 1);
348 result.col(result.cols()-1) = ineqMatrix.row(i);
354 for (const auto& it : mEquations) {
355 addSubformulaToPassedFormula(FormulaT(it));
358 MatrixT resultT = result.transpose();
359 const VectorT& newB = resultT.col(resultT.cols() - 1);
360 resultT.conservativeResize(resultT.rows(), resultT.cols() - 1);
361 return reconstructEqSystem(resultT, newB, mVariables, ineqRels);