SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
GBModule.tpp
Go to the documentation of this file.
1 /**
2  * @file GBModule.tpp
3  *
4  * @author Sebastian Junges
5  * @author Ulrich Loup
6  *
7  * @version 2012-12-20
8  */
9 #include <smtrat-common/smtrat-common.h>
10 
11 #include "GBModule.h"
12 #include "GBModuleStatistics.h"
13 #include "UsingDeclarations.h"
14 #ifdef USE_NSS
15 #include <reallynull/lib/GroebnerToSDP/GroebnerToSDP.h>
16 #endif
17 
18 //#define CHECK_SMALLER_MUSES
19 //#define SEARCH_FOR_RADICALMEMBERS
20 //#define GB_OUTPUT_METHODS
21 //#define GB_OUTPUT
22 
23 using std::set;
24 
25 
26 
27 namespace smtrat
28 {
29 
30 template<class Settings>
31 GBModule<Settings>::GBModule( const ModuleInput* const _formula, Conditionals& _conditionals, Manager* const _manager ):
32  Module( _formula, _conditionals, _manager ),
33  mBasis( ),
34  mInequalities( this ),
35  mStateHistory( ),
36  mRecalculateGB(false)
37 #ifdef SMTRAT_DEVOPTION_Statistics
38  ,
39  mStats(GBModuleStats::getInstance(Settings::identifier)),
40  mGBStats(GBCalculationStats::getInstance(Settings::identifier))
41 #endif
42 {
43  pushBacktrackPoint( rReceivedFormula().end( ) );
44 }
45 
46 template<class Settings>
47 GBModule<Settings>::~GBModule( )
48 {}
49 
50 /**
51  * Adds the constraint to the known constraints of the module.
52  * This includes scanning variables as well as transforming inequalities, if this is enabled.
53  * @param _formula A REALCONSTRAINT which should be regarded by the next theory call.
54  * @return true
55  */
56 template<class Settings>
57 bool GBModule<Settings>::addCore( ModuleInput::const_iterator _formula )
58 {
59  if( _formula->formula().type() != carl::FormulaType::CONSTRAINT )
60  {
61  return true;
62  }
63  assert(!_formula->formula().constraint().lhs().is_constant());
64 
65  #ifdef SMTRAT_DEVOPTION_Statistics
66  const ConstraintT& constraint = _formula->formula().constraint( );
67  mStats.constraintAdded(constraint.relation());
68  #endif
69 
70  processNewConstraint(_formula);
71  //only equalities should be added to the gb
72  return true;
73 
74 }
75 
76 template<class Settings>
77 bool GBModule<Settings>::constraintByGB(carl::Relation cr)
78 {
79  return ((cr == carl::Relation::EQ) ||
80  (Settings::transformIntoEqualities == ALL_INEQUALITIES) ||
81  (Settings::transformIntoEqualities == ONLY_NONSTRICT && (cr == carl::Relation::GEQ || cr == carl::Relation::LEQ) ));
82 }
83 
84 /**
85  * Method which updates internal data structures to reflect the added formula.
86  * @param _formula
87  */
88 template<class Settings>
89 void GBModule<Settings>::processNewConstraint(ModuleInput::const_iterator _formula)
90 {
91  const ConstraintT& constraint = _formula->formula().constraint( );
92  bool toGb = constraintByGB(constraint.relation());
93 
94  if( toGb )
95  {
96  handleConstraintToGBQueue(_formula);
97  }
98  else
99  {
100  handleConstraintNotToGB(_formula);
101  }
102 }
103 
104 /**
105  * Method which adds constraint to the GB-process.
106  * @param _formula
107  */
108 template<class Settings>
109 void GBModule<Settings>::handleConstraintToGBQueue(ModuleInput::const_iterator _formula)
110 {
111  pushBacktrackPoint( _formula );
112  // Equalities do not need to be transformed, so we add them directly.
113  GBPolynomial newPol;
114  if(_formula->formula().constraint( ).relation() == carl::Relation::EQ)
115  {
116  newPol = GBPolynomial ((typename Poly::PolyType)_formula->formula().constraint().lhs());
117  }
118  else
119  {
120  newPol = transformIntoEquality( _formula );
121 
122  }
123  newPol.setReasons(carl::BitVector(unsigned(mBacktrackPoints.size() - 1)));
124  mBasis.addPolynomial( newPol );
125  saveState( );
126 
127  if( !Settings::passGB )
128  {
129  addReceivedSubformulaToPassedFormula( _formula );
130  }
131 }
132 
133 
134 /**
135  * Method which adds constraints to our internal datastructures without adding them to the GB. E.g. inequalities are added to the inequalitiestable.
136  * @param _formula
137  */
138 template<class Settings>
139 void GBModule<Settings>::handleConstraintNotToGB(ModuleInput::const_iterator _formula)
140 {
141  if( Settings::checkInequalities == NEVER )
142  {
143  addReceivedSubformulaToPassedFormula( _formula );
144  }
145  else if( Settings::checkInequalities == ALWAYS )
146  {
147  mNewInequalities.push_back( mInequalities.InsertReceivedFormula( _formula ) );
148  // assert((mNewInequalities.back()->first)->formula()->constraint().relation() != carl::Relation::EQ); TODO: ???
149  }
150  else
151  {
152  assert( Settings::checkInequalities == AFTER_NEW_GB);
153  mInequalities.InsertReceivedFormula( _formula );
154  }
155 }
156 
157 
158 /**
159  * A theory call to the GBModule. The exact working of this module depends on the settings in GBSettings.
160  * @return (TRUE,FALSE,UNKNOWN) dependent on the asserted constraints.
161  */
162 template<class Settings>
163 Answer GBModule<Settings>::checkCore()
164 {
165 #ifdef GB_OUTPUT
166  std::cout << "GB Called" << std::endl;
167 #endif
168  // We can only handle conjunctions of constraints.
169  if(!rReceivedFormula().is_constraint_conjunction())
170  {
171  return UNKNOWN;
172  }
173  // This check asserts that all the conflicts are handled by the SAT solver. (workaround)
174  if( !mInfeasibleSubsets.empty() )
175  {
176  return UNSAT;
177  }
178 
179  #ifdef SMTRAT_DEVOPTION_Statistics
180  mStats.called();
181  #endif
182 
183  assert( mInfeasibleSubsets.empty( ) );
184 
185  // New elements queued for adding to the gb have to be handled.
186  if( !mBasis.inputEmpty( ) )
187  {
188  #ifdef GB_OUTPUT
189  std::cout << "Scheduled: " << std::endl;
190  mBasis.printScheduledPolynomials();
191  #endif
192  if(Settings::iterativeVariableRewriting)
193  {
194  if(mRewriteRules.size() > 0)
195  {
196  std::list<std::pair<carl::BitVector, carl::BitVector> > deductions;
197  /// TODO fix this
198  //deductions = mBasis.applyVariableRewriteRulesToInput(mRewriteRules);
199  knownConstraintDeduction(deductions);
200  }
201  }
202  #ifdef GB_OUTPUT
203  std::cout << "-------->" << std::endl;
204  mBasis.printScheduledPolynomials();
205  std::cout << "--------|" << std::endl;
206  #endif
207  //first, we interreduce the input!
208  }
209 
210  if( !mBasis.inputEmpty( ) )
211  {
212  std::list<std::pair<carl::BitVector, carl::BitVector> > deduced = mBasis.reduceInput( );
213  //analyze for deductions
214  knownConstraintDeduction(deduced);
215  }
216 
217  //If the GB needs to be updated, we do so. Otherwise we skip.
218  // Notice that we might to update the gb after backtracking (mRecalculateGB flag).
219  if( !mBasis.inputEmpty( ) || (mRecalculateGB && mBacktrackPoints.size() > 1 ) )
220  {
221  //now, we calculate the groebner basis
222 #ifdef GB_OUTPUT
223  std::cout << "basis calculate call" << std::endl;
224 #endif
225  mBasis.calculate( );
226 #ifdef GB_OUTPUT
227  std::cout << "basis calculated" << std::endl;
228  mBasis.getIdeal().print();
229 #endif
230  mRecalculateGB = false;
231  if( Settings::iterativeVariableRewriting && !mBasis.basisis_constant( ) )
232  {
233  iterativeVariableRewriting();
234  }
235  GBPolynomial witness;
236  #ifdef USE_NSS
237  // If the system is constant, we already have a witness for unsatisfiability.
238  // On linear systems, all solutions lie in Q. So we do not have to check for a solution.
239  if( Settings::applyNSS && !mBasis.is_constant( ) && !mBasis.getGbIdeal( ).is_linear( ) )
240  {
241  witness = callGroebnerToSDP(mBasis.getGbIdeal());
242  }
243  // We have found an infeasible subset. Generate it.
244  #endif
245  if( mBasis.basisis_constant( ) || (Settings::applyNSS && !carl::is_zero(witness)) )
246  {
247 
248  if( mBasis.basisis_constant( ) )
249  {
250  #ifdef SMTRAT_DEVOPTION_Statistics
251  mStats.constantGB();
252  #endif
253  assert(mBasis.getIdeal().nrGenerators() == 1);
254  witness = mBasis.getIdeal( ).getGenerators().front();
255  }
256  #ifdef USE_NSS
257  else
258  {
259  typename Settings::Reductor red( mBasis.getGbIdeal( ), witness );
260  witness = red.fullReduce( );
261  std::cout << witness << std::endl;
262  assert( carl::is_zero(witness) );
263  }
264  #endif
265  mInfeasibleSubsets.emplace_back();
266  // The equalities we used for the basis-computation are the infeasible subset
267 
268  assert(!Settings::getReasonsForInfeasibility || !witness.getReasons().empty());
269  carl::BitVector::const_iterator origIt = witness.getReasons().begin( );
270  origIt++; // As the first bit shows to the first entry in the backtrack points, which is the end of the received formula
271 
272  auto it = mBacktrackPoints.begin( );
273  for( ++it; it != mBacktrackPoints.end( ); ++it )
274  {
275  assert(it != mBacktrackPoints.end());
276  assert( (*it)->formula().type() == carl::FormulaType::CONSTRAINT );
277  assert( Settings::transformIntoEqualities != NO_INEQUALITIES || (*it)->formula().constraint( ).relation( ) == carl::Relation::EQ );
278 
279  if( Settings::getReasonsForInfeasibility )
280  {
281 
282  if( origIt.get( ) )
283  {
284  mInfeasibleSubsets.back( ).insert( (*it)->formula() );
285  }
286  origIt++;
287  }
288  else
289  {
290  mInfeasibleSubsets.back( ).insert( (*it)->formula() );
291  }
292  }
293 
294  #ifdef SMTRAT_DEVOPTION_Statistics
295  mStats.EffectivenessOfConflicts( (double)mInfeasibleSubsets.back().size()/(double)rReceivedFormula().size());
296  #endif
297  #ifdef CHECK_SMALLER_MUSES
298  Module::checkInfSubsetForMinimality( mInfeasibleSubsets->begin() );
299  #endif
300  assert(!mInfeasibleSubsets.empty());
301  assert(!mInfeasibleSubsets.front().empty());
302  return UNSAT;
303  }
304  saveState( );
305 
306 
307  if( Settings::checkInequalities != NEVER )
308  {
309  Answer ans = UNKNOWN;
310  ans = mInequalities.reduceWRTGroebnerBasis( mBasis.getIdeal( ), mRewriteRules );
311 
312  if( ans == UNSAT )
313  {
314  return ans;
315  }
316  }
317  assert( mInfeasibleSubsets.empty( ) );
318 
319  // When passing a gb, first remove last and then pass current gb.
320  if( Settings::passGB )
321  {
322  // TODO: Do not use rPassedFormulaBegin, which should be disabled
323  for( ModuleInput::iterator i = passedFormulaBegin( ); i != rPassedFormula().end( ); )
324  {
325  // assert( i->formula().type() == carl::FormulaType::CONSTRAINT ); // TODO: Assure, not to add TRUE to the passed formula.
326  if( std::count(mGbEqualities.begin(), mGbEqualities.end(), i->formula()) == 1 )
327  {
328  i = super::eraseSubformulaFromPassedFormula( i, true );
329  }
330  else
331  {
332  ++i;
333  }
334  }
335  mGbEqualities.clear();
336  passGB( );
337  }
338  }
339  // If we always want to check inequalities, we also have to do so when there is no new groebner basis
340  else if( Settings::checkInequalities == ALWAYS )
341  {
342  Answer ans = UNKNOWN;
343  // We only check those inequalities which are new, as the others are unchanged and have already been reduced wrt the latest GB
344  ans = mInequalities.reduceWRTGroebnerBasis( mNewInequalities, mBasis.getIdeal( ), mRewriteRules );
345  // New inequalities are handled now, no need to longer save them as new.
346  mNewInequalities.clear( );
347  // If we managed to get an answer, we can return that.
348  if( ans != UNKNOWN )
349  {
350  return ans;
351  }
352  }
353  assert( mInfeasibleSubsets.empty( ) );
354 
355  #ifdef GB_OUTPUT
356  printRewriteRules();
357  mInequalities.print();
358  std::cout << "Basis" << std::endl;
359  mBasis.getIdeal().print();
360  print();
361  #endif
362 
363  // call other modules as the groebner module cannot decide satisfiability.
364  Answer ans = runBackends();
365  if( ans == UNSAT )
366  {
367  #ifdef SMTRAT_DEVOPTION_Statistics
368  mStats.backendFalse();
369  #endif
370  // use the infeasible subsets from our backends.
371  getInfeasibleSubsets( );
372 
373  assert( !mInfeasibleSubsets.empty( ) );
374  }
375  return ans;
376 }
377 
378 
379 /**
380  * With the new groebner basis, we search for radical-members which then can be added to the GB.
381  * @return
382  */
383 
384 template<class Settings>
385 bool GBModule<Settings>::iterativeVariableRewriting()
386 {
387  std::list<GBPolynomial> polynomials = mBasis.listBasisPolynomials();
388  bool newRuleFound = true;
389  bool gbUpdate = false;
390 
391  // The parameters of the new rule.
392  carl::Variable ruleVar = carl::Variable::NO_VARIABLE;
393  TermT ruleTerm;
394  carl::BitVector ruleReasons;
395 
396  std::map<carl::Variable, std::pair<TermT, carl::BitVector> >& rewrites = mRewriteRules;
397  typename Settings::Groebner basis;
398 
399  while(newRuleFound)
400  {
401  newRuleFound = false;
402 #ifdef GB_OUTPUT
403  std::cout << "current gb" << std::endl;
404  for(typename std::list<GBPolynomial>::const_iterator it = polynomials.begin(); it != polynomials.end(); ++it )
405  {
406  std::cout << *it;
407  it->getReasons().print();
408  std::cout << std::endl;
409  }
410  std::cout << "----" << std::endl;
411 #endif
412 
413  for(typename std::list<GBPolynomial>::iterator it = polynomials.begin(); it != polynomials.end();)
414  {
415  if( it->nr_terms() == 1 && it->lterm().tdeg()==1 )
416  {
417  //TODO optimization, this variable does not appear in the gb.
418  ruleVar = it->lterm().single_variable();
419  ruleTerm = TermT(Rational(0));
420  ruleReasons = it->getReasons();
421  newRuleFound = true;
422  }
423  else if( it->nr_terms() == 2 )
424  {
425  if(it->lterm().tdeg() == 1 )
426  {
427  ruleVar = it->lterm().single_variable();
428  if( it->trailingTerm().has(ruleVar) )
429  {
430  // TODO deduce a factorisation.
431  }
432  else
433  {
434  // learned a rule.
435  ruleTerm = -(it->trailingTerm());
436  ruleReasons = it->getReasons();
437  newRuleFound = true;
438  }
439  }
440  else if(it->trailingTerm().tdeg() == 1 )
441  {
442  ruleVar = it->trailingTerm().single_variable();
443  if( it->lterm().has(ruleVar) )
444  {
445  // TODO deduce a factorisation
446  }
447  else
448  {
449  // learned a rule.
450  it->lterm().divide(-it->trailingTerm().coeff(), ruleTerm);
451  ruleReasons = it->getReasons();
452  newRuleFound = true;
453  }
454  }
455  }
456  if(newRuleFound)
457  {
458  it = polynomials.erase(it);
459  break;
460  }
461  else
462  {
463  ++it;
464  }
465  }
466 
467  if(newRuleFound)
468  {
469  gbUpdate = true;
470  rewrites.insert(std::pair<carl::Variable, std::pair<TermT, carl::BitVector> >(ruleVar, std::pair<TermT, BitVector>(ruleTerm, ruleReasons ) ) );
471 
472  std::list<GBPolynomial> resultingGb;
473  basis.reset();
474  for(typename std::list<GBPolynomial>::const_iterator it = polynomials.begin(); it != polynomials.end(); ++it )
475  {
476  resultingGb.push_back(rewriteVariable(*it,ruleVar, ruleTerm, ruleReasons));
477  basis.addPolynomial(resultingGb.back());
478  #ifdef GB_OUTPUT
479  std::cout << *it << " ---- > ";
480  std::cout.flush();
481  std::cout << resultingGb.back() << std::endl;
482  #endif
483  }
484 
485  if( !basis.inputEmpty( ) )
486  {
487  basis.reduceInput();
488  basis.calculate();
489  polynomials = basis.listBasisPolynomials();
490  }
491 
492  for( std::map<carl::Variable, std::pair<TermT, BitVector> >::iterator it = rewrites.begin(); it != rewrites.end(); ++it )
493  {
494  /// TODO fix this
495  //std::pair<Term, bool> reducedRule = it->second.first.rewriteVariables(ruleVar, ruleTerm);
496  //if(reducedRule.second)
497  //{
498  // it->second.first = reducedRule.first;
499  // it->second.second |= ruleReasons;
500  //}
501  }
502  #ifdef GB_OUTPUT
503  printRewriteRules();
504  #endif
505 
506  }
507  }
508 
509  if( gbUpdate )
510  {
511  mBasis = basis;
512  saveState();
513  }
514 
515  #ifdef SEARCH_FOR_RADICALMEMBERS
516  std::set<unsigned> variableNumbers(mBasis.getGbIdeal().gatherVariables());
517 
518  // find variable rewrite rules
519  // apply the rules RRI-* from the Thesis from G.O. Passmore
520  // Iterate over all variables in the GB
521  for(std::set<unsigned>::const_iterator it = variableNumbers.begin(); it != variableNumbers.end(); ++it) {
522  // We search until a given (static) maximal exponent
523  for(unsigned exponent = 3; exponent <= 17; ++(++exponent) )
524  {
525  // Construct x^exp
526  TermT t(Rational(1), *it, exponent);
527  GBPolynomial reduce(t);
528 
529  // reduce x^exp
530  typename Settings::Reductor reduction( mBasis.getGbIdeal( ), reduce );
531  reduce = reduction.fullReduce( );
532 
533  if( reduce.is_constant() )
534  {
535  // TODO handle 0 and 1.
536  // TODO handle other cases
537  // calculate q-root(reduce);
538  #ifdef SMTRAT_DEVOPTION_Statistics
539  mStats.FoundEqualities();
540  #endif
541  std::cout << t << " -> " << reduce << std::endl;
542 
543  break;
544  }
545  //x^(m+1) - y^(n+1)
546  else if( reduce.isReducedIdentity(*it, exponent))
547  {
548  #ifdef SMTRAT_DEVOPTION_Statistics
549  mStats.FoundIdentities();
550  #endif
551  std::cout << t << " -> " << reduce << std::endl;
552 
553  break;
554  }
555  }
556  }
557 
558 
559  #else
560  return false;
561  #endif
562 }
563 
564 /**
565  * A method which looks for polynomials which have trivial factors.
566  *
567  */
568 template<class Settings>
569 bool GBModule<Settings>::findTrivialFactorisations()
570 {
571  return false;
572 }
573 
574 template<class Settings>
575 void GBModule<Settings>::knownConstraintDeduction(const std::list<std::pair<carl::BitVector,carl::BitVector> >& deductions)
576 {
577  for(auto it = deductions.rbegin(); it != deductions.rend(); ++it)
578  {
579  // if the bitvector is not empty, there is a theory deduction
580  if( Settings::addTheoryDeductions == ALL_CONSTRAINTS && !it->second.empty() )
581  {
582  FormulasT subformulas;
583  FormulasT deduced( generateReasons( it->first ));
584  // When this kind of deduction is greater than one, we would have to determine wich of them is really the deduced one.
585  if( deduced.size() > 1 ) continue;
586  FormulasT originals( generateReasons( it->second ));
587  FormulasT originalsWithoutDeduced;
588 
589  std::set_difference(originals.begin(), originals.end(), deduced.begin(), deduced.end(), std::inserter(originalsWithoutDeduced, originalsWithoutDeduced.end()));
590 
591 
592  for( auto jt = originalsWithoutDeduced.begin(); jt != originalsWithoutDeduced.end(); ++jt )
593  {
594  subformulas.push_back( FormulaT( carl::FormulaType::NOT, *jt ) );
595  }
596 
597  for( auto jt = deduced.begin(); jt != deduced.end(); ++jt )
598  {
599  subformulas.push_back( *jt );
600  }
601 
602  addLemma( FormulaT( carl::FormulaType::OR, subformulas ) );
603  //deduction->print();
604  #ifdef SMTRAT_DEVOPTION_Statistics
605  mStats.DeducedEquality();
606  #endif
607  }
608  }
609 }
610 
611 template<class Settings>
612 void GBModule<Settings>::newConstraintDeduction( )
613 {
614 
615 
616 }
617 
618 /**
619  * Removes the constraint from the GBModule.
620  * Notice: Whenever a constraint is removed which was not asserted before, this leads to an unwanted error.
621  * A general approach for this has to be found.
622  * @param _formula the constraint which should be removed.
623  */
624 template<class Settings>
625 void GBModule<Settings>::removeCore( ModuleInput::const_iterator _formula )
626 {
627  if(_formula->formula().type() != carl::FormulaType::CONSTRAINT) {
628  return;
629  }
630  #ifdef SMTRAT_DEVOPTION_Statistics
631  mStats.constraintRemoved(_formula->formula().constraint().relation());
632  #endif
633  if( constraintByGB(_formula->formula().constraint().relation()))
634  {
635  popBacktrackPoint( _formula );
636  }
637  else
638  {
639  if( Settings::checkInequalities != NEVER )
640  {
641  if (Settings::checkInequalities == ALWAYS)
642  {
643  removeReceivedFormulaFromNewInequalities( _formula );
644  }
645  mInequalities.removeInequality( _formula );
646  }
647  }
648 }
649 
650 /**
651  * Removes a received formula from the list of new inequalities. It assumes that there is only one such element in the list.
652  * @param _formula
653  */
654 template<class Settings>
655 void GBModule<Settings>::removeReceivedFormulaFromNewInequalities( ModuleInput::const_iterator _formula )
656 {
657  for(auto it = mNewInequalities.begin(); it != mNewInequalities.end(); ++it )
658  {
659  if((*it)->first == _formula)
660  {
661  mNewInequalities.erase(it);
662  return;
663  }
664  }
665 }
666 
667 /**
668  * To implement backtrackability, we save the current state after each equality we add.
669  * @param btpoint The equality we have removed
670  */
671 template<class Settings>
672 void GBModule<Settings>::pushBacktrackPoint( ModuleInput::const_iterator btpoint )
673 {
674  assert( mBacktrackPoints.empty( ) || btpoint->formula().type() == carl::FormulaType::CONSTRAINT );
675  assert( mBacktrackPoints.size( ) == mStateHistory.size( ) );
676 
677  // We save the current level
678  if( !mBacktrackPoints.empty( ) )
679  {
680  saveState( );
681  }
682 
683  if( mStateHistory.empty() )
684  {
685  // there are no variable rewrite rules, so we can only push our current basis and empty rewrites
686  mStateHistory.emplace_back( mBasis, std::map<carl::Variable, std::pair<TermT, carl::BitVector> >() );
687  }
688  else
689  {
690  // we save the current basis and the rewrite rules
691  mStateHistory.push_back( GBModuleState<Settings>( mBasis, mRewriteRules ) );
692  }
693 
694  mBacktrackPoints.push_back( btpoint );
695  assert( mBacktrackPoints.size( ) == mStateHistory.size( ) );
696 
697  // If we also handle inequalities in the inequalitiestable, we have to notify it about the extra pushbacktrack point
698  if( Settings::checkInequalities != NEVER )
699  {
700  mInequalities.pushBacktrackPoint( );
701  }
702 }
703 
704 
705 /**
706  * Pops all states from the stack until the state which we had before the constraint was added.
707  * Then, we make new states with all equalities which were added afterwards.
708  * @param a pointer in the received formula to the constraint which will be removed.
709  */
710 template<class Settings>
711 void GBModule<Settings>::popBacktrackPoint( ModuleInput::const_iterator btpoint )
712 {
713  //assert( validityCheck( ) );
714  assert( mBacktrackPoints.size( ) == mStateHistory.size( ) );
715  assert( !mBacktrackPoints.empty( ) );
716 
717  //We first count how far we have to backtrack.
718  //Because the polynomials have to be added again afterwards, we save them in a list.
719  unsigned nrOfBacktracks = 1;
720  std::list<ModuleInput::const_iterator> rescheduled;
721 
722  while( !mBacktrackPoints.empty( ) )
723  {
724  if( mBacktrackPoints.back( ) == btpoint )
725  {
726  mBacktrackPoints.pop_back( );
727  break;
728  }
729  else
730  {
731  ++nrOfBacktracks;
732  rescheduled.push_front(mBacktrackPoints.back());
733  mBacktrackPoints.pop_back( );
734  }
735  }
736 
737  #ifdef SMTRAT_DEVOPTION_Statistics
738  mStats.PopLevel(nrOfBacktracks);
739  #endif
740 
741  for( unsigned i = 0; i < nrOfBacktracks; ++i )
742  {
743  assert( !mStateHistory.empty( ) );
744  mStateHistory.pop_back( );
745  }
746  assert( mBacktrackPoints.size( ) == mStateHistory.size( ) );
747  assert( !mStateHistory.empty( ) );
748 
749  // Load the state to be restored;
750  mBasis = mStateHistory.back( ).getBasis( );
751  mRewriteRules = mStateHistory.back().getRewriteRules();
752  //assert( mBasis.nrOriginalConstraints( ) == mBacktrackPoints.size( ) - 1 );
753 
754  if( Settings::checkInequalities != NEVER )
755  {
756  mInequalities.popBacktrackPoint( nrOfBacktracks );
757  }
758 
759  mRecalculateGB = true;
760  //Add all others
761  for( auto it = rescheduled.begin(); it != rescheduled.end(); ++it )
762  {
763  processNewConstraint(*it);
764  }
765  //assert( mBasis.nrOriginalConstraints( ) == mBacktrackPoints.size( ) - 1 );
766 }
767 
768 #ifdef USE_NSS
769 /**
770  *
771  * @param gb The current Groebner basis.
772  * @return A witness which is zero in case we had no success.
773  */
774 template<class Settings>
775 typename Settings::Polynomial GBModule<Settings>::callGroebnerToSDP( const Ideal& gb )
776 {
777  using namespace reallynull;
778  Poly witness;
779  std::cout << "NSS..?" << std::flush;
780 
781  std::set<unsigned> variables;
782  std::set<unsigned> allVars = gb.gatherVariables( );
783  std::set<unsigned> superfluous = gb.getSuperfluousVariables( );
784  std::set_difference( allVars.begin( ), allVars.end( ),
785  superfluous.begin( ), superfluous.end( ),
786  std::inserter( variables, variables.end( ) ) );
787 
788  unsigned vars = variables.size( );
789  // We currently only try with a low nr of variables.
790  if( vars < Settings::SDPupperBoundNrVariables )
791  {
792  std::cout << " Run SDP.." << std::flush;
793 
794  GroebnerToSDP<typename Settings::Order> sdp( gb, MonomialIterator( variables, Settings::maxSDPdegree ) );
795  witness = sdp.findWitness( );
796  }
797  std::cout << std::endl;
798  if( !carl::is_zero(witness) ) std::cout << "Found witness: " << witness << std::endl;
799  return witness;
800 }
801 #endif
802 
803 /**
804  * Transforms a given inequality to a polynomial such that p = 0 is equivalent to the given constraint.
805  * This is done by inserting an additional variable which has an index which is given by the id of the given inequality.
806  * @param constraint a pointer to the inequality
807  * @return The polynomial which represents the equality.
808  */
809 template<class Settings>
810 typename GBModule<Settings>::GBPolynomial GBModule<Settings>::transformIntoEquality( ModuleInput::const_iterator constraint )
811 {
812  GBPolynomial result( (typename Poly::PolyType)constraint->formula().constraint( ).lhs( ) );
813  const auto& constr = constraint->formula().constraint( );
814  std::map<ConstraintT, carl::Variable>::const_iterator mapentry = mAdditionalVarMap.find( constr );
815  carl::Variable var = carl::Variable::NO_VARIABLE;
816  if( mapentry == mAdditionalVarMap.end( ) )
817  {
818  std::stringstream stream;
819  stream << "AddVarGB" << constr;
820 
821  var = carl::fresh_real_variable( stream.str() );
822  mAdditionalVarMap.insert(std::pair<ConstraintT, carl::Variable>(constr, var));
823  }
824  else
825  {
826  var = mapentry->second;
827  }
828 
829  // Modify to reflect inequalities.
830  switch( constraint->formula().constraint( ).relation( ) )
831  {
832  case carl::Relation::GEQ:
833  result = result + TermT( -1, var, 2 );
834  break;
835  case carl::Relation::LEQ:
836  result = result + TermT( 1, var, 2 );
837  break;
838  case carl::Relation::GREATER:
839  result = result * TermT( 1, var, 2 );
840  result = result + TermT( -1 );
841  break;
842  case carl::Relation::LESS:
843  result = result * TermT( 1, var, 2 );
844  result = result + TermT( 1 );
845  break;
846  case carl::Relation::NEQ:
847  result = result * TermT( 1, var, 1);
848  result = result + TermT( 1 );
849  break;
850  default:
851  assert( false );
852  }
853  return result;
854 }
855 
856 /**
857  *
858  * @return
859  */
860 template<class Settings>
861 bool GBModule<Settings>::saveState( )
862 {
863  assert( mStateHistory.size( ) == mBacktrackPoints.size( ) );
864 
865  // TODO fix this copy.
866  mStateHistory.pop_back( );
867  mStateHistory.push_back( GBModuleState<Settings>( mBasis, mRewriteRules ) );
868 
869  return true;
870 }
871 
872 /**
873  * Add the equalities from the Groebner basis to the passed formula. Adds the reason vector.
874  */
875 template<class Settings>
876 void GBModule<Settings>::passGB( )
877 {
878  // This method should only be called if the GB should be passed.
879  assert( Settings::passGB );
880 
881  // Declare a set of reason sets.
882  FormulasT originals;
883 
884  if( !Settings::passWithMinimalReasons )
885  {
886  // In the case we do not want to pass the GB with a minimal reason set,
887  // we calculate the reason set here for all polynomials.
888  for( ModuleInput::const_iterator it = rReceivedFormula().begin( ); it != rReceivedFormula().end( ); ++it )
889  {
890  // Add the constraint if it is of a type that it was handled by the gb.
891  if( constraintByGB(it->formula().constraint( ).relation( )) )
892  {
893  originals.push_back( it->formula() );
894  }
895  }
896  assert(!originals.empty());
897  }
898 
899  // We extract the current polynomials from the Groebner Basis.
900  const std::vector<GBPolynomial>& simplified = mBasis.getBasisPolynomials();
901  // For each polynomial in this Groebner basis,
902  for( typename std::vector<GBPolynomial>::const_iterator simplIt = simplified.begin( ); simplIt != simplified.end( ); ++simplIt )
903  {
904  if( Settings::passWithMinimalReasons )
905  {
906  assert(!simplIt->getReasons().empty( ));
907  // We calculate the reason set for this polynomial in the GB.
908  originals = generateReasons( simplIt->getReasons() );
909  }
910  // The reason set may never be empty.
911  assert(!originals.empty());
912  // We now add polynomial = 0 as a constraint to the passed formula.
913  // We use the originals set calculated before as reason set.
914  assert(!simplIt->is_constant());
915  auto res = addSubformulaToPassedFormula( FormulaT( Poly(typename smtrat::Poly::PolyType((*simplIt))), carl::Relation::EQ ), FormulaT( carl::FormulaType::AND, originals ) );
916  if( res.second )
917  mGbEqualities.push_back(res.first->formula());
918  }
919 }
920 
921 /**
922  * Generate reason sets from reason vectors
923  * @param reasons The reasons vector.
924  * @return The reason set.
925  */
926 template<class Settings>
927 FormulasT GBModule<Settings>::generateReasons( const carl::BitVector& reasons )
928 {
929  if(reasons.empty())
930  {
931  return FormulasT();
932  }
933 
934  carl::BitVector::const_iterator origIt = reasons.begin( );
935  origIt++;
936  FormulasT origins;
937 
938  auto it = mBacktrackPoints.begin( );
939  for( ++it; it != mBacktrackPoints.end( ); ++it )
940  {
941  assert( (*it)->formula().type() == carl::FormulaType::CONSTRAINT );
942  assert( Settings::transformIntoEqualities != NO_INEQUALITIES || (*it)->formula().constraint( ).relation( ) == carl::Relation::EQ );
943  // If the corresponding entry in the reason vector is set,
944  // we add the polynomial.
945  if( origIt.get( ) )
946  {
947  origins.push_back( (*it)->formula() );
948  }
949  origIt++;
950  }
951  return origins;
952 
953 }
954 
955 /**
956  * Generate reason sets from reason vectors
957  * @param reasons The reasons vector.
958  * @return The reason set.
959  */
960 template<class Settings>
961 FormulaSetT GBModule<Settings>::generateReasonSet( const carl::BitVector& reasons )
962 {
963  if(reasons.empty())
964  {
965  return FormulaSetT();
966  }
967 
968  carl::BitVector::const_iterator origIt = reasons.begin( );
969  origIt++;
970  FormulaSetT origins;
971 
972  auto it = mBacktrackPoints.begin( );
973  for( ++it; it != mBacktrackPoints.end( ); ++it )
974  {
975  assert( (*it)->formula().type() == carl::FormulaType::CONSTRAINT );
976  assert( Settings::transformIntoEqualities != NO_INEQUALITIES || (*it)->formula().constraint( ).relation( ) == carl::Relation::EQ );
977  // If the corresponding entry in the reason vector is set,
978  // we add the polynomial.
979  if( origIt.get( ) )
980  {
981  origins.insert( (*it)->formula() );
982  }
983  origIt++;
984  }
985  return origins;
986 
987 }
988 
989 /**
990  * A validity check of the data structures which can be used to assert valid behaviour.
991  * @return true, iff the backtrackpoints are valid.
992  */
993 template<class Settings>
994 bool GBModule<Settings>::validityCheck( )
995 {
996  auto btp = mBacktrackPoints.begin( );
997  ++btp;
998  for( auto it = rReceivedFormula().begin( ); it != rReceivedFormula().end( ); ++it )
999  {
1000  bool isInGb = constraintByGB(it->formula().constraint( ).relation( ));
1001 
1002  if( isInGb )
1003  {
1004  if( it != *btp )
1005  {
1006 // print( );
1007 // printStateHistory( );
1008 // std::cout << *it << " (Element in received formula) != " << **btp << "(Backtrackpoint)" << std::endl;
1009  return false;
1010  }
1011  ++btp;
1012  }
1013  }
1014  return true;
1015 }
1016 
1017 /**
1018  * This function is overwritten such that it is visible to the InequalitiesTable.
1019  * For more details take a look at Module::eraseSubformulaFromPassedFormula(..)
1020  * @param _formula
1021  */
1022 template<class Settings>
1023 void GBModule<Settings>::removeSubformulaFromPassedFormula( ModuleInput::iterator _formula )
1024 {
1025  super::eraseSubformulaFromPassedFormula( _formula, true );
1026 }
1027 
1028 #ifdef GB_OUTPUT_METHODS
1029 
1030 /**
1031  * Prints the state history.
1032  */
1033 template<class Settings>
1034 void GBModule<Settings>::printStateHistory( )
1035 {
1036  std::cout << "[";
1037  auto btp = mBacktrackPoints.begin( );
1038  for( auto it = mStateHistory.begin( ); it != mStateHistory.end( ); ++it )
1039  {
1040  std::cout << (*btp)->formula() << ": ";
1041  it->getBasis( ).getIdeal( ).print( );
1042  std::cout << "," << std::endl;
1043  btp++;
1044  }
1045  std::cout << "]" << std::endl;
1046 }
1047 
1048 /**
1049  * Prints the rewrite rules.
1050  */
1051 template<class Settings>
1052 void GBModule<Settings>::printRewriteRules( )
1053 {
1054  for(auto it = mRewriteRules.begin(); it != mRewriteRules.end(); ++it)
1055  {
1056  std::cout << it->first << " -> " << it->second.first << " [";
1057  it->second.second.print();
1058  std::cout << "]" << std::endl;
1059  }
1060 }
1061 #endif
1062 
1063 } // namespace smtrat
1064 
1065