SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
PBGaussModule.tpp
Go to the documentation of this file.
1 /**
2  * @file PBGauss.cpp
3  * @author YOUR NAME <YOUR EMAIL ADDRESS>
4  *
5  * @version 2017-05-03
6  * Created on 2017-05-03.
7  */
8 
9 #include "PBGaussModule.h"
10 
11 namespace smtrat
12 {
13  template<class Settings>
14  PBGaussModule<Settings>::PBGaussModule(const ModuleInput* _formula, Conditionals& _conditionals, Manager* _manager):
15  Module( _formula, _conditionals, _manager )
16  {}
17 
18  template<class Settings>
19  PBGaussModule<Settings>::~PBGaussModule()
20  {}
21 
22  template<class Settings>
23  bool PBGaussModule<Settings>::informCore( const FormulaT& )
24  {
25 
26  return true;
27  }
28 
29  template<class Settings>
30  void PBGaussModule<Settings>::init()
31  {}
32 
33  template<class Settings>
34  bool PBGaussModule<Settings>::addCore( ModuleInput::const_iterator )
35  {
36  return true;
37  }
38 
39  template<class Settings>
40  void PBGaussModule<Settings>::removeCore( ModuleInput::const_iterator )
41  {}
42 
43  template<class Settings>
44  void PBGaussModule<Settings>::updateModel() const
45  {
46  mModel.clear();
47  if( solverState() == Answer::SAT )
48  {
49  getBackendsModel();
50  }
51  }
52 
53  template<class Settings>
54  Answer PBGaussModule<Settings>::checkCore()
55  {
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);
62  }
63 
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);
69  }else{
70  addSubformulaToPassedFormula(f);
71  }
72  }else{
73  addSubformulaToPassedFormula(f);
74  }
75  }
76 
77  FormulaT formula;
78  if(mEquations.size() > 1){
79  formula = gaussAlgorithm();
80  SMTRAT_LOG_DEBUG("smtrat.gauss", "Gaussing resulted in " << formula);
81  }else{
82  FormulasT subformulas;
83  for(const auto& it : mInequalities){
84  subformulas.push_back(FormulaT(it));
85  }
86  if(mEquations.size() == 1){
87  subformulas.push_back(FormulaT(mEquations.front()));
88  }
89  formula = FormulaT(carl::FormulaType::AND, std::move(subformulas));
90  }
91 
92  addSubformulaToPassedFormula(formula);
93  Answer answer = runBackends();
94  if (answer == Answer::UNSAT) {
95  generateTrivialInfeasibleSubset();
96  }
97  return answer;
98  }
99 
100 
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());
108  }
109 
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);
115  }
116  }
117  std::vector<carl::Variable> eqVars(eqVarSet.begin(), eqVarSet.end());
118 
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
124  bool found = false;
125  for (const auto& term: it.lhs()) {
126  if (term.is_constant()) continue;
127 
128  if (term.single_variable() == var) {
129  found = true;
130  coef.push_back(term.coeff());
131  break;
132  }
133  }
134 
135  if (!found) {
136  coef.push_back(0);
137  }
138  }
139 
140  coef.push_back(-it.lhs().constant_part());
141  }
142 
143  std::size_t rows = mEquations.size();
144  std::size_t columns = eqVars.size();
145 
146  MatrixT matrix = MatrixT::Map(coef.data(), (long) columns + 1, (long) rows).transpose();
147 
148  SMTRAT_LOG_DEBUG("smtrat.gauss", matrix);
149 
150  //LU Decomposition
151  Eigen::FullPivLU<MatrixT> lu(matrix);
152 
153  const MatrixT& u = lu.matrixLU().triangularView<Eigen::Upper>();
154  const MatrixT& q = lu.permutationQ();
155  const MatrixT& p = lu.permutationP();
156 
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);
161 
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);
165  }else{
166  return reduce(newUpper, newB, eqVarSet);
167  }
168  }
169 
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++){
175  Poly newLHS;
176  const VectorT& r = m.row(i);
177 
178  // Compute least common multiple of all denominators
179  Rational mpl = 1;
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]));
183  }
184  }
185  // Restore
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]);
189  }
190  subformulas.emplace_back(ConstraintT(newLHS + Rational(b[i] * -mpl), rels[std::size_t(i)]));
191  }
192  return FormulaT(carl::FormulaType::AND, std::move(subformulas));
193  }
194 
195 
196 template<class Settings>
197  FormulaT PBGaussModule<Settings>::reduce(const MatrixT& u, const VectorT& b, const carl::Variables vars){
198 
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]));
204  }else{
205  normUVec.push_back(u.row(i)[rid]);
206  }
207  }
208  }
209 
210 
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());
213 
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)]);
223  }else{
224  upperCoef.push_back((Rational) 0);
225  }
226  }
227  upperCoef.push_back(bVector[(std::size_t) i]);
228  }
229 
230  MatrixT uMatrix = MatrixT::Map(upperCoef.data(), (long) mVariables.size() + 1, (long) mEquations.size()).transpose();
231 
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());
237  auto iLHS = i.lhs();
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;
243  });
244  if(elem != iLHS.end()){
245  ineqCoef.push_back(elem->coeff());
246  }else{
247  ineqCoef.push_back(0);
248  }
249  }
250  ineqCoef.push_back(i.lhs().constant_part());
251  }
252 
253 
254  MatrixT ineqMatrix = MatrixT::Map(ineqCoef.data(), (long) mVariables.size() + 1, (long) mInequalities.size()).transpose();
255 
256  MatrixT result(mVariables.size() + 1, 0);
257  for(auto i = 0; i < ineqMatrix.rows();){
258  const VectorT& row = ineqMatrix.row(i);
259 
260  //Check if possible to simplify
261  Rational m;
262  long column = -1;
263  for(auto j = 0; j < row.size(); j++){
264  if(row(j) != 0){
265  column = j;
266  break;
267  }
268  }
269  Rational multiplier;
270  if(column >= 0 && column < u.rows()){
271  //Reduce
272 
273  //Look for row in u which can reduce the inequality
274  VectorT eqRow;
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){
280  it++;
281  break;
282  }else{
283  bool found = false;
284  if(colIterator == 0){
285  if(r(0) == 1){
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);
291  }else{
292  multiplier = row(colIterator);
293  }
294  found = true;
295  break;
296  }
297  }else{
298  if(r(colIterator) == 1){
299  //Check if entries before column-th column are 0
300  bool zeros = true;
301  for(auto k = 0; k < colIterator; k++){
302  if(r(k) != 0){
303  zeros = false;
304  break;
305  }
306  }
307  if(zeros){
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);
313  }else{
314  multiplier = row(colIterator);
315  }
316  found = true;
317  break;
318  }
319  }
320  }
321  if(found) break;
322  }
323  }
324 
325  }
326 
327 
328  std::vector<Rational> rowVec(row.data(), row.data() + row.size());
329  std::vector<Rational> eqRowVec(eqRow.data(), eqRow.data() + eqRow.size());
330 
331  if(eqRowVec.size() != 0){
332  ineqMatrix.row(i) = (multiplier * eqRow) + row;
333  //Update relation
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;
338  }
339  // Try again with this (simplified) row
340  continue;
341  }else{
342  //Got to next row
343  i++;
344  }
345  }else {
346  //It is not possible to simplify.
347  result.conservativeResize(result.rows(), result.cols() + 1);
348  result.col(result.cols()-1) = ineqMatrix.row(i);
349  // Go to next row
350  i++;
351  }
352  }
353 
354  for (const auto& it : mEquations) {
355  addSubformulaToPassedFormula(FormulaT(it));
356  }
357 
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);
362  }
363 }
364 
365