6 * Initializes the inequalities table
9 template<class Settings>
10 InequalitiesTable<Settings>::InequalitiesTable( GBModule<Settings>* module ) : mModule( module )
13 mNewConstraints = mReducedInequalities.begin( );
17 * Adds the constraint as a row to the inequalities table.
18 * @param received A pointer from the receivedFormula to the inequality.
19 * @return The position in the inequalities table.
22 template<class Settings>
23 typename InequalitiesTable<Settings>::Rows::iterator InequalitiesTable<Settings>::InsertReceivedFormula( ModuleInput::const_iterator received )
25 assert( received->formula().constraint().relation() != carl::Relation::EQ );
26 // We assume that the just added formula is the last one.
27 ModuleInput::iterator passedEntry = mModule->addReceivedSubformulaToPassedFormula(received).first;
28 // And we add a row to our table
29 return mReducedInequalities.insert( Row( received, RowEntry( passedEntry, received->formula().constraint( ).relation( ), std::list<CellEntry > (1, CellEntry( 0, Polynomial( (typename Poly::PolyType)received->formula().constraint( ).lhs( ) ) )) ) ) ).first;
33 * Informs the inequalities table that new reductions are with respect to the GB with the latest btpoint.
36 template<class Settings>
37 void InequalitiesTable<Settings>::pushBacktrackPoint( )
40 if( Settings::setCheckInequalitiesToBeginAfter > 1 )
42 if( mLastRestart + Settings::setCheckInequalitiesToBeginAfter == mBtnumber )
44 mNewConstraints = mReducedInequalities.begin( );
50 * Clears cells from the inequalities table with backtrack points from the latest nrOfBacktracks many backtrackpoints.
51 * Also updates the new backtracknumber.
52 * @param nrOfBacktracks How many backtrack points are popped.
55 template<class Settings>
56 void InequalitiesTable<Settings>::popBacktrackPoint( unsigned nrOfBacktracks )
58 assert( mBtnumber >= nrOfBacktracks );
59 mBtnumber -= nrOfBacktracks;
60 for( auto it = mReducedInequalities.begin( ); it != mReducedInequalities.end( ); ++it )
62 typename std::list<CellEntry>::iterator listEnd = std::get < 2 > (it->second).end( );
63 for( typename std::list<CellEntry>::iterator jt = std::get < 2 > (it->second).begin( ); jt != listEnd; ++jt )
65 if( jt->first > mBtnumber )
67 std::get < 2 > (it->second).erase( jt, listEnd );
69 if( Settings::passInequalities == FULL_REDUCED_IF )
71 pass = Settings::passPolynomial::evaluate( std::get < 2 > (it->second).front( ).second, std::get < 2 > (it->second).back( ).second );
75 if( Settings::passInequalities == AS_RECEIVED )
77 if( std::get < 0 > (it->second) == mModule->rPassedFormula().end( ) )
79 // we had reduced it to true, therefore not passed it, but now we have to pass the original one again
80 std::get < 0 > (it->second) = mModule->addReceivedSubformulaToPassedFormula( it->first ).first;
85 if( std::get < 0 > (it->second) != mModule->rPassedFormula().end( ) )
87 // we can of course only remove something which is in the formula
89 // TODO (from Florian): store the reasons formula somewhere, such that we only construct it if the reasons vector has been changed
90 FormulasT subformulas = mModule->generateReasons(std::get<2>(it->second).back( ).second.getReasons() );
91 subformulas.push_back( it->first->formula() );
92 FormulaT origin = FormulaT( carl::FormulaType::AND, subformulas );
93 mModule->removeOrigin( std::get < 0 > (it->second), origin );
94 // mModule->removeSubformulaFromPassedFormula( std::get < 0 > (it->second) );
96 if( Settings::passInequalities == FULL_REDUCED || (Settings::passInequalities == FULL_REDUCED_IF && pass) )
98 const carl::BitVector& reasons = std::get<2>(it->second).back( ).second.getReasons();
101 std::get < 0 > (it->second) = mModule->addReceivedSubformulaToPassedFormula( it->first ).first;
105 FormulaT simplifiedConstraint = FormulaT( Poly(typename smtrat::Poly::PolyType(std::get<2>(it->second).back().second)), std::get<1>(it->second) );
106 assert( simplifiedConstraint.type() != carl::FormulaType::FALSE );
107 if( simplifiedConstraint.type() == carl::FormulaType::TRUE )
109 std::get < 0 > (it->second) = mModule->passedFormulaEnd();
113 FormulasT sformulas = mModule->generateReasons(reasons);
114 sformulas.push_back( it->first->formula() );
115 FormulaT originals = FormulaT( carl::FormulaType::AND, sformulas);
116 // we update the reference to the passed formula again
117 std::get < 0 > (it->second) = mModule->addSubformulaToPassedFormula( simplifiedConstraint, originals ).first;
123 assert( Settings::passInequalities == FULL_REDUCED_IF );
124 // we pass the original one and update the reference to the passed formula again
125 std::get < 0 > (it->second) = mModule->addReceivedSubformulaToPassedFormula( it->first ).first;
135 * Reduce all rows with respect to the given Groebner basis.
136 * @param gb The groebner basis
137 * @return If one of the inequalities yields a contradiction, UNSAT, else Unknown.
140 template<class Settings>
141 Answer InequalitiesTable<Settings>::reduceWRTGroebnerBasis( const Ideal& gb, const RewriteRules& rules )
143 for( auto it = mReducedInequalities.begin( ); it != mReducedInequalities.end( ); ++it )
145 // The formula is not passed because it is unsatisfiable.
146 if( !reduceWRTGroebnerBasis( it, gb, rules ) ) {
147 #ifdef SMTRAT_DEVOPTION_Statistics
148 mStats.infeasibleInequality();
150 if( Settings::withInfeasibleSubset == RETURN_DIRECTLY )
156 if( Settings::withInfeasibleSubset != RETURN_DIRECTLY )
158 if( mModule->mInfeasibleSubsets.empty( ) )
164 #ifdef SMTRAT_DEVOPTION_Statistics
165 mStats.infeasibleInequality();
178 * Reduce the given rows with respect to the given Groebner basis.
179 * @param ineqToBeReduced A list of rows which should be updated.
180 * @param gb The Groebner basis.
181 * @return If one of the inequalities yields a contradiction, UNSAT, else Unknown.
184 template<class Settings>
185 Answer InequalitiesTable<Settings>::reduceWRTGroebnerBasis( const std::list<typename Rows::iterator>& ineqToBeReduced, const Ideal& gb, const RewriteRules& rules )
187 for( auto it = ineqToBeReduced.begin( ); it != ineqToBeReduced.end( ); ++it )
189 assert( std::get < 1 > ((*it)->second) != carl::Relation::EQ );
190 if( !reduceWRTGroebnerBasis( *it, gb, rules ) ) {
191 #ifdef SMTRAT_DEVOPTION_Statistics
192 mStats.infeasibleInequality();
194 if( Settings::withInfeasibleSubset == RETURN_DIRECTLY )
200 if( Settings::withInfeasibleSubset != RETURN_DIRECTLY )
202 if( mModule->mInfeasibleSubsets.empty( ) )
208 #ifdef SMTRAT_DEVOPTION_Statistics
209 mStats.infeasibleInequality();
221 * Reduce the given row with respect to the given Groebner basis.
222 * @param ineqToBeReduced A pointer to the row which should be updated.
223 * @param gb The Groebner basis.
224 * @return If one of the inequalities yields a contradiction, false, else true.
227 template<class Settings>
228 bool InequalitiesTable<Settings>::reduceWRTGroebnerBasis( typename Rows::iterator it, const Ideal& gb, const RewriteRules& rules )
230 assert( std::get < 1 > (it->second) != carl::Relation::EQ );
231 // Check if constraint has already been reduced to true (no further reduction possible).
232 if( std::get < 0 > (it->second) == mModule->passedFormulaEnd() ) return true;
234 Polynomial& p = std::get<2>(it->second).back( ).second;
237 bool reductionOccured = false;
238 bool rewriteOccured = false;
239 if( !carl::is_zero(p) && !p.is_constant( ) )
241 if(rules.size() == 0)
243 typename Settings::Reductor reductor( gb, p );
244 reduced = reductor.fullReduce( );
245 reductionOccured = reductor.reductionOccured( );
249 Polynomial ptemp = groebner::rewritePolynomial(p, rules);
251 rewriteOccured = (ptemp != p);
252 if( !carl::is_zero(ptemp) && !ptemp.is_constant() )
254 typename Settings::Reductor reductor( gb, ptemp );
255 reduced = reductor.fullReduce( );
256 reductionOccured = reductor.reductionOccured( );
261 reduced.setReasons(ptemp.getReasons());
266 carl::Relation relation = std::get < 1 > (it->second);
267 if( rewriteOccured || reductionOccured )
269 assert(std::get < 0 > (it->second) != mModule->passedFormulaEnd());
270 if( carl::is_zero(reduced) || reduced.is_constant( ) )
272 bool satisfied = false;
273 if( carl::is_zero(reduced) && is_weak( relation ) )
275 assert( is_weak( relation ) );
278 else if( !carl::is_zero(reduced) )
280 assert( reduced.nr_terms( ) > 0 );
281 assert( reduced.lcoeff( ) != 0 );
283 smtrat::Rational reducedConstant = reduced.lcoeff( );
284 assert( reducedConstant != 0 );
285 if( reducedConstant < 0 )
287 if( relation == carl::Relation::LESS || relation == carl::Relation::LEQ || relation == carl::Relation::NEQ )
294 if( relation == carl::Relation::GREATER || relation == carl::Relation::GEQ || relation == carl::Relation::NEQ )
303 // remove the last formula
305 if( std::get < 0 > (it->second) != mModule->passedFormulaEnd( ) )
307 // TODO (from Florian): store the reasons formula somewhere, such that we only construct it if the reasons vector has been changed
308 FormulasT subformulas = mModule->generateReasons(std::get<2>(it->second).back( ).second.getReasons() );
309 subformulas.push_back( it->first->formula() );
310 FormulaT origin = FormulaT( carl::FormulaType::AND, subformulas );
311 mModule->removeOrigin( std::get < 0 > (it->second), origin );
312 // mModule->removeSubformulaFromPassedFormula( std::get < 0 > (it->second) );
313 std::get < 0 > (it->second) = mModule->passedFormulaEnd( );
316 std::get < 2 > (it->second).push_back( CellEntry( mBtnumber, reduced ) ); // TODO: Is this necessary?
317 if( Settings::addTheoryDeductions != NO_CONSTRAINTS )
319 // TODO: Why is the following disabled?
320 // FormulasT originals = mModule->generateReasons( reduced.getReasons( ) );
321 // FormulasT subformulas;
322 // for( auto jt = originals.begin(); jt != originals.end(); ++jt )
324 // subformulas.insert( FormulaT( carl::FormulaType::NOT, *jt ) );
326 // subformulas.insert( it->first->formula() );
328 // std::cout << "Id="<<(*(it->first))->pConstraint()->id()<<std::endl;
329 // std::cout << "Gb learns: ";
330 // deduction->print();
331 // std::cout << std::endl;
332 // mModule->addLemma( FormulaT( carl::FormulaType::carl::FormulaType::OR, subformulas ) ); // TODO: Florian ask Sebastian, why he commented that line
333 #ifdef SMTRAT_DEVOPTION_Statistics
334 mStats.DeducedInequality();
339 else // we have a conflict
342 FormulaSetT infeasibleSubset( mModule->generateReasonSet( reduced.getReasons( ) ) );
343 infeasibleSubset.insert( it->first->formula() );
344 #ifdef SMTRAT_DEVOPTION_Statistics
345 mStats.EffectivenessOfConflicts(infeasibleSubset.size()/mModule->rReceivedFormula().size());
346 #endif //SMTRAT_DEVOPTION_Statistics
347 mModule->mInfeasibleSubsets.push_back( infeasibleSubset );
348 if( Settings::withInfeasibleSubset == RETURN_DIRECTLY )
354 else if( Settings::withInfeasibleSubset == PROCEED_ALLINEQUALITIES || mModule->mInfeasibleSubsets.empty( ) )
357 if( Settings::passInequalities == FULL_REDUCED_IF )
359 pass = Settings::passPolynomial::evaluate( std::get < 2 > (it->second).front( ).second, reduced );
362 if( Settings::passInequalities == FULL_REDUCED || (Settings::passInequalities == FULL_REDUCED_IF && pass) )
364 //remove the last one
366 // TODO (from Florian): store the reasons formula somewhere, such that we only construct it if the reasons vector has been changed
367 FormulasT subformulas = mModule->generateReasons(std::get<2>(it->second).back( ).second.getReasons() );
368 subformulas.push_back( it->first->formula() );
369 FormulaT origin = FormulaT( carl::FormulaType::AND, subformulas );
370 mModule->removeOrigin( std::get < 0 > (it->second), origin );
371 // mModule->removeSubformulaFromPassedFormula( std::get < 0 > (it->second) );
374 std::get < 2 > (it->second).push_back( CellEntry( mBtnumber, reduced ) );
375 if( Settings::passInequalities == FULL_REDUCED || (Settings::passInequalities == FULL_REDUCED_IF && pass) )
377 FormulaT redResult = FormulaT( Poly(typename smtrat::Poly::PolyType(reduced)), relation );
378 switch( redResult.type() )
380 case carl::FormulaType::TRUE:
384 case carl::FormulaType::FALSE:
386 FormulaSetT infeasibleSubset( mModule->generateReasonSet( reduced.getReasons( ) ) );
387 infeasibleSubset.insert( it->first->formula() );
388 #ifdef SMTRAT_DEVOPTION_Statistics
389 mStats.EffectivenessOfConflicts(infeasibleSubset.size()/mModule->rReceivedFormula().size());
390 #endif //SMTRAT_DEVOPTION_Statistics
391 mModule->mInfeasibleSubsets.push_back( infeasibleSubset );
392 if( Settings::withInfeasibleSubset == RETURN_DIRECTLY )
400 assert( redResult.type() == carl::FormulaType::CONSTRAINT );
401 // get the reason set for the reduced polynomial
402 FormulasT originals = mModule->generateReasons( reduced.getReasons( ) );
403 originals.push_back( it->first->formula() );
406 //TODO: replace "Formula::constraintPool().variables()" by a smaller approximations of the variables contained in "reduced.toEx( )"
407 // and set the pointer to the passed formula accordingly.
408 std::get < 0 > (it->second) = mModule->addSubformulaToPassedFormula( redResult, FormulaT( carl::FormulaType::AND, originals ) ).first;
412 // new constraint learning
413 // If the original constraint is nonlinear
414 /*if( !((*(it->first))->pConstraint( ))->is_linear() )
416 // We only want to learn linear constraints.
417 if( reduced.is_linear() )
419 // get the reason set for the reduced polynomial
420 FormulasT subformulas;
421 std::vector<FormulasT > originals;
422 originals.push_back( mModule->generateReasons( reduced.getOrigins( ).getBitVector( ) ) );
424 for( auto jt = originals.front().begin(); jt != originals.front().end(); ++jt )
426 subformulas.insert( FormulaT( carl::FormulaType::NOT, *it ) );
428 subformulas.insert( FormulaT( carl::FormulaType::NOT, *it->first ) );
429 subformulas.insert( FormulaT( reduced.toEx( ), relation ) );
430 //mModule->addLemma( FormulaT( carl::FormulaType::OR, subformulas ) );
438 template<class Settings>
439 Answer InequalitiesTable<Settings>::reduceWRTVariableRewriteRules(const RewriteRules& rules)
441 for( auto it = mReducedInequalities.begin( ); it != mReducedInequalities.end( ); ++it )
443 assert( std::get < 1 > ((*it)->second) != carl::Relation::EQ );
444 if( !reduceWRTVariableRewriteRules( *it, rules ) ) {
445 #ifdef SMTRAT_DEVOPTION_Statistics
446 mStats.infeasibleInequality();
448 if( Settings::withInfeasibleSubset == RETURN_DIRECTLY )
454 if( Settings::withInfeasibleSubset != RETURN_DIRECTLY )
456 if( mModule->mInfeasibleSubsets.empty( ) )
462 #ifdef SMTRAT_DEVOPTION_Statistics
463 mStats.infeasibleInequality();
474 template<class Settings>
475 Answer InequalitiesTable<Settings>::reduceWRTVariableRewriteRules(const std::list< typename Rows::iterator>& ineqToBeReduced, const RewriteRules& rules )
477 for( auto it = ineqToBeReduced.begin( ); it != ineqToBeReduced.end( ); ++it )
479 assert( std::get < 1 > ((*it)->second) != carl::Relation::EQ );
480 if( !reduceWRTVariableRewriteRules( *it, rules ) ) {
481 #ifdef SMTRAT_DEVOPTION_Statistics
482 mStats.infeasibleInequality();
484 if( Settings::withInfeasibleSubset == RETURN_DIRECTLY )
490 if( Settings::withInfeasibleSubset != RETURN_DIRECTLY )
492 if( mModule->mInfeasibleSubsets.empty( ) )
498 #ifdef SMTRAT_DEVOPTION_Statistics
499 mStats.infeasibleInequality();
510 template<class Settings>
511 bool InequalitiesTable<Settings>::reduceWRTVariableRewriteRules( typename Rows::iterator , const RewriteRules& )
513 /// TODO implement or erase
520 * Removes the row corresponding to this constraint from the inequalities table.
521 * @param _formula A pointer to the constraint in the receivedFormula which has to be removed.
524 template<class Settings>
525 void InequalitiesTable<Settings>::removeInequality( ModuleInput::const_iterator _formula )
527 mReducedInequalities.erase( _formula );
528 if( mNewConstraints != mReducedInequalities.end( ) && _formula == mNewConstraints->first )
535 * A print function for the inequalitiestable
539 template<class Settings>
540 void InequalitiesTable<Settings>::print( std::ostream& os ) const
542 os << "Bt: " << mBtnumber << std::endl;
543 for( auto it = mReducedInequalities.begin( ); it != mReducedInequalities.end( ); ++it )
545 typename std::list<CellEntry>::const_iterator listEnd = std::get < 2 > (it->second).end( );
546 os << it->first->formula() << " -> ";
547 if( std::get<0>(it->second) == mModule->passedFormulaEnd() )
548 os << "true" << std::endl;
550 os << std::get<0>(it->second)->formula() << std::endl;
551 for(typename std::list<CellEntry>::const_iterator jt = std::get < 2 > (it->second).begin( ); jt != listEnd; ++jt )
553 os << "\t(" << jt->first << ") " << jt->second << " [";
554 jt->second.getReasons().print();
555 os << "] " << std::endl;