3 * @author Stefan Schupp <stefan.schupp@rwth-aachen.de>
4 * @author Florian Corzilius <corzilius@cs.rwth-aachen.de>
6 * Created on October 16, 2012, 1:07 PM
12 #include <smtrat-solver/Manager.h>
13 #include "ICPModule.h"
15 //#define ICP_MODULE_DEBUG_METHODS
16 //#define ICP_MODULE_DEBUG_0
17 //#define ICP_MODULE_DEBUG_1
18 //#define ICP_MODULE_DEBUG_2
19 //#define ICP_MODULE_SHOW_PROGRESS
21 #ifdef ICP_MODULE_DEBUG_2
22 #ifndef ICP_MODULE_DEBUG_1
23 #define ICP_MODULE_DEBUG_1
27 #ifdef ICP_MODULE_DEBUG_1
28 #ifndef ICP_MODULE_DEBUG_0
29 #define ICP_MODULE_DEBUG_0
35 template<class Settings>
36 ICPModule<Settings>::ICPModule( const ModuleInput* _formula, Conditionals& _conditionals, Manager* const _manager ):
37 Module( _formula, _conditionals, _manager ),
40 mActiveNonlinearConstraints(),
41 mActiveLinearConstraints(),
43 mNonlinearConstraints(),
44 mNotEqualConstraints(),
48 mIcpRelevantCandidates(),
51 mVariableLinearizations(),
53 mHistoryRoot(new icp::HistoryNode(mIntervals)),
54 mHistoryActual(nullptr),
55 mValidationFormula(new ModuleInput()),
56 mLRAFoundAnswer( std::vector< std::atomic_bool* >( 1, new std::atomic_bool( false ) ) ),
57 mLRA(mValidationFormula, mLRAFoundAnswer),
59 mIsIcpInitialized(false),
60 mSplitOccurred(false),
62 mTargetDiameter(Settings::target_diameter_nra),
63 mContractionThreshold(Settings::contraction_threshold_nra),
64 mDefaultSplittingSize(Settings::default_splitting_size_nra),
65 mSplittingHeuristic(Settings::splitting_heuristic_nra),
66 mNumberOfReusagesAfterTargetDiameterReached(Settings::number_of_reusages_after_target_diameter_reached),
67 mRelativeContraction(0),
68 mAbsoluteContraction(0),
69 mCountBackendCalls(0),
73 if( mpManager != nullptr && mpManager->logic() == carl::Logic::QF_NIA )
75 mTargetDiameter = Settings::target_diameter_nia;
76 mContractionThreshold = Settings::contraction_threshold_nia;
77 mDefaultSplittingSize = Settings::default_splitting_size_nia;
78 mSplittingHeuristic = Settings::splitting_heuristic_nia;
82 template<class Settings>
83 ICPModule<Settings>::~ICPModule()
85 while( !mLRAFoundAnswer.empty() )
87 std::atomic_bool* toDel = mLRAFoundAnswer.back();
88 mLRAFoundAnswer.pop_back();
91 mLRAFoundAnswer.clear();
93 delete mValidationFormula;
94 for( auto variableIt = mVariables.begin(); variableIt != mVariables.end(); ++variableIt )
95 delete (*variableIt).second;
97 #ifdef ICP_MODULE_SHOW_PROGRESS
98 std::cout << std::endl;
102 template<class Settings>
103 bool ICPModule<Settings>::informCore( const FormulaT& _constraint )
105 #ifdef ICP_MODULE_DEBUG_1
106 std::cout << "[ICP] inform: " << _constraint << std::endl;
108 if( _constraint.type() == carl::FormulaType::CONSTRAINT )
110 const ConstraintT& constraint = _constraint.constraint();
111 if( !constraint.integer_valued() )
112 mDefaultSplittingSize = 1000;
113 unsigned constraintConsistency = constraint.is_consistent();
114 if( constraintConsistency == 2 && _constraint.constraint().relation() != carl::Relation::NEQ )
115 addConstraint( _constraint );
116 return constraintConsistency != 0;
121 template<class Settings>
122 bool ICPModule<Settings>::addCore( ModuleInput::const_iterator _formula )
124 switch( _formula->formula().type() )
126 case carl::FormulaType::FALSE:
128 FormulaSetT infSubSet;
129 infSubSet.insert( _formula->formula() );
130 mInfeasibleSubsets.push_back( infSubSet );
131 mFoundSolution.clear();
134 case carl::FormulaType::TRUE:
138 case carl::FormulaType::CONSTRAINT:
140 const ConstraintT& constr = _formula->formula().constraint();
141 // create and initialize slackvariables
142 if (carl::satisfied_by(constr, mFoundSolution) != 1 )
143 mFoundSolution.clear();
144 if( !mIsIcpInitialized )
149 for( const auto& lem : mLRA.lemmas() )
151 #ifdef ICP_MODULE_DEBUG_2
152 std::cout << "Create lemma for: " << lem.mLemma << std::endl;
154 FormulaT lemma = getReceivedFormulas( lem.mLemma );
155 addLemma(lemma, lem.mLemmaType);
156 #ifdef ICP_MODULE_DEBUG_2
157 std::cout << "Passed lemma: " << lemma << std::endl;
161 mIsIcpInitialized = true;
163 // Handle Not Equal separate
164 if( constr.relation() == carl::Relation::NEQ ) {
165 mNotEqualConstraints.insert(_formula->formula());
166 addReceivedSubformulaToPassedFormula(_formula);
169 #ifdef ICP_MODULE_DEBUG_1
170 std::cout << "[ICP] Assertion: " << constr << std::endl;
172 if( !carl::is_bound(_formula->formula().constraint()) )
174 // TODO: here or somewhere later in isConsistent: remove constraints from passed formula which are implied by the current box
175 addSubformulaToPassedFormula( _formula->formula(), _formula->formula() );
176 for( auto var : _formula->formula().constraint().variables() )
178 auto iter = mVariables.find( var );
179 if( Settings::original_polynomial_contraction && iter == mVariables.end() )
181 iter->second->addOriginalConstraint( _formula->formula() );
184 // activate associated nonlinear contraction candidates
185 if( !constr.lhs().is_linear() )
186 activateNonlinearConstraint( _formula->formula() );
187 // lookup corresponding linearization - in case the constraint is already linear, mReplacements holds the constraint as the linearized one
188 auto replacementIt = mLinearizations.find( _formula->formula() );
189 assert( replacementIt != mLinearizations.end() );
190 const FormulaT& replacementPtr = (*replacementIt).second;
191 assert( replacementPtr.type() == carl::FormulaType::CONSTRAINT );
192 if( carl::is_bound(replacementPtr.constraint()) )
194 // considered constraint is activated but has no slack variable -> it is a boundary constraint
195 auto res = mValidationFormula->add( replacementPtr );
196 #ifdef ICP_MODULE_DEBUG_1
197 std::cout << "[mLRA] Assert bound constraint: " << replacementPtr << std::endl;
199 // If the constraint has not yet been part of the lramodule's received formula, assert it. If the
200 // lramodule already detects inconsistency, process its infeasible subsets.
201 if( res.second && !mLRA.add( res.first ) )
203 remapAndSetLraInfeasibleSubsets();
204 assert( !mInfeasibleSubsets.empty() );
209 activateLinearConstraint( replacementPtr, _formula->formula() );
220 template<class Settings>
221 void ICPModule<Settings>::removeCore( ModuleInput::const_iterator _formula )
223 if( _formula->formula().type() != carl::FormulaType::CONSTRAINT )
225 const ConstraintT& constr = _formula->formula().constraint();
226 #ifdef ICP_MODULE_DEBUG_1
227 std::cout << "[ICP] Remove Formula " << constr << std::endl;
229 assert( constr.is_consistent() == 2 );
230 if( constr.relation() == carl::Relation::NEQ ) {
231 mNotEqualConstraints.erase(_formula->formula());
234 if( !carl::is_bound(constr) )
236 for( auto var : constr.variables() )
237 mVariables.at(var)->addOriginalConstraint( _formula->formula() );
240 auto iter = mNonlinearConstraints.find( constr );
241 if( iter != mNonlinearConstraints.end() )
243 #ifdef ICP_MODULE_DEBUG_1
244 std::cout << "Nonlinear." << std::endl;
246 for( icp::ContractionCandidate* cc : iter->second )
248 // remove candidate if counter == 1, else decrement counter.
249 assert( cc->isActive() );
250 // remove origin, no matter if constraint is active or not
251 cc->removeOrigin( _formula->formula() );
252 if( cc->activity() == 0 )
254 // reset History to point before this candidate was used
256 // clean up icpRelevantCandidates
257 removeCandidateFromRelevant( cc );
258 mActiveNonlinearConstraints.erase( cc );
263 auto linearization = mLinearizations.find( _formula->formula() );
264 assert( linearization != mLinearizations.end() );
265 const icp::LRAVariable* slackvariable = mLRA.getSlackVariable( linearization->second );
266 assert( slackvariable != nullptr );
267 // lookup if contraction candidates already exist - if so, add origins
268 auto iterB = mLinearConstraints.find( slackvariable );
269 if( iterB != mLinearConstraints.end() )
271 #ifdef ICP_MODULE_DEBUG_1
272 std::cout << "Linear." << std::endl;
274 for( icp::ContractionCandidate* cc : iterB->second )
276 // remove candidate if counter == 1, else decrement counter.
277 // TODO: as the origin has maybe already been removed with removing the origins of non-linear constraints
278 // we need to check the following before. This should be avoided differently.
279 if( cc->hasOrigin( _formula->formula() ) )
281 // remove origin, no matter if constraint is active or not
282 cc->removeOrigin( _formula->formula() );
283 if( cc->activity() == 0 )
285 // reset History to point before this candidate was used
287 // clean up icpRelevantCandidates
288 removeCandidateFromRelevant( cc );
289 mActiveLinearConstraints.erase( cc );
294 // remove constraint from mLRA module
295 auto replacementIt = mLinearizations.find( _formula->formula() );
296 assert( replacementIt != mLinearizations.end() );
297 auto validationFormulaIt = mValidationFormula->find( replacementIt->second );
298 if( validationFormulaIt != mValidationFormula->end() )
300 #ifdef ICP_MODULE_DEBUG_1
301 std::cout << "[mLRA] remove " << validationFormulaIt->formula().constraint() << std::endl;
303 mLRA.remove( validationFormulaIt );
304 mValidationFormula->erase( validationFormulaIt );
308 template<class Settings>
309 Answer ICPModule<Settings>::checkCore()
311 #ifdef ICP_MODULE_DEBUG_0
312 std::cout << "##############################################################" << std::endl;
313 std::cout << "Start consistency check with the ICPModule on the constraints " << std::endl;
314 for( const auto& f : rReceivedFormula() )
315 std::cout << " " << f.formula().constraint() << std::endl;
317 mLRAFoundSolution = false;
318 if( !mFoundSolution.empty() )
320 #ifdef ICP_MODULE_DEBUG_0
321 std::cout << "Found solution still feasible." << std::endl << std::endl;
323 if( checkNotEqualConstraints() )
330 // Debug Outputs of linear and nonlinear Tables
331 #ifdef ICP_MODULE_DEBUG_0
332 #ifdef ICP_MODULE_DEBUG_1
335 std::cout << "Constraints after preprocessing:" << std::endl;
336 printPreprocessedInput( " " );
337 std::cout << std::endl;
340 for( icp::ContractionCandidate* cc : mActiveLinearConstraints )
341 cc->resetReusagesAfterTargetDiameterReached();
342 for( icp::ContractionCandidate* cc : mActiveNonlinearConstraints )
343 cc->resetReusagesAfterTargetDiameterReached();
344 Answer lraAnswer = UNKNOWN;
345 if( initialLinearCheck( lraAnswer ) )
347 if( lraAnswer == SAT )
349 assert( !Settings::just_contraction );
350 if( checkNotEqualConstraints() )
352 #ifdef ICP_MODULE_DEBUG_0
353 std::cout << "Found solution with internal LRAModule!" << std::endl;
355 mLRAFoundSolution = true;
363 #ifdef ICP_MODULE_DEBUG_0
364 std::cout << "Linear constraints not feasible!" << std::endl;
369 #ifdef ICP_MODULE_SHOW_PROGRESS
370 if( mGlobalBoxSize == 0.0 ) mGlobalBoxSize = calculateCurrentBoxSize();
371 mInitialBoxSize = calculateCurrentBoxSize();
373 #ifdef ICP_MODULE_DEBUG_0
374 std::cout << "Start with the intervals" << std::endl;
375 printIntervals( false );
377 contractCurrentBox();
378 if( anAnswerFound() )
380 #ifdef ICP_MODULE_DEBUG_0
381 std::cout << std::endl;
383 // when one interval is empty, we can skip validation and chose next box.
384 if( mInvalidBox ) // box contains no solution
386 #ifdef ICP_MODULE_DEBUG_0
387 std::cout << "Whole box contains no solution! Return UNSAT." << std::endl;
389 // whole box forms infeasible subset
390 mInfeasibleSubsets.push_back( createPremiseDeductions() );
391 #ifdef ICP_MODULE_SHOW_PROGRESS
392 addProgress( mInitialBoxSize );
398 assert( !intervalsEmpty() );
401 #ifdef ICP_MODULE_DEBUG_0
402 std::cout << "Return unknown, raise lemmas for split." << std::endl;
406 if( !Settings::just_contraction && tryTestPoints() )
408 if( checkNotEqualConstraints() )
415 // create Bounds and set them, add to passedFormula
416 pushBoundsToPassedFormula();
417 // lazy call of the backends on found box
418 Answer lazyResult = callBackends( mFinalCheck, false, objective() );
419 if( lazyResult == ABORTED )
421 // if it led to a result or the backends require a splitting
422 if( lazyResult != UNKNOWN || !lemmas().empty() )
424 // Full call of the backends, if no box has target diameter
425 bool furtherContractionOccurred = false;
426 if( !performSplit( mOriginalVariableIntervalContracted, furtherContractionOccurred ) )
427 return callBackends( mFinalCheck, mFullCheck, objective() );
430 #ifdef ICP_MODULE_DEBUG_0
431 std::cout << "Whole box contains no solution! Return UNSAT." << std::endl;
433 // whole box forms infeasible subset
434 mInfeasibleSubsets.push_back( createPremiseDeductions() );
435 #ifdef ICP_MODULE_SHOW_PROGRESS
436 addProgress( mInitialBoxSize );
440 if( furtherContractionOccurred )
448 template<class Settings>
449 void ICPModule<Settings>::resetHistory( icp::ContractionCandidate* _cc )
451 if( mHistoryActual == nullptr )
453 if(mHistoryActual->getCandidates().find(_cc) != mHistoryActual->getCandidates().end())
455 setBox(mHistoryRoot);
456 mHistoryActual->reset();
460 template<class Settings>
461 void ICPModule<Settings>::addConstraint( const FormulaT& _formula )
463 assert( _formula.type() == carl::FormulaType::CONSTRAINT );
464 assert( _formula.constraint().is_consistent() == 2 );
465 const ConstraintT& constraint = _formula.constraint();
466 auto linearization = mLinearizations.find( _formula );
467 if( linearization == mLinearizations.end() ) // If this constraint has not been added before
469 const Poly& constr = constraint.lhs();
470 // add original variables to substitution mapping
471 for( auto var: constraint.variables() )
473 if( mSubstitutions.find( var ) == mSubstitutions.end() )
475 assert( mVariables.find(var) == mVariables.end() );
476 assert( mIntervals.find(var) == mIntervals.end() );
477 mSubstitutions.insert( std::make_pair( var, Poly(var) ) );
478 getIcpVariable( var, true, nullptr ); // note that we have to set the lra variable later
479 mHistoryRoot->addInterval( var, DoubleInterval::unbounded_interval() );
482 // actual preprocessing
483 FormulaT linearFormula = FormulaT( carl::FormulaType::TRUE );
484 if( constr.is_linear() )
485 linearFormula = _formula;
488 assert( mLinearizations.find( _formula ) == mLinearizations.end() );
489 std::vector<Poly> temporaryMonomes = icp::getNonlinearMonomials( constr );
490 assert( !temporaryMonomes.empty() );
491 Poly lhs = createNonlinearCCs( _formula.constraint(), temporaryMonomes );
492 linearFormula = FormulaT( lhs, constraint.relation() );
493 assert( linearFormula.constraint().lhs().is_linear() );
494 #ifdef ICP_MODULE_DEBUG_1
495 std::cout << "linearize constraint to " << linearFormula.constraint() << std::endl;
498 assert( !linearFormula.is_true() );
499 // store replacement for later comparison when asserting
500 assert( mDeLinearizations.find( linearFormula ) == mDeLinearizations.end() );
501 assert( mLinearizations.find( _formula ) == mLinearizations.end() );
502 mDeLinearizations[linearFormula] = _formula;
503 mLinearizations[_formula] = linearFormula;
504 // inform internal LRAmodule of the linearized constraint
505 mLRA.inform( linearFormula );
506 const ConstraintT& linearizedConstraint = linearFormula.constraint();
507 #ifdef ICP_MODULE_DEBUG_1
508 std::cout << "[mLRA] inform: " << linearizedConstraint << std::endl;
510 if( !carl::is_bound(linearizedConstraint) || (Settings::original_polynomial_contraction && !_formula.constraint().lhs().is_linear()) )
511 createLinearCCs( linearFormula, _formula );
512 // set the lra variables for the icp variables regarding variables (introduced and original ones)
513 // TODO: Refactor this last part - it seems to be too complicated
514 for( auto var: linearizedConstraint.variables() )
516 auto iter = mVariables.find( var );
517 if( Settings::original_polynomial_contraction && iter == mVariables.end() )
519 assert( iter != mVariables.end() );
520 if( iter->second->lraVar() == nullptr )
522 auto ovarIter = mLRA.originalVariables().find( var );
523 if( ovarIter != mLRA.originalVariables().end() )
524 iter->second->setLraVar( ovarIter->second );
530 template<class Settings>
531 icp::IcpVariable* ICPModule<Settings>::getIcpVariable( carl::Variable::Arg _var, bool _original, const icp::LRAVariable* _lraVar )
533 auto iter = mVariables.find( _var );
534 if( iter != mVariables.end() )
536 auto res = mIntervals.insert( std::make_pair( _var, DoubleInterval::unbounded_interval() ) );
537 assert( res.second );
538 icp::IcpVariable* icpVar = new icp::IcpVariable( _var, _original, passedFormulaEnd(), res.first, _lraVar );
539 mVariables.insert( std::make_pair( _var, icpVar ) );
543 template<class Settings>
544 void ICPModule<Settings>::activateNonlinearConstraint( const FormulaT& _formula )
546 assert( _formula.type() == carl::FormulaType::CONSTRAINT );
547 auto iter = mNonlinearConstraints.find( _formula.constraint() );
548 #ifdef ICP_MODULE_DEBUG_1
549 std::cout << "[ICP] Assertion (nonlinear)" << _formula.constraint() << std::endl;
550 std::cout << "mNonlinearConstraints.size: " << mNonlinearConstraints.size() << std::endl;
551 std::cout << "Number Candidates: " << iter->second.size() << std::endl;
553 for( auto candidateIt = iter->second.begin(); candidateIt != iter->second.end(); ++candidateIt )
555 if( (*candidateIt)->activity() == 0 )
557 mActiveNonlinearConstraints.insert( *candidateIt );
558 #ifdef ICP_MODULE_DEBUG_1
559 std::cout << "[ICP] Activated candidate: ";
560 (*candidateIt)->print();
563 (*candidateIt)->addOrigin( _formula );
564 #ifdef ICP_MODULE_DEBUG_1
565 std::cout << "[ICP] Increased candidate count: ";
566 (*candidateIt)->print();
571 template<class Settings>
572 void ICPModule<Settings>::activateLinearConstraint( const FormulaT& _formula, const FormulaT& _origin )
574 assert( _formula.type() == carl::FormulaType::CONSTRAINT );
575 const icp::LRAVariable* slackvariable = mLRA.getSlackVariable( _formula );
576 assert( slackvariable != nullptr );
577 // lookup if contraction candidates already exist - if so, add origins
578 auto iter = mLinearConstraints.find( slackvariable );
579 assert( iter != mLinearConstraints.end() );
580 for ( auto candidateIt = iter->second.begin(); candidateIt != iter->second.end(); ++candidateIt )
582 #ifdef ICP_MODULE_DEBUG_2
583 std::cout << "[ICP] ContractionCandidates already exist: ";
584 slackvariable->print();
585 std::cout << ", Size Origins: " << (*candidateIt)->origin().size() << std::endl;
586 std::cout << _formula << std::endl;
587 (*candidateIt)->print();
588 std::cout << "Adding origin." << std::endl;
590 // set value in activeLinearConstraints
591 if( (*candidateIt)->activity() == 0 )
592 mActiveLinearConstraints.insert( *candidateIt );
594 (*candidateIt)->addOrigin( _origin );
598 auto res = mValidationFormula->add( _formula );
601 if( !mLRA.add( res.first ) )
602 remapAndSetLraInfeasibleSubsets();
603 #ifdef ICP_MODULE_DEBUG_1
604 std::cout << "[mLRA] Assert " << _formula << std::endl;
609 template<class Settings>
610 bool ICPModule<Settings>::checkNotEqualConstraints()
612 for( auto& constraint : mNotEqualConstraints )
614 if( carl::satisfied_by(constraint, mFoundSolution) == 0 )
618 splitUnequalConstraint(constraint);
619 #ifdef ICP_MODULE_DEBUG_0
620 std::cout << "Unresolved inequality " << constraint << " - Return unknown and raise lemmas for split." << std::endl;
629 template<class Settings>
630 void ICPModule<Settings>::contractCurrentBox()
632 #ifdef ICP_MODULE_DEBUG_0
633 std::cout << __func__ << ":" << std::endl;
636 mSplitOccurred = false;
637 mOriginalVariableIntervalContracted = false;
640 if( anAnswerFound() )
642 while(!mBoxStorage.empty())
644 icp::set_icpVariable icpVariables;
645 carl::carlVariables originalRealVariables(carl::variable_type_filter::real());
646 rReceivedFormula().gatherVariables(originalRealVariables);
647 // TODO: store original variables as member, updating them efficiently with assert and remove
648 for( auto variablesIt = originalRealVariables.begin(); variablesIt != originalRealVariables.end(); ++variablesIt )
650 auto iter = mVariables.find(*variablesIt);
651 if( iter != mVariables.end() )
652 icpVariables.insert( iter->second );
654 FormulasT box = variableReasonHull(icpVariables);
655 mBoxStorage.push(box);
656 #ifdef ICP_MODULE_DEBUG_1
657 std::cout << "********************** [ICP] Contraction **********************" << std::endl;
658 //cout << "Subtree size: " << mHistoryRoot->sizeSubtree() << std::endl;
659 mHistoryActual->print();
661 // prepare IcpRelevantCandidates
663 while ( !mIcpRelevantCandidates.empty() && !mSplitOccurred )
665 icp::ContractionCandidate* candidate = chooseContractionCandidate();
666 assert(candidate != nullptr);
667 mRelativeContraction = -1; // TODO: try without this line
668 mAbsoluteContraction = 0; // TODO: try without this line
669 contraction( candidate );
670 // catch if new interval is empty -> we can drop box and chose next box
671 if ( mIntervals.at(candidate->derivationVar()).is_empty() )
673 #ifdef ICP_MODULE_DEBUG_0
674 std::cout << "Contracted to empty interval!" << std::endl;
679 if( (mRelativeContraction > 0 || mAbsoluteContraction > 0) && originalRealVariables.has( candidate->derivationVar() ) )
681 mOriginalVariableIntervalContracted = true;
683 // update weight of the candidate
684 removeCandidateFromRelevant(candidate);
685 candidate->setPayoff(mRelativeContraction);
686 candidate->calcRWA();
687 // only add nonlinear CCs as linear CCs should only be used once
688 if( !candidate->is_linear() )
689 addCandidateToRelevant(candidate); // TODO: Improve - no need to add irrelevant candidates (see below)
690 assert(mIntervals.find(candidate->derivationVar()) != mIntervals.end() );
691 /// TODO: compare against mRelativeContraction or candidate->RWA()
692 if ( (mRelativeContraction < mContractionThreshold && !mSplitOccurred) || fulfillsTarget(*candidate) )
693 removeCandidateFromRelevant(candidate);
694 else if ( mRelativeContraction >= mContractionThreshold )
696 // make sure all candidates which contain the variable of which the interval has significantly changed are contained in mIcpRelevantCandidates.
697 std::map<carl::Variable, icp::IcpVariable*>::iterator icpVar = mVariables.find(candidate->derivationVar());
698 assert(icpVar != mVariables.end());
699 for ( auto candidateIt = (*icpVar).second->candidates().begin(); candidateIt != (*icpVar).second->candidates().end(); ++candidateIt )
702 // TODO: there must be a better way to find out whether the candidate is already in the relevants
703 for ( auto relevantCandidateIt = mIcpRelevantCandidates.begin(); relevantCandidateIt != mIcpRelevantCandidates.end(); ++relevantCandidateIt )
705 if ( (*relevantCandidateIt).second == (*candidateIt)->id() )
708 if ( toAdd && (*candidateIt)->isActive() && !fulfillsTarget(**candidateIt) )
709 addCandidateToRelevant(*candidateIt);
712 } //while ( !mIcpRelevantCandidates.empty() && !mSplitOccurred)
713 // verify if the box is already invalid
714 if( !mInvalidBox && !mSplitOccurred )
716 mInvalidBox = !checkBoxAgainstLinearFeasibleRegion();
717 #ifdef ICP_MODULE_DEBUG_1
718 std::cout << "Invalid against linear region: " << (mInvalidBox ? "yes!" : "no!") << std::endl;
723 if( mSplitOccurred || mIcpRelevantCandidates.empty() ) // relevantCandidates is not empty, if we got new bounds from LRA during boxCheck
726 assert( false ); // should not happen
729 template<class Settings>
730 Answer ICPModule<Settings>::callBackends( bool _final, bool _full, carl::Variable _objective )
732 #ifdef ICP_MODULE_DEBUG_0
733 std::cout << "Ask backends " << (_full ? "full" : "lazy") << " for the satisfiability of:" << std::endl;
734 for( const auto& f : rPassedFormula() )
735 std::cout << " " << f.formula().constraint() << std::endl;
737 ++mCountBackendCalls;
738 Answer a = runBackends( _final, _full, _objective );
742 std::vector<Module*>::const_iterator backend = usedBackends().begin();
743 while( backend != usedBackends().end() )
745 (*backend)->clearLemmas();
748 #ifdef ICP_MODULE_DEBUG_0
749 std::cout << " Backend's answer: " << a << std::endl;
753 assert(infeasibleSubsets().empty());
754 FormulaSetT contractionConstraints = this->createPremiseDeductions();
755 backend = usedBackends().begin();
756 while( backend != usedBackends().end() )
758 assert( !(*backend)->infeasibleSubsets().empty() );
759 #ifdef ICP_MODULE_DEBUG_1
760 (*backend)->printInfeasibleSubsets();
762 for( auto infsubset = (*backend)->infeasibleSubsets().begin(); infsubset != (*backend)->infeasibleSubsets().end(); ++infsubset )
764 FormulaSetT newInfSubset;
765 for( auto subformula = infsubset->begin(); subformula != infsubset->end(); ++subformula )
767 if( !carl::is_bound(subformula->constraint()) )
768 newInfSubset.insert( *subformula );
770 newInfSubset.insert( contractionConstraints.begin(), contractionConstraints.end() );
771 mInfeasibleSubsets.push_back( std::move(newInfSubset) );
775 #ifdef ICP_MODULE_SHOW_PROGRESS
776 addProgress( mInitialBoxSize );
780 else // if a == SAT or a == UNKNOWN
782 assert( mHistoryActual != nullptr );
783 assert( mHistoryRoot != nullptr );
784 mHistoryActual->propagateStateInfeasibleConstraints(mHistoryRoot);
785 mHistoryActual->propagateStateInfeasibleVariables(mHistoryRoot);
786 #ifdef ICP_MODULE_SHOW_PROGRESS
787 // if( _full && a == UNKNOWN && !hasLemmas() )
788 // addProgress( mInitialBoxSize );
794 template<class Settings>
795 Poly ICPModule<Settings>::createNonlinearCCs( const ConstraintT& _constraint, const std::vector<Poly>& _tempMonomes )
797 Poly linearizedConstraint;
798 ContractionCandidates ccs;
800 * Create all icp variables and contraction candidates for the given non-linear constraint:
802 * a_1*m_1 + .. + a_k*m_k ~ b, with b and a_i being rationals and m_i being monomials (possibly linear)
804 for( auto& monom : _tempMonomes )
806 ContractionCandidates ccsOfMonomial;
807 auto iter = mVariableLinearizations.find( monom );
808 if( iter == mVariableLinearizations.end() ) // no linearization yet
810 // create mLinearzations entry
811 carl::carlVariables variables = carl::variables(monom);
812 bool hasRealVar = false;
813 for (auto var: variables) {
814 if (var.type() == carl::VariableType::VT_REAL) {
819 carl::Variable newVar = hasRealVar ? carl::fresh_real_variable() : carl::fresh_integer_variable();
820 mVariableLinearizations.insert( std::make_pair( monom, newVar ) );
821 mSubstitutions.insert( std::make_pair( newVar, monom ) );
822 if( !Settings::original_polynomial_contraction )
824 assert( mVariables.find( newVar ) == mVariables.end() );
825 icp::IcpVariable* icpVar = getIcpVariable( newVar, false, nullptr );
826 mHistoryRoot->addInterval( newVar, DoubleInterval::unbounded_interval() );
827 #ifdef ICP_MODULE_DEBUG_1
828 std::cout << "New replacement: " << monom << " -> " << mVariableLinearizations.at(monom) << std::endl;
830 // Create equation m_i - v_i = 0, where m_i is the nonlinear monomial x_{i,1}^e_{i,1}*..*x_{i,n}^e_{i,n} being replaced by the freshly introduced variable v_i
831 Poly rhs = monom - Poly(newVar);
832 if( mContractors.find(rhs) == mContractors.end() )
834 mContractors.emplace( rhs, Contractor<carl::SimpleNewton>(rhs) );
837 ConstraintT tmp = ConstraintT( rhs, carl::Relation::EQ );
838 for( auto varIndex = variables.begin(); varIndex != variables.end(); ++varIndex )
840 // create a contraction candidate for m_i-v_i regarding the variable x_{i,1}
841 icp::ContractionCandidate* tmpCandidate = mCandidateManager.createCandidate( newVar, rhs, tmp, *varIndex, mContractors.at( rhs ), Settings::use_propagation );
842 ccsOfMonomial.insert( ccsOfMonomial.end(), tmpCandidate );
843 tmpCandidate->setNonlinear();
844 // add the contraction candidate to the icp variable of v_i
845 auto tmpIcpVar = mVariables.find( newVar );
846 assert( tmpIcpVar != mVariables.end() );
847 tmpIcpVar->second->addCandidate( tmpCandidate );
849 // create a contraction candidate for m_i-v_i regarding the variable v_i
850 icp::ContractionCandidate* tmpCandidate = mCandidateManager.createCandidate( newVar, rhs, tmp, newVar, mContractors.at( rhs ), Settings::use_propagation );
851 tmpCandidate->setNonlinear();
852 icpVar->addCandidate( tmpCandidate );
853 ccsOfMonomial.insert( ccsOfMonomial.end(), tmpCandidate );
854 // add all contraction candidates for m_i-v_i to the icp variables of all x_{i,j}
855 for( auto var = variables.begin(); var != variables.end(); ++var )
857 auto origIcpVar = mVariables.find( *var );
858 assert( origIcpVar != mVariables.end() );
859 origIcpVar->second->addCandidates( ccsOfMonomial );
861 ccs.insert( ccsOfMonomial.begin(), ccsOfMonomial.end() );
864 else // already existing replacement/substitution/linearization
866 #ifdef ICP_MODULE_DEBUG_2
867 std::cout << "Existing replacement: " << monom << " -> " << mVariableLinearizations.at(monom) << std::endl;
869 auto iterB = mVariables.find( iter->second );
870 if( !Settings::original_polynomial_contraction || iterB != mVariables.end() )
872 assert( iterB != mVariables.end() );
873 // insert already created CCs into the current list of CCs
874 ccs.insert( iterB->second->candidates().begin(), iterB->second->candidates().end() );
878 // Construct the linearization
879 for( auto monomialIt = _constraint.lhs().polynomial().begin(); monomialIt != _constraint.lhs().polynomial().end(); ++monomialIt )
881 if( (monomialIt)->monomial() == nullptr || (monomialIt)->monomial()->isAtMostLinear() )
882 linearizedConstraint += Poly(typename Poly::PolyType(*monomialIt));
885 assert( mVariableLinearizations.find(Poly(typename Poly::PolyType((monomialIt)->monomial()))) != mVariableLinearizations.end() );
886 linearizedConstraint += (monomialIt)->coeff() * Poly((*mVariableLinearizations.find( Poly(typename Poly::PolyType((monomialIt)->monomial())) )).second);
889 mNonlinearConstraints.emplace( _constraint, std::move(ccs) );
890 linearizedConstraint *= _constraint.lhs().coefficient();
891 return linearizedConstraint;
894 template<class Settings>
895 void ICPModule<Settings>::createLinearCCs( const FormulaT& _constraint, const FormulaT& _original )
898 * Create all icp variables and contraction candidates for the given linear constraint:
900 * a_1*x_1 + .. + a_k*x_k ~ b, with b and a_i being rationals and x_i being variables
902 assert( _constraint.type() == carl::FormulaType::CONSTRAINT );
903 assert( _constraint.constraint().lhs().is_linear() );
904 const icp::LRAVariable* slackvariable = mLRA.getSlackVariable( _constraint );
905 assert( slackvariable != nullptr );
906 if( mLinearConstraints.find( slackvariable ) == mLinearConstraints.end() )
908 carl::Variables variables = Settings::original_polynomial_contraction ? _original.constraint().variables().as_set() : _constraint.constraint().variables().as_set();
909 bool hasRealVar = false;
910 for( auto var : variables )
912 if( var.type() == carl::VariableType::VT_REAL )
918 carl::Variable newVar = hasRealVar ? carl::fresh_real_variable() : carl::fresh_integer_variable();
919 variables.insert( variables.end(), newVar );
920 mSubstitutions.insert( std::make_pair( newVar, Poly( newVar ) ) );
921 assert( mVariables.find( newVar ) == mVariables.end() );
922 icp::IcpVariable* icpVar = getIcpVariable( newVar, false, slackvariable );
923 mHistoryRoot->addInterval( newVar, DoubleInterval::unbounded_interval() );
924 // Create equation a_1'*x_1 + .. + a_k'*x_k = 0, with a_i' = a_i/gcd(a_1,..,a_k)*sgn(a_1)
925 Poly rhs = Poly(slackvariable->expression()) - Poly(newVar);
926 ConstraintT tmpConstr = ConstraintT( rhs, carl::Relation::EQ );
927 auto iter = mContractors.find( rhs );
928 if( iter == mContractors.end() )
930 iter = mContractors.emplace( rhs, Contractor<carl::SimpleNewton>(rhs, carl::substitute(rhs, mSubstitutions )) ).first;
932 ContractionCandidates ccs;
933 // Create candidates for every possible variable:
934 for( auto var = variables.begin(); var != variables.end(); ++var )
936 // create a contraction candidate for a_1'*x_1 + .. + a_k'*x_k - v regarding the variable x_i/v
937 icp::ContractionCandidate* newCandidate = mCandidateManager.createCandidate( newVar, rhs, tmpConstr, *var, iter->second, Settings::use_propagation && (!Settings::original_polynomial_contraction || _original.constraint().lhs().is_linear()) );
938 ccs.insert( ccs.end(), newCandidate );
939 newCandidate->setLinear();
941 // add all contraction candidates for a_1'*x_1 + .. + a_k'*x_k - v to the icp variables of all x_i/v
942 for( auto var = variables.begin(); var != variables.end(); ++var )
944 auto origIcpVar = mVariables.find( *var );
945 assert( origIcpVar != mVariables.end() );
946 origIcpVar->second->addCandidates( ccs );
948 mLinearConstraints.insert( std::pair<const icp::LRAVariable*, ContractionCandidates>( slackvariable, icpVar->candidates() ) );
952 template<class Settings>
953 void ICPModule<Settings>::fillCandidates()
955 // fill mIcpRelevantCandidates with the nonlinear contractionCandidates
956 for ( icp::ContractionCandidate* nonlinearIt : mActiveNonlinearConstraints )
958 // check that assertions have been processed properly
959 assert( (*nonlinearIt).activity() == (*nonlinearIt).origin().size() );
960 if ( !fulfillsTarget(*nonlinearIt) )
961 addCandidateToRelevant( nonlinearIt );// only add if not already existing
962 else // the candidate is not relevant -> delete from icpRelevantCandidates
963 removeCandidateFromRelevant(nonlinearIt);
965 // fill mIcpRelevantCandidates with the active linear contractionCandidates
966 for ( icp::ContractionCandidate* linearIt : mActiveLinearConstraints )
968 // check that assertions have been processed properly
969 assert( (*linearIt).activity() == (*linearIt).origin().size() );
970 if ( (*linearIt).isActive() && !fulfillsTarget(*linearIt) )
971 addCandidateToRelevant( linearIt );
972 else // the candidate is not relevant -> delete from icpRelevantCandidates
973 removeCandidateFromRelevant( linearIt );
977 template<class Settings>
978 bool ICPModule<Settings>::addCandidateToRelevant(icp::ContractionCandidate* _candidate)
980 if ( _candidate->isActive() )
982 mIcpRelevantCandidates.erase( std::pair<double, unsigned>( _candidate->lastRWA(), _candidate->id() ) );
983 std::pair<double, unsigned> target(_candidate->RWA(), _candidate->id());
984 if ( mIcpRelevantCandidates.find(target) == mIcpRelevantCandidates.end() )
986 #ifdef ICP_MODULE_DEBUG_1
987 std::cout << "add to relevant candidates: " << (*_candidate).rhs() << " in variable " << (*_candidate).derivationVar() << std::endl;
988 std::cout << " id: " << (*_candidate).id() << std::endl;
989 std::cout << " key: (" << target.first << ", " << target.second << ")" << std::endl;
991 mIcpRelevantCandidates.insert(target);
992 _candidate->updateLastRWA();
999 template<class Settings>
1000 bool ICPModule<Settings>::removeCandidateFromRelevant(icp::ContractionCandidate* _candidate)
1002 std::pair<double, unsigned> target(_candidate->lastRWA(), _candidate->id());
1003 auto iter = mIcpRelevantCandidates.find( target );
1004 if( iter != mIcpRelevantCandidates.end() )
1006 #ifdef ICP_MODULE_DEBUG_1
1007 std::cout << "remove from relevant candidates: " << (*_candidate).rhs() << std::endl;
1008 std::cout << " id: " << (*_candidate).id() << " , Diameter: " << mIntervals[(*_candidate).derivationVar()].diameter() << std::endl;
1010 mIcpRelevantCandidates.erase(iter);
1016 template<class Settings>
1017 void ICPModule<Settings>::updateRelevantCandidates(carl::Variable::Arg _var)
1019 // update all candidates which contract in the dimension in which the split has happened
1020 std::set<icp::ContractionCandidate*> updatedCandidates;
1021 // iterate over all affected constraints
1022 std::map<carl::Variable, icp::IcpVariable*>::iterator icpVar = mVariables.find(_var);
1023 assert(icpVar != mVariables.end());
1024 for ( auto candidatesIt = (*icpVar).second->candidates().begin(); candidatesIt != (*icpVar).second->candidates().end(); ++candidatesIt)
1026 if ( (*candidatesIt)->isActive() )
1028 unsigned id = (*candidatesIt)->id();
1029 // search if candidate is already contained - erase if, else do nothing
1030 removeCandidateFromRelevant(*candidatesIt);
1031 // create new tuple for mIcpRelevantCandidates
1032 mCandidateManager.getCandidate(id)->setPayoff(mRelativeContraction );
1033 mCandidateManager.getCandidate(id)->calcRWA();
1034 updatedCandidates.insert(*candidatesIt);
1037 // re-insert tuples into icpRelevantCandidates
1038 for ( auto candidatesIt = updatedCandidates.begin(); candidatesIt != updatedCandidates.end(); ++candidatesIt )
1040 if ( !fulfillsTarget(**candidatesIt) )
1041 addCandidateToRelevant(*candidatesIt);
1045 template<class Settings>
1046 icp::ContractionCandidate* ICPModule<Settings>::chooseContractionCandidate()
1048 assert(!mIcpRelevantCandidates.empty());
1049 // as the map is sorted ascending, we can simply pick the last value
1050 for( auto candidateIt = mIcpRelevantCandidates.rbegin(); candidateIt != mIcpRelevantCandidates.rend(); ++candidateIt )
1052 icp::ContractionCandidate* cc = mCandidateManager.getCandidate((*candidateIt).second);
1053 assert( cc != nullptr );
1054 if( cc->isActive() )//&& mIntervals[mCandidateManager.getCandidate((*candidateIt).second)->derivationVar()].diameter() != 0 )
1056 cc->calcDerivative();
1057 #ifdef ICP_MODULE_DEBUG_1
1058 std::cout << "Choose Candidate: ";
1060 std::cout << std::endl;
1068 template<class Settings>
1069 void ICPModule<Settings>::contraction( icp::ContractionCandidate* _selection )
1071 DoubleInterval resultA;
1072 DoubleInterval resultB;
1073 // check if derivative is already calculated
1074 if(carl::is_zero(_selection->derivative()))
1075 _selection->calcDerivative();
1076 carl::Variable variable = _selection->derivationVar();
1077 assert( mVariables.find( variable ) != mVariables.end() );
1078 icp::IcpVariable& icpVar = *mVariables.find( variable )->second;
1079 DoubleInterval icpVarIntervalBefore = icpVar.interval();
1080 mSplitOccurred = _selection->contract( mIntervals, resultA, resultB );
1081 if( (!mFinalCheck || !Settings::split_by_division_with_zero) && mSplitOccurred )
1083 mSplitOccurred = false;
1084 resultA = resultA.convex_hull( resultB );
1086 if( mSplitOccurred )
1088 assert( !resultB.is_empty() );
1089 #ifdef ICP_MODULE_DEBUG_2
1090 std::cout << "Split occurred: " << resultA << " and " << resultB << std::endl;
1092 setContraction( _selection, icpVar, resultA.convex_hull( resultB ) );
1093 icp::set_icpVariable variables;
1094 for( auto variable: _selection->constraint().variables() )
1096 assert(mVariables.find(variable) != mVariables.end());
1097 variables.insert(mVariables.at(variable));
1099 mHistoryActual->addContraction(_selection, variables);
1100 /// create prequesites: ((oldBox AND CCs) -> newBox) in CNF: (oldBox OR CCs) OR newBox
1101 FormulasT subformulas;
1102 std::vector<FormulaT> splitPremise = createPremise();
1103 for( const FormulaT& subformula : splitPremise )
1104 subformulas.emplace_back( carl::FormulaType::NOT, subformula );
1105 // construct new box
1106 FormulasT boxFormulas = createBoxFormula( true );
1108 if( !boxFormulas.empty() )
1110 auto lastFormula = --boxFormulas.end();
1111 if( boxFormulas.size() > 1 )
1113 for( auto iter = boxFormulas.begin(); iter != lastFormula; ++iter )
1114 mTheoryPropagations.emplace_back( std::move(FormulasT(subformulas)), *iter );
1116 mTheoryPropagations.emplace_back( std::move(subformulas), *lastFormula );
1118 #ifdef ICP_MODULE_SHOW_PROGRESS
1119 addProgress( mInitialBoxSize - calculateCurrentBoxSize() );
1121 // create split: (not h_b OR (Not x<b AND x>=b) OR (x<b AND Not x>=b) )
1122 assert(resultA.upper_bound_type() != carl::BoundType::INFTY );
1123 Rational bound = carl::rationalize<Rational>( resultA.upper() );
1124 Module::branchAt( variable, bound, std::move(splitPremise), true, true );
1125 #ifdef ICP_MODULE_DEBUG_1
1126 std::cout << "division causes split on " << variable << " at " << bound << "!" << std::endl << std::endl;
1128 #ifdef ICP_MODULE_DEBUG_0
1129 printContraction( *_selection, icpVarIntervalBefore, resultA, resultB );
1135 setContraction( _selection, icpVar, resultA );
1137 #ifdef ICP_MODULE_DEBUG_1
1138 std::cout << " Relative contraction: " << mRelativeContraction << std::endl;
1142 template<class Settings>
1143 void ICPModule<Settings>::setContraction( icp::ContractionCandidate* _selection, icp::IcpVariable& _icpVar, const DoubleInterval& _contractedInterval )
1145 updateRelativeContraction( _icpVar.interval(), _contractedInterval );
1146 updateAbsoluteContraction( _icpVar.interval(), _contractedInterval );
1147 #ifdef ICP_MODULE_DEBUG_0
1148 printContraction( *_selection, _icpVar.interval(), _contractedInterval );
1150 _icpVar.setInterval( _contractedInterval );
1151 if (mRelativeContraction > 0 || mAbsoluteContraction > 0)
1153 mHistoryActual->addInterval(_selection->lhs(), mIntervals.at(_selection->lhs()));
1154 icp::set_icpVariable variables;
1155 for( auto variable: _selection->constraint().variables() )
1157 if( Settings::original_polynomial_contraction && mVariables.find(variable) == mVariables.end() )
1159 assert(mVariables.find(variable) != mVariables.end());
1160 variables.insert(mVariables.at(variable));
1162 mHistoryActual->addContraction(_selection, variables);
1166 template<class Settings>
1167 void ICPModule<Settings>::setContraction( const FormulaT& _constraint, icp::IcpVariable& _icpVar, const DoubleInterval& _contractedInterval, bool _allCCs )
1169 icp::ContractionCandidate* foundCC = nullptr;
1170 if( _constraint.constraint().lhs().is_linear() )
1172 auto iter = mLinearConstraints.find( mLRA.getSlackVariable( _constraint ) );
1173 assert( iter != mLinearConstraints.end() );
1174 for( const auto& cc : iter->second )
1177 setContraction( cc, _icpVar, _contractedInterval );
1178 else if( cc->derivationVar() == _icpVar.var() )
1185 if( foundCC == nullptr )
1187 assert( _constraint.type() == carl::FormulaType::CONSTRAINT );
1188 auto iter = mNonlinearConstraints.find( _constraint.constraint() );
1189 assert( iter != mNonlinearConstraints.end() );
1190 for( const auto& cc : iter->second )
1193 setContraction( cc, _icpVar, _contractedInterval );
1194 else if( cc->derivationVar() == _icpVar.var() )
1201 if( foundCC == nullptr && _constraint.constraint().maxDegree( _icpVar.var() ) == 1 )
1203 auto linearization = mLinearizations.find( _constraint );
1204 assert( linearization != mLinearizations.end() );
1205 auto iter = mLinearConstraints.find( mLRA.getSlackVariable( linearization->second ) );
1206 assert( iter != mLinearConstraints.end() );
1207 for( const auto& cc : iter->second )
1210 setContraction( cc, _icpVar, _contractedInterval );
1211 else if( cc->derivationVar() == _icpVar.var() )
1220 assert( foundCC != nullptr );
1221 setContraction( foundCC, _icpVar, _contractedInterval );
1224 template<class Settings>
1225 void ICPModule<Settings>::updateRelativeContraction( const DoubleInterval& _interval, const DoubleInterval& _contractedInterval )
1227 assert( _interval == _contractedInterval || _interval.contains( _contractedInterval ) );
1228 if( _contractedInterval.is_empty() )
1230 mRelativeContraction = 1;
1233 if( _interval == _contractedInterval )
1235 mRelativeContraction = 0;
1238 // If the interval lost an infinite part, give it a high valuation
1239 if( (_interval.lower_bound_type() == carl::BoundType::INFTY && _contractedInterval.lower_bound_type() != carl::BoundType::INFTY)
1240 || (_interval.upper_bound_type() == carl::BoundType::INFTY && _contractedInterval.upper_bound_type() != carl::BoundType::INFTY) )
1242 mRelativeContraction = 1;
1245 // If zero is split from the interval, give it a high valuation
1246 if( _interval.contains( (double) 0.0 ) && !_contractedInterval.contains( (double) 0.0 ) )
1248 mRelativeContraction = 1;
1251 // If the interval is still unbounded the relative contraction is 0
1252 if( _contractedInterval.lower_bound_type() == carl::BoundType::INFTY || _contractedInterval.upper_bound_type() == carl::BoundType::INFTY )
1254 mRelativeContraction = 0;
1257 assert( _interval.lower_bound_type() != carl::BoundType::INFTY );
1258 assert( _interval.upper_bound_type() != carl::BoundType::INFTY );
1259 assert( _contractedInterval.lower_bound_type() != carl::BoundType::INFTY );
1260 assert( _contractedInterval.upper_bound_type() != carl::BoundType::INFTY );
1261 mRelativeContraction = (double)1 - (_contractedInterval.diameter()/_interval.diameter());
1264 template<class Settings>
1265 void ICPModule<Settings>::updateAbsoluteContraction( const DoubleInterval& _interval, const DoubleInterval& _contractedInterval )
1267 assert( _interval == _contractedInterval || _interval.contains( _contractedInterval ) );
1268 if( _contractedInterval.is_empty() )
1270 if( _interval.lower_bound_type() == carl::BoundType::INFTY || _interval.upper_bound_type() == carl::BoundType::INFTY )
1271 mAbsoluteContraction = std::numeric_limits<double>::infinity();
1273 mAbsoluteContraction = _interval.diameter();
1276 if( _interval == _contractedInterval )
1278 mAbsoluteContraction = 0;
1281 if( (_interval.lower_bound_type() == carl::BoundType::INFTY && _contractedInterval.lower_bound_type() != carl::BoundType::INFTY)
1282 || (_interval.upper_bound_type() == carl::BoundType::INFTY && _contractedInterval.upper_bound_type() != carl::BoundType::INFTY) )
1284 mAbsoluteContraction = std::numeric_limits<double>::infinity();
1287 if( _contractedInterval.lower_bound_type() == carl::BoundType::INFTY )
1289 assert( _interval.upper_bound_type() != carl::BoundType::INFTY );
1290 assert( _contractedInterval.lower_bound_type() == carl::BoundType::INFTY );
1291 assert( _contractedInterval.upper_bound_type() != carl::BoundType::INFTY );
1292 assert( _interval.upper() >= _contractedInterval.upper() ); // >= as _contractedInterval.upper_bound_type() could be strict and _interval.upper_bound_type() weak
1293 mAbsoluteContraction = _interval.upper() - _contractedInterval.upper();
1294 if( _interval.upper_bound_type() == carl::BoundType::WEAK && _contractedInterval.upper_bound_type() == carl::BoundType::STRICT )
1295 mAbsoluteContraction = std::nextafter( mAbsoluteContraction, INFINITY );
1296 else if( _interval.upper_bound_type() == carl::BoundType::STRICT && _contractedInterval.upper_bound_type() == carl::BoundType::WEAK )
1297 mAbsoluteContraction = std::nextafter( mAbsoluteContraction, -INFINITY );
1300 if( _contractedInterval.upper_bound_type() == carl::BoundType::INFTY )
1302 assert( _interval.lower_bound_type() != carl::BoundType::INFTY );
1303 assert( _contractedInterval.upper_bound_type() == carl::BoundType::INFTY );
1304 assert( _contractedInterval.lower_bound_type() != carl::BoundType::INFTY );
1305 assert( _interval.lower() <= _contractedInterval.lower() ); // >= as _contractedInterval.lower_bound_type() could be strict and _interval.lower_bound_type() weak
1306 mAbsoluteContraction = _contractedInterval.lower() - _interval.lower();
1307 if( _interval.lower_bound_type() == carl::BoundType::WEAK && _contractedInterval.lower_bound_type() == carl::BoundType::STRICT )
1308 mAbsoluteContraction = std::nextafter( mAbsoluteContraction, INFINITY );
1309 else if( _interval.lower_bound_type() == carl::BoundType::STRICT && _contractedInterval.lower_bound_type() == carl::BoundType::WEAK )
1310 mAbsoluteContraction = std::nextafter( mAbsoluteContraction, -INFINITY );
1313 assert( _interval.lower_bound_type() != carl::BoundType::INFTY );
1314 assert( _interval.upper_bound_type() != carl::BoundType::INFTY );
1315 assert( _contractedInterval.lower_bound_type() != carl::BoundType::INFTY );
1316 assert( _contractedInterval.upper_bound_type() != carl::BoundType::INFTY );
1317 mAbsoluteContraction = _interval.diameter() - _contractedInterval.diameter();
1320 template<class Settings>
1321 std::map<carl::Variable, double> ICPModule<Settings>::createModel( bool antipoint ) const
1323 // Note that we do not need to consider INFTY bounds in the calculation of the antipoint.
1324 std::map<carl::Variable, double> assignments;
1325 auto varIntervalIt = mIntervals.begin();
1326 auto varIt = mVariables.begin();
1327 if( Settings::original_polynomial_contraction )
1329 while( varIntervalIt->first != varIt->first && varIt != mVariables.end() )
1332 while( varIt != mVariables.end() )
1334 if( !varIt->second->isOriginal() )
1337 if( Settings::original_polynomial_contraction )
1339 while( varIntervalIt->first != varIt->first && varIt != mVariables.end() )
1341 if( varIt == mVariables.end() )
1348 assert( varIntervalIt->first == varIt->first );
1349 assert( varIt->second->var() == varIt->first );
1351 const DoubleInterval& interv = varIntervalIt->second;
1352 if( !interv.is_infinite() )
1354 bool takeLower = false;
1355 bool takeUpper = false;
1356 if( antipoint ) // Find a point within the interval bounds which is most likely NOT SATISFYING all constraints
1358 switch( (*varIt).second->isInternalUpdated() )
1360 case icp::Updated::BOTH:
1363 case icp::Updated::LEFT:
1366 case icp::Updated::RIGHT:
1374 else // Find a point within the interval which is most likely SATISFYING all constraints
1376 switch( (*varIt).second->isInternalUpdated() )
1378 case icp::Updated::BOTH:
1382 case icp::Updated::LEFT:
1385 case icp::Updated::RIGHT:
1392 if( takeLower && takeUpper )
1394 if(interv.is_point_interval())
1396 value = interv.lower();
1400 value = carl::sample(interv,false);
1403 else if( takeLower )
1405 if( interv.lower_bound_type() == carl::BoundType::INFTY )
1407 if( interv.upper_bound_type() == carl::BoundType::WEAK )
1409 value = interv.upper();
1413 value = std::nextafter( interv.upper(), -INFINITY );
1418 if( interv.lower_bound_type() == carl::BoundType::WEAK )
1420 value = interv.lower();
1422 else if( interv.upper_bound_type() != carl::BoundType::INFTY )
1424 value = std::nextafter( interv.lower(), INFINITY );
1425 // Check if the interval does contain any double. If not, return an empty model.
1426 if( value > interv.upper() || (interv.upper_bound_type() == carl::BoundType::STRICT && value == interv.upper()) )
1428 return std::map<carl::Variable, double>();
1433 if( interv.lower() == std::numeric_limits<double>::max() )
1435 return std::map<carl::Variable, double>();
1437 value = std::nextafter( interv.lower(), INFINITY );
1443 if( interv.upper_bound_type() == carl::BoundType::INFTY )
1445 if( interv.lower_bound_type() == carl::BoundType::WEAK )
1447 value = interv.lower();
1451 value = std::nextafter( interv.lower(), INFINITY );
1456 if( interv.upper_bound_type() == carl::BoundType::WEAK )
1458 value = interv.upper();
1460 else if( interv.lower_bound_type() != carl::BoundType::INFTY )
1462 value = std::nextafter( interv.upper(), -INFINITY );
1463 // Check if the interval does contain any double. If not, return an empty model.
1464 if( value < interv.lower() || (interv.lower_bound_type() == carl::BoundType::STRICT && value == interv.lower()) )
1466 return std::map<carl::Variable, double>();
1471 if( interv.upper() == std::numeric_limits<double>::min() )
1473 return std::map<carl::Variable, double>();
1475 value = std::nextafter( interv.upper(), -INFINITY );
1480 assert( interv.contains( value ) );
1481 assignments[varIt->first] = value;
1488 template<class Settings>
1489 void ICPModule<Settings>::updateModel() const
1492 if( solverState() == SAT )
1494 if( mFoundSolution.empty() )
1496 if( !mLRAFoundSolution )
1497 Module::getBackendsModel();
1498 RationalAssignment rationalAssignment = mLRA.getRationalModel();
1499 for( auto assignmentIt = rationalAssignment.begin(); assignmentIt != rationalAssignment.end(); ++assignmentIt )
1501 auto varIt = mVariables.find((*assignmentIt).first);
1502 if( varIt != mVariables.end() && (*varIt).second->isOriginal() )
1504 mModel.emplace( assignmentIt->first, assignmentIt->second );
1510 for (const auto& assignment: mFoundSolution)
1512 auto varIt = mVariables.find(assignment.first.asVariable());
1513 if( varIt != mVariables.end() && (*varIt).second->isOriginal() )
1515 mModel.emplace(assignment.first, assignment.second);
1522 template<class Settings>
1523 ModuleInput::iterator ICPModule<Settings>::eraseSubformulaFromPassedFormula( ModuleInput::iterator _subformula, bool _ignoreOrigins )
1525 // TODO: check if the sub-formula is a bound, then take the variable, find its icp-variable and update it
1526 for( auto& varIcpvarPair : mVariables )
1528 icp::IcpVariable& icpVar = *varIcpvarPair.second;
1529 assert( icpVar.externalLeftBound() == passedFormulaEnd() || icpVar.externalLeftBound() != icpVar.externalRightBound() );
1530 if( icpVar.externalLeftBound() == _subformula )
1532 icpVar.setExternalLeftBound( passedFormulaEnd() );
1533 icpVar.setExternalModified();
1536 else if( icpVar.externalRightBound() == _subformula )
1538 icpVar.setExternalRightBound( passedFormulaEnd() );
1539 icpVar.setExternalModified();
1543 auto res = Module::eraseSubformulaFromPassedFormula( _subformula, _ignoreOrigins );
1547 template<class Settings>
1548 double ICPModule<Settings>::sizeBasedSplittingImpact( std::map<carl::Variable, icp::IcpVariable*>::const_iterator _varIcpVarMapIter ) const
1550 const DoubleInterval& varInterval = _varIcpVarMapIter->second->interval();
1551 if( varInterval.lower_bound_type() == carl::BoundType::INFTY || varInterval.upper_bound_type() == carl::BoundType::INFTY )
1552 return std::numeric_limits<double>::infinity();
1554 double originalDiameter = varInterval.diameter();
1555 switch(mSplittingStrategy)
1557 case 1: // Select biggest interval
1559 impact = originalDiameter;
1562 case 2: // Rule of Hansen and Walster - select interval with most varying function values
1564 EvalDoubleIntervalMap tmpIntervals = mIntervals;
1565 tmpIntervals.insert(std::make_pair(_varIcpVarMapIter->first,DoubleInterval(1)));
1566 DoubleInterval derivedEvalInterval = carl::evaluate((*_varIcpVarMapIter->second->candidates().begin())->derivative(), tmpIntervals); // TODO: WHY ANY DERIVATIVE??
1567 if( derivedEvalInterval.lower_bound_type() == carl::BoundType::INFTY || derivedEvalInterval.upper_bound_type() == carl::BoundType::INFTY )
1568 return std::numeric_limits<double>::infinity();
1569 impact = derivedEvalInterval.diameter() * originalDiameter;
1572 case 3: // Rule of Ratz - minimize width of inclusion
1574 EvalDoubleIntervalMap tmpIntervals = mIntervals;
1575 tmpIntervals.insert(std::make_pair(_varIcpVarMapIter->first,DoubleInterval(1)));
1576 DoubleInterval derivedEvalInterval = carl::evaluate((*_varIcpVarMapIter->second->candidates().begin())->derivative(), tmpIntervals); // TODO: WHY ANY DERIVATIVE??
1577 DoubleInterval negCenter = varInterval.inverse();
1578 negCenter = negCenter.add(varInterval);
1579 derivedEvalInterval = derivedEvalInterval.mul(negCenter);
1580 if( derivedEvalInterval.lower_bound_type() == carl::BoundType::INFTY || derivedEvalInterval.upper_bound_type() == carl::BoundType::INFTY )
1581 return std::numeric_limits<double>::infinity();
1582 impact = derivedEvalInterval.diameter();
1585 case 4: // Select according to optimal machine representation of bounds
1587 if( varInterval.contains(0) )
1588 impact = originalDiameter;
1590 impact = originalDiameter/(varInterval.upper() > 0 ? varInterval.lower() : varInterval.upper());
1595 impact = originalDiameter;
1596 if( varInterval.lower_bound_type() == carl::BoundType::STRICT )
1597 impact = std::nextafter( impact, -INFINITY );
1598 if( varInterval.upper_bound_type() == carl::BoundType::STRICT )
1599 impact = std::nextafter( impact, -INFINITY );
1603 #ifdef ICP_MODULE_DEBUG_1
1604 std::cout << __PRETTY_FUNCTION__ << " Rule " << mSplittingStrategy << ": " << impact << std::endl;
1609 template<class Settings>
1610 FormulaSetT ICPModule<Settings>::createPremiseDeductions()
1612 // collect applied contractions
1613 FormulaSetT contractions = mHistoryActual->appliedConstraints();
1614 // collect original box
1615 assert( mBoxStorage.size() > 0 );
1616 const FormulasT& box = mBoxStorage.front();
1617 for( auto& f : box )
1618 contractions.insert( f );
1620 return contractions;
1623 template<class Settings>
1624 FormulasT ICPModule<Settings>::createPremise()
1626 // collect applied contractions
1627 FormulasT contractions;
1628 mHistoryActual->appliedConstraints( contractions );
1629 // collect original box
1630 assert( mBoxStorage.size() > 0 );
1631 contractions.insert( contractions.end(), mBoxStorage.front().begin(), mBoxStorage.front().end() );
1633 return contractions;
1636 template<class Settings>
1637 FormulasT ICPModule<Settings>::createBoxFormula( bool _onlyOriginalVariables )
1639 carl::carlVariables originalRealVariables(carl::variable_type_filter::real());
1640 rReceivedFormula().gatherVariables(originalRealVariables);
1641 // TODO: store original variables as member, updating them efficiently with assert and remove
1642 FormulasT subformulas;
1643 for( auto intervalIt = mIntervals.begin(); intervalIt != mIntervals.end(); ++intervalIt )
1645 if( !_onlyOriginalVariables || originalRealVariables.has( (*intervalIt).first ) )
1647 std::pair<ConstraintT, ConstraintT> boundaries = icp::intervalToConstraint(Poly((*intervalIt).first), (*intervalIt).second);
1648 if( boundaries.first != ConstraintT() )
1649 subformulas.emplace_back( boundaries.first );
1650 if( boundaries.second != ConstraintT() )
1651 subformulas.emplace_back( boundaries.second );
1657 template<class Settings>
1658 bool ICPModule<Settings>::performSplit( bool _contractionApplied, bool& _furtherContractionApplied )
1660 assert( !intervalsEmpty() );
1662 bool leftCaseWeak = true;
1663 bool preferLeftCase = true;
1664 carl::Variable variable;
1665 switch( mSplittingHeuristic )
1667 case SplittingHeuristic::SIZE:
1668 sizeBasedSplitting( variable, bound, leftCaseWeak, preferLeftCase );
1670 case SplittingHeuristic::UNSATISFIABILITY:
1671 _furtherContractionApplied = satBasedSplitting( variable, bound, leftCaseWeak, preferLeftCase );
1673 case SplittingHeuristic::SATISFIABILITY:
1674 _furtherContractionApplied = satBasedSplitting( variable, bound, leftCaseWeak, preferLeftCase );
1679 SMTRAT_LOG_DEBUG("smtrat.icp", "Contraction applied? " << _furtherContractionApplied);
1680 if( !_furtherContractionApplied && variable != carl::Variable::NO_VARIABLE )
1682 SMTRAT_LOG_DEBUG("smtrat.icp", "Creating split");
1683 // create split: (not h_b OR (Not x<b AND x>=b) OR (x<b AND Not x>=b) )
1684 // first the premise: ((oldBox AND CCs) -> newBox) in CNF: (oldBox OR CCs) OR newBox
1685 std::vector<FormulaT> splitPremise = createPremise();
1686 if( _contractionApplied )
1688 FormulasT subformulas;
1689 subformulas.reserve(splitPremise.size()+1);
1690 for( auto formulaIt = splitPremise.begin(); formulaIt != splitPremise.end(); ++formulaIt )
1691 subformulas.emplace_back( carl::FormulaType::NOT, *formulaIt );
1692 // construct new box
1693 subformulas.emplace_back( carl::FormulaType::AND, std::move( createBoxFormula( true ) ) ); // TODO: only add this lemma if any contraction took place!!!
1695 addLemma( FormulaT( carl::FormulaType::OR, std::move(subformulas) ) );
1696 #ifdef ICP_MODULE_SHOW_PROGRESS
1697 addProgress( mInitialBoxSize - calculateCurrentBoxSize() );
1700 assert( variable != carl::Variable::NO_VARIABLE);
1701 Module::branchAt( variable, bound, std::move(splitPremise), leftCaseWeak, preferLeftCase );
1702 #ifdef ICP_MODULE_DEBUG_0
1703 std::cout << std::endl << "Force split on " << variable << " at " << bound << "!" << std::endl;
1704 printIntervals(true);
1711 template<class Settings>
1712 bool ICPModule<Settings>::splitToBoundedIntervalsWithoutZero( carl::Variable& _variable, Rational& _value, bool& _leftCaseWeak, bool& _preferLeftCase, std::vector<std::map<carl::Variable, icp::IcpVariable*>::const_iterator>& _suitableVariables )
1714 double valueAsDouble = 0;
1715 for( auto varIcpvarIter = mVariables.begin(); varIcpvarIter != mVariables.end(); ++varIcpvarIter )
1717 const auto& varInterval = varIcpvarIter->second->interval();
1718 if( varIcpvarIter->second->isOriginal() && varIcpvarIter->second->isActive() && !varInterval.is_point_interval() )
1720 if( varInterval.upper_bound_type() == carl::BoundType::INFTY )
1722 if( varInterval.lower_bound_type() != carl::BoundType::INFTY )
1724 // a is finite => if b = mDefaultSplittingSize is not in the interval give up otherwise split to <a,b] and (b,oo)
1725 assert( mDefaultSplittingSize > 0 );
1726 if( varInterval.lower() < mDefaultSplittingSize )
1728 _variable = varIcpvarIter->first;
1729 valueAsDouble = mDefaultSplittingSize;
1730 _leftCaseWeak = true;
1731 _preferLeftCase = true;
1732 _suitableVariables.push_back(varIcpvarIter);
1735 else // otherwise the interval is (-oo,oo) so keep 0
1737 _variable = varIcpvarIter->first;
1738 valueAsDouble = mDefaultSplittingSize;
1739 _leftCaseWeak = true;
1740 _preferLeftCase = true;
1741 _suitableVariables.push_back(varIcpvarIter);
1745 else if( varInterval.lower_bound_type() == carl::BoundType::INFTY ) // Variable interval is (-oo,a> and a finite
1747 // if b = -mDefaultSplittingSize is not in the interval give up otherwise split to (-oo,b) and [b,a>
1748 if( varInterval.upper() > -mDefaultSplittingSize )
1750 _variable = varIcpvarIter->first;
1751 valueAsDouble = -mDefaultSplittingSize;
1752 _preferLeftCase = false;
1753 _leftCaseWeak = false;
1754 _suitableVariables.push_back(varIcpvarIter);
1757 else if( varInterval.lower_bound_type() == carl::BoundType::WEAK && varInterval.lower() == 0 )
1759 // Variable interval is [0,a> => split it to [0,0] and (0,a>
1760 _variable = varIcpvarIter->first;
1761 valueAsDouble = varInterval.lower();
1762 _preferLeftCase = true;
1763 _leftCaseWeak = true;
1764 _suitableVariables.push_back(varIcpvarIter);
1766 else if( varInterval.upper_bound_type() == carl::BoundType::WEAK && varInterval.upper() == 0 )
1768 // Variable interval is <a,0] => split it to <a,0) and [0,0]
1769 _variable = varIcpvarIter->first;
1770 valueAsDouble = varInterval.upper();
1771 _preferLeftCase = false;
1772 _leftCaseWeak = false;
1773 _suitableVariables.push_back(varIcpvarIter);
1777 _suitableVariables.push_back(varIcpvarIter);
1779 if( _variable != carl::Variable::NO_VARIABLE )
1781 if( mSplittingHeuristic == SplittingHeuristic::SATISFIABILITY || mSplittingHeuristic == SplittingHeuristic::UNSATISFIABILITY )
1783 FormulaT violatedConstraint;
1784 EvalDoubleIntervalMap intervals = mIntervals;
1785 DoubleInterval leftSide( varInterval.lower(), varInterval.lower_bound_type(), valueAsDouble, (_leftCaseWeak ? carl::BoundType::WEAK : carl::BoundType::STRICT) );
1786 DoubleInterval rightSide( valueAsDouble, (_leftCaseWeak ? carl::BoundType::STRICT : carl::BoundType::WEAK), varInterval.upper(), varInterval.upper_bound_type() );
1787 intervals[_variable] = leftSide;
1788 if( satBasedSplittingImpact( *varIcpvarIter->second, intervals, rightSide, false ) < 0 )
1792 intervals[_variable] = rightSide;
1793 if( satBasedSplittingImpact( *varIcpvarIter->second, intervals, leftSide, false ) < 0 )
1798 _value = carl::rationalize<Rational>( valueAsDouble );
1806 template<class Settings>
1807 void ICPModule<Settings>::sizeBasedSplitting( carl::Variable& _variable, Rational& _value, bool& _leftCaseWeak, bool& _preferLeftCase )
1810 _leftCaseWeak = true;
1811 _preferLeftCase = true;
1812 std::vector<std::map<carl::Variable, icp::IcpVariable*>::const_iterator> suitableVariables;
1813 splitToBoundedIntervalsWithoutZero( _variable, _value, _leftCaseWeak, _preferLeftCase, suitableVariables );
1814 if( suitableVariables.empty() || _variable != carl::Variable::NO_VARIABLE )
1816 assert( _variable == carl::Variable::NO_VARIABLE );
1817 double maximalImpact = 0;
1818 double valueAsDouble = 0;
1819 std::map<carl::Variable, icp::IcpVariable*>::const_iterator bestVar = mVariables.end();
1820 for( const auto& varIcpvarIter : suitableVariables )
1822 if( varIcpvarIter->second->isOriginal() && varIcpvarIter->second->isActive() && !varIcpvarIter->second->interval().is_point_interval() )
1824 if( !fulfillsTarget(varIcpvarIter->second->interval()) )
1826 double actualImpact = sizeBasedSplittingImpact( varIcpvarIter );
1827 if( actualImpact > maximalImpact )
1829 valueAsDouble = carl::sample(varIcpvarIter->second->interval(), false );
1830 if( valueAsDouble == std::numeric_limits<double>::infinity() || valueAsDouble == -std::numeric_limits<double>::infinity() )
1834 bestVar = varIcpvarIter;
1835 maximalImpact = actualImpact;
1840 if( bestVar != mVariables.end() )
1842 // split at a nice number c in the interval: <a,c] and (c,b>
1843 _variable = bestVar->first;
1844 assert( !Settings::first_split_to_bounded_intervals_without_zero || !bestVar->second->interval().is_unbounded() );
1845 _value = carl::rationalize<Rational>( valueAsDouble );
1850 template<class Settings>
1851 bool ICPModule<Settings>::satBasedSplitting( carl::Variable& _variable, Rational& _value, bool& _leftCaseWeak, bool& _preferLeftCase )
1854 _leftCaseWeak = true;
1855 _preferLeftCase = true;
1856 std::vector<std::map<carl::Variable, icp::IcpVariable*>::const_iterator> suitableVariables;
1857 if( splitToBoundedIntervalsWithoutZero( _variable, _value, _leftCaseWeak, _preferLeftCase, suitableVariables ) )
1859 if( suitableVariables.empty() || _variable != carl::Variable::NO_VARIABLE )
1861 assert( _variable == carl::Variable::NO_VARIABLE );
1862 _leftCaseWeak = true;
1863 double valueAsDouble = 0;
1864 double maximalImpact = -1;
1865 for( const auto& varIcpvarIter : suitableVariables )
1867 const auto& varInterval = varIcpvarIter->second->interval();
1868 if( !varIcpvarIter->second->isOriginal() || !varIcpvarIter->second->isActive()
1869 || varIcpvarIter->second->interval().is_point_interval() || fulfillsTarget(varInterval) )
1873 assert( !Settings::first_split_to_bounded_intervals_without_zero || !varInterval.is_unbounded() );
1874 valueAsDouble = carl::sample( varInterval, false );
1875 if( valueAsDouble == std::numeric_limits<double>::infinity() || valueAsDouble == -std::numeric_limits<double>::infinity() )
1879 bool leftCaseWeak = true;
1880 if( valueAsDouble == varInterval.upper() )
1881 leftCaseWeak = false;
1882 EvalDoubleIntervalMap intervals = mIntervals;
1883 DoubleInterval leftSide( varInterval.lower(), varInterval.lower_bound_type(), valueAsDouble, leftCaseWeak ? carl::BoundType::WEAK : carl::BoundType::STRICT );
1884 DoubleInterval rightSide( valueAsDouble, leftCaseWeak ? carl::BoundType::STRICT : carl::BoundType::WEAK, varInterval.upper(), varInterval.upper_bound_type() );
1885 intervals[varIcpvarIter->first] = leftSide;
1886 FormulaT violatedConstraint;
1887 double impactLeftCase = satBasedSplittingImpact( *varIcpvarIter->second, intervals, rightSide, true );
1888 if( impactLeftCase < 0 )
1892 intervals[varIcpvarIter->first] = rightSide;
1893 double impactRightCase = satBasedSplittingImpact( *varIcpvarIter->second, intervals, leftSide, true );
1894 if( impactRightCase < 0 )
1898 if( impactLeftCase > impactRightCase )
1900 if( impactLeftCase > maximalImpact )
1902 maximalImpact = impactLeftCase;
1903 _variable = varIcpvarIter->first;
1904 _preferLeftCase = true;
1905 _value = carl::rationalize<Rational>( valueAsDouble );
1910 if( impactRightCase > maximalImpact )
1912 maximalImpact = impactRightCase;
1913 _variable = varIcpvarIter->first;
1914 _preferLeftCase = false;
1915 _value = carl::rationalize<Rational>( valueAsDouble );
1922 // #define ICP_SAT_BASED_SPLITTING_DEBUG
1924 template<class Settings>
1925 double ICPModule<Settings>::satBasedSplittingImpact( icp::IcpVariable& _icpVar, const EvalDoubleIntervalMap& _intervals, const DoubleInterval& _seperatedPart, bool _calculateImpact )
1927 assert( !intervalsEmpty( _intervals ) );
1928 assert( mSplittingHeuristic == SplittingHeuristic::SATISFIABILITY || mSplittingHeuristic == SplittingHeuristic::UNSATISFIABILITY );
1930 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
1931 std::cout << _intervals << std::endl;
1933 for( const auto& rec : rReceivedFormula() )
1935 assert( rec.formula().type() == carl::FormulaType::CONSTRAINT );
1936 const ConstraintT& constraint = rec.formula().constraint();
1937 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
1938 std::cout << constraint << std::endl;
1940 DoubleInterval solutionSpace = carl::evaluate( constraint.lhs(), _intervals );
1941 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
1942 std::cout << solutionSpace << std::endl;
1944 switch( constraint.relation() )
1946 case carl::Relation::EQ:
1947 if( solutionSpace.contains( 0 ) )
1949 if( mSplittingHeuristic == SplittingHeuristic::UNSATISFIABILITY )
1951 if( solutionSpace.is_unbounded() )
1953 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
1954 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
1956 return std::numeric_limits<double>::infinity();
1958 if( !_calculateImpact )
1960 assert( (solutionSpace.diameter()/ (double) rReceivedFormula().size()) >= (double) 0 );
1961 result += (solutionSpace.diameter()/ (double) rReceivedFormula().size());
1966 splittingBasedContraction( _icpVar, rec.formula(), _seperatedPart );
1970 case carl::Relation::LEQ:
1971 if( solutionSpace > (double)0 )
1973 splittingBasedContraction( _icpVar, rec.formula(), _seperatedPart );
1978 if( mSplittingHeuristic == SplittingHeuristic::SATISFIABILITY )
1980 if( solutionSpace.lower_bound_type() == carl::BoundType::INFTY )
1982 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
1983 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
1985 return std::numeric_limits<double>::infinity();
1987 if( !_calculateImpact )
1989 if( solutionSpace.upper_bound_type() != carl::BoundType::INFTY && solutionSpace.upper() < (double) 0 )
1991 assert( (solutionSpace.diameter()/ (double) rReceivedFormula().size()) >= (double) 0 );
1992 result += (solutionSpace.diameter()/ (double) rReceivedFormula().size());
1996 assert( (-solutionSpace.lower()/ (double) rReceivedFormula().size()) >= (double) 0 );
1997 result += (-solutionSpace.lower()/ (double) rReceivedFormula().size());
2002 if( solutionSpace.upper_bound_type() == carl::BoundType::INFTY )
2004 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2005 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
2007 return std::numeric_limits<double>::infinity();
2009 if( !_calculateImpact )
2011 if( solutionSpace.upper() > (double) 0 )
2013 assert( solutionSpace.lower_bound_type() == carl::BoundType::INFTY || solutionSpace.lower() <= (double) 0 );
2014 assert( (solutionSpace.upper()/ (double) rReceivedFormula().size()) >= (double) 0 );
2015 result += (solutionSpace.upper()/ (double) rReceivedFormula().size());
2020 case carl::Relation::GEQ:
2021 if( solutionSpace < (double)0 )
2023 splittingBasedContraction( _icpVar, rec.formula(), _seperatedPart );
2028 if( mSplittingHeuristic == SplittingHeuristic::SATISFIABILITY )
2030 if( solutionSpace.upper_bound_type() == carl::BoundType::INFTY )
2032 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2033 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
2035 return std::numeric_limits<double>::infinity();
2037 if( !_calculateImpact )
2039 if( solutionSpace.lower_bound_type() != carl::BoundType::INFTY && solutionSpace.lower() > (double) 0 )
2041 assert( (solutionSpace.diameter()/ (double) rReceivedFormula().size()) >= (double) 0 );
2042 result += (solutionSpace.diameter()/ (double) rReceivedFormula().size());
2046 assert( (solutionSpace.upper()/ (double) rReceivedFormula().size()) >= (double) 0 );
2047 result += (solutionSpace.upper()/ (double) rReceivedFormula().size());
2052 if( solutionSpace.lower_bound_type() == carl::BoundType::INFTY )
2054 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2055 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
2057 return std::numeric_limits<double>::infinity();
2059 if( !_calculateImpact )
2061 if( solutionSpace.lower() < (double) 0 )
2063 assert( solutionSpace.upper_bound_type() == carl::BoundType::INFTY || solutionSpace.upper() <= (double) 0 );
2064 assert( (-solutionSpace.lower()/ (double) rReceivedFormula().size()) >= (double) 0 );
2065 result += (-solutionSpace.lower()/ (double) rReceivedFormula().size());
2070 case carl::Relation::LESS:
2071 if( solutionSpace >= (double)0 )
2073 splittingBasedContraction( _icpVar, rec.formula(), _seperatedPart );
2078 if( mSplittingHeuristic == SplittingHeuristic::SATISFIABILITY )
2080 if( solutionSpace.lower_bound_type() == carl::BoundType::INFTY )
2082 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2083 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
2085 return std::numeric_limits<double>::infinity();
2087 if( !_calculateImpact )
2089 if( solutionSpace.upper_bound_type() != carl::BoundType::INFTY && solutionSpace.upper() < (double) 0 )
2091 assert( (solutionSpace.diameter()/ (double) rReceivedFormula().size()) >= (double) 0 );
2092 result += (solutionSpace.diameter()/ (double) rReceivedFormula().size());
2096 assert( (-solutionSpace.lower()/ (double) rReceivedFormula().size()) >= (double) 0 );
2097 result += (-solutionSpace.lower()/ (double) rReceivedFormula().size());
2102 if( solutionSpace.upper_bound_type() == carl::BoundType::INFTY )
2104 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2105 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
2107 return std::numeric_limits<double>::infinity();
2109 if( !_calculateImpact )
2111 if( solutionSpace.upper() > (double) 0 )
2113 assert( solutionSpace.lower_bound_type() == carl::BoundType::INFTY || solutionSpace.lower() < (double) 0 );
2114 assert( (solutionSpace.upper()/ (double) rReceivedFormula().size()) >= (double) 0 );
2115 result += (solutionSpace.upper()/ (double) rReceivedFormula().size());
2120 case carl::Relation::GREATER:
2121 if( solutionSpace <= (double)0 )
2123 splittingBasedContraction( _icpVar, rec.formula(), _seperatedPart );
2128 if( mSplittingHeuristic == SplittingHeuristic::SATISFIABILITY )
2130 if( solutionSpace.upper_bound_type() == carl::BoundType::INFTY )
2132 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2133 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
2135 return std::numeric_limits<double>::infinity();
2137 if( !_calculateImpact )
2139 if( solutionSpace.lower_bound_type() != carl::BoundType::INFTY && solutionSpace.lower() > (double) 0 )
2141 assert( (solutionSpace.diameter()/ (double) rReceivedFormula().size()) >= (double) 0 );
2142 result += (solutionSpace.diameter()/ (double) rReceivedFormula().size());
2146 assert( (solutionSpace.upper()/ (double) rReceivedFormula().size()) >= (double) 0 );
2147 result += (solutionSpace.upper()/ (double) rReceivedFormula().size());
2152 if( solutionSpace.lower_bound_type() == carl::BoundType::INFTY )
2154 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2155 std::cout << "Result: " << std::numeric_limits<double>::infinity() << std::endl;
2157 return std::numeric_limits<double>::infinity();
2159 if( !_calculateImpact )
2161 if( solutionSpace.lower() < (double) 0 )
2163 assert( solutionSpace.upper_bound_type() == carl::BoundType::INFTY || solutionSpace.upper() < (double) 0 );
2164 assert( (-solutionSpace.lower()/ (double) rReceivedFormula().size()) >= (double) 0 );
2165 result += (-solutionSpace.lower()/ (double) rReceivedFormula().size());
2170 default: // carl::Relation::NEQ
2175 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2176 std::cout << "Result: " << result << std::endl;
2181 template<class Settings>
2182 void ICPModule<Settings>::splittingBasedContraction( icp::IcpVariable& _icpVar, const FormulaT& _violatedConstraint, const DoubleInterval& _contractedInterval )
2184 #ifdef ICP_SAT_BASED_SPLITTING_DEBUG
2185 std::cout << "Result: -1" << std::endl;
2187 assert( !carl::is_bound(_violatedConstraint.constraint()) );
2188 assert( _violatedConstraint.type() == carl::FormulaType::CONSTRAINT );
2189 bool constraintContainsSplittingVar = _violatedConstraint.constraint().variables().has( _icpVar.var() );
2190 setContraction( _violatedConstraint, _icpVar, (constraintContainsSplittingVar ? DoubleInterval::empty_interval() : _contractedInterval), constraintContainsSplittingVar );
2191 if( constraintContainsSplittingVar )
2195 template<class Settings>
2196 bool ICPModule<Settings>::tryTestPoints()
2198 // find a point within the intervals
2199 carl::carlVariables originalRealVariables(carl::variable_type_filter::real());
2200 rReceivedFormula().gatherVariables(originalRealVariables);
2201 // TODO: store original variables as member, updating them efficiently with assert and remove
2202 std::map<carl::Variable, double> antipoint = createModel( true );
2203 mFoundSolution.clear();
2204 #ifdef ICP_MODULE_DEBUG_0
2205 std::cout << __func__ << ":" << std::endl;
2207 if( antipoint.empty() )
2209 #ifdef ICP_MODULE_DEBUG_0
2210 std::cout << " Failed!" << std::endl << std::endl;
2214 bool boxContainsOnlyOneSolution = true;
2215 auto origVarsIter = originalRealVariables.begin();
2216 for( auto iter = antipoint.begin(); iter != antipoint.end(); ++iter )
2218 SMTRAT_LOG_TRACE("smtrat.module.icp", "Checking antipoint " << iter->first << " = " << iter->second);
2219 // Add an assignment for variables only occurring in constraints with != as relation symbol
2220 while( origVarsIter != originalRealVariables.end() && *origVarsIter < iter->first )
2222 mFoundSolution.emplace(*origVarsIter, 0); // TODO: find a rational assignment which most probably satisfies this inequality
2225 if( origVarsIter != originalRealVariables.end() )
2227 if (std::isinf(iter->second) || std::isnan(iter->second)) {
2230 assert(!std::isinf(iter->second) && !std::isnan(iter->second));
2231 // rationalize the found test point for the given dimension
2232 Rational value = carl::rationalize<Rational>( iter->second );
2233 // check if the test point, which has been generated for double intervals, does not satisfy the rational
2234 // original bounds in this dimension (might occur, as we over-approximated them)
2235 auto lraVarBoundsIter = mInitialIntervals.find( iter->first );
2236 if( lraVarBoundsIter != mInitialIntervals.end() )
2238 const RationalInterval& varBounds = lraVarBoundsIter->second;
2239 assert( !varBounds.is_empty() );
2240 if( varBounds.is_point_interval() )
2242 value = varBounds.lower();
2246 assert( iter->first.type() != carl::VariableType::VT_INT || varBounds.is_unbounded() || varBounds.diameter() >= 1 );
2247 if( iter->first.type() != carl::VariableType::VT_INT )
2248 boxContainsOnlyOneSolution = false;
2249 if( varBounds.lower_bound_type() != carl::BoundType::INFTY && value < varBounds.lower() )
2251 if( varBounds.lower_bound_type() == carl::BoundType::STRICT )
2253 value = carl::sample( varBounds, false );
2257 value = varBounds.lower();
2260 else if( varBounds.upper_bound_type() != carl::BoundType::INFTY && value > varBounds.upper() )
2262 if( varBounds.upper_bound_type() == carl::BoundType::STRICT )
2264 value = carl::sample( varBounds, false );
2268 value = varBounds.upper();
2272 assert( varBounds.contains( value ) );
2274 #ifdef ICP_MODULE_DEBUG_0
2275 std::cout << " " << iter->first << " -> " << std::setprecision(10) << iter->second << " [" << value << "]" << std::endl;
2277 mFoundSolution.emplace(iter->first, value);
2279 bool has_unknown = false;
2280 bool has_conflict = false;
2281 for (const auto& rf : rReceivedFormula()) {
2282 assert( rf.formula().type() == carl::FormulaType::CONSTRAINT );
2283 unsigned isSatisfied = carl::satisfied_by(rf.formula().constraint(), mFoundSolution);
2284 if (isSatisfied == 2) has_unknown = true;
2285 else if (isSatisfied == 0) {
2286 has_conflict = true;
2287 if (boxContainsOnlyOneSolution) {
2288 // TODO: create infeasible subset and return UNSAT in checkCore
2294 mFoundSolution.clear();
2295 #ifdef ICP_MODULE_DEBUG_0
2296 if( !has_conflict ) std::cout << " Success!" << std::endl << std::endl;
2298 return !has_unknown && !has_conflict;
2301 template<class Settings>
2302 bool ICPModule<Settings>::initialLinearCheck( Answer& _answer )
2304 #ifdef ICP_MODULE_DEBUG_1
2305 std::cout << "Initial linear check:" << std::endl;
2307 // call mLRA to check linear feasibility
2309 mValidationFormula->updateProperties();
2310 _answer = mLRA.check( mFinalCheck, true );
2315 for( const auto& lem : mLRA.lemmas() )
2317 #ifdef ICP_MODULE_DEBUG_2
2318 std::cout << "Create lemma for: " << lem.mLemma << std::endl;
2320 FormulaT lemma = getReceivedFormulas(lem.mLemma);
2321 addLemma(lemma, lem.mLemmaType);
2322 #ifdef ICP_MODULE_DEBUG_2
2323 std::cout << "Passed lemma: " << lemma << std::endl;
2328 if( _answer == UNSAT )
2330 // remap infeasible subsets to original constraints
2331 remapAndSetLraInfeasibleSubsets();
2332 #ifdef ICP_MODULE_DEBUG_1
2333 std::cout << "LRA: " << _answer << std::endl;
2337 else if( !Settings::just_contraction && _answer == SAT ) // _answer == SAT, but no nonlinear constraints -> linear solution is a solution
2339 #ifdef ICP_MODULE_DEBUG_1
2340 std::cout << "LRA: " << _answer << std::endl;
2342 bool solutionFound = true;
2343 RationalAssignment sol = mLRA.getRationalModel();
2344 for( const auto& rf : rReceivedFormula() )
2346 assert( rf.formula().type() == carl::FormulaType::CONSTRAINT );
2347 const ConstraintT& cons = rf.formula().constraint();
2348 assert( !cons.lhs().is_linear() || cons.relation() == carl::Relation::NEQ || carl::satisfied_by( cons,sol ) == 1 );
2349 if( (!cons.lhs().is_linear() || cons.relation() == carl::Relation::NEQ) && carl::satisfied_by( cons,sol ) != 1 )
2351 solutionFound = false;
2358 if( !Settings::just_contraction && !lemmas().empty() && _answer == UNKNOWN )
2360 // get intervals for initial variables
2361 mInitialIntervals = mLRA.getVariableBounds();
2362 #ifdef ICP_MODULE_DEBUG_1
2363 std::cout << "Newly obtained Intervals: " << std::endl;
2365 for ( auto constraintIt = mInitialIntervals.begin(); constraintIt != mInitialIntervals.end(); ++constraintIt )
2367 #ifdef ICP_MODULE_DEBUG_1
2368 std::cout << (*constraintIt).first << ": " << (*constraintIt).second << std::endl;
2370 const RationalInterval& tmp = (*constraintIt).second;
2371 DoubleInterval newInterval = DoubleInterval(tmp.lower(), tmp.lower_bound_type(), tmp.upper(), tmp.upper_bound_type());
2372 mHistoryRoot->addInterval((*constraintIt).first, newInterval );
2373 if( Settings::original_polynomial_contraction && mVariables.find(constraintIt->first) == mVariables.end() )
2375 mIntervals[(*constraintIt).first] = newInterval;
2379 assert( mVariables.find(constraintIt->first) != mVariables.end() );
2380 mVariables.find((*constraintIt).first)->second->setInterval( newInterval );
2383 // get intervals for slackvariables
2384 const LRAModule<LRASettings1>::ExVariableMap slackVariables = mLRA.slackVariables();
2385 for( auto slackIt = slackVariables.begin(); slackIt != slackVariables.end(); ++slackIt )
2387 std::map<const icp::LRAVariable*, ContractionCandidates>::iterator linIt = mLinearConstraints.find((*slackIt).second);
2388 if ( linIt != mLinearConstraints.end() )
2390 // dirty hack: expect lhs to be set and take first item of set of CCs --> Todo: Check if it is really set in the constructors of the CCs during inform and assert
2391 RationalInterval tmp = (*slackIt).second->getVariableBounds();
2392 // keep root updated about the initial box.
2393 mHistoryRoot->rIntervals()[(*(*linIt).second.begin())->lhs()] = DoubleInterval(tmp.lower(), tmp.lower_bound_type(), tmp.upper(), tmp.upper_bound_type());
2394 // No need to propagate update-status in the icp-variable
2395 assert( mIntervals.find( (*(*linIt).second.begin())->lhs() ) != mIntervals.end() );
2396 mIntervals[(*(*linIt).second.begin())->lhs()] = DoubleInterval(tmp.lower(), tmp.lower_bound_type(), tmp.upper(), tmp.upper_bound_type());
2397 #ifdef ICP_MODULE_DEBUG_2
2398 std::cout << "Added interval (slackvariables): " << (*(*linIt).second.begin())->lhs() << " " << tmp << std::endl;
2402 // temporary solution - an added linear constraint might have changed the box.
2403 setBox(mHistoryRoot);
2404 mHistoryRoot->rReasons().clear();
2405 mHistoryRoot->rStateInfeasibleConstraints().clear();
2406 mHistoryRoot->rStateInfeasibleVariables().clear();
2407 #ifdef ICP_MODULE_DEBUG_1
2408 std::cout << "actual box: ";
2409 mHistoryActual->print(std::cout);
2410 std::cout << std::endl;
2415 template<class Settings>
2416 bool ICPModule<Settings>::checkBoxAgainstLinearFeasibleRegion()
2418 FormulasT addedBoundaries = createConstraintsFromBounds(mIntervals,false);
2419 for( auto formulaIt = addedBoundaries.begin(); formulaIt != addedBoundaries.end(); )
2421 auto res = mValidationFormula->add( *formulaIt );
2424 mLRA.inform( *formulaIt );
2425 mLRA.add( res.first );
2430 formulaIt = addedBoundaries.erase(formulaIt);
2433 mValidationFormula->updateProperties();
2434 Answer boxCheck = mLRA.check( false, true );
2435 #ifdef ICP_MODULE_DEBUG_1
2437 std::cout << "Boxcheck: " << boxCheck << std::endl;
2439 #ifdef SMTRAT_DEVOPTION_VALIDATION_ICP
2440 if ( boxCheck == UNSAT )
2442 FormulaT actualAssumptions = FormulaT(*mValidationFormula);
2443 SMTRAT_VALIDATION_ADD("smtrat.modules.icp","ICP_BoxValidation",actualAssumptions,false);
2446 if( boxCheck != UNKNOWN )
2448 if( boxCheck != SAT )
2450 std::vector<FormulaSetT> tmpSet = mLRA.infeasibleSubsets();
2451 for ( auto infSetIt = tmpSet.begin(); infSetIt != tmpSet.end(); ++infSetIt )
2453 for ( auto formulaIt = (*infSetIt).begin(); formulaIt != (*infSetIt).end(); ++formulaIt )
2455 if( !carl::is_bound(formulaIt->constraint()) )
2457 mHistoryActual->addInfeasibleConstraint(formulaIt->constraint());
2458 for( auto variable: formulaIt->variables() )
2460 assert( mVariables.find(variable) != mVariables.end() );
2461 mHistoryActual->addInfeasibleVariable(mVariables.at(variable));
2466 assert( mVariables.find( *formulaIt->variables().begin() ) != mVariables.end() );
2467 mHistoryActual->addInfeasibleVariable( mVariables.at( *formulaIt->variables().begin() ) );
2472 else if( Settings::prolong_contraction )
2474 EvalRationalIntervalMap bounds = mLRA.getVariableBounds();
2475 #ifdef ICP_MODULE_DEBUG_1
2476 std::cout << "Newly obtained Intervals: " << std::endl;
2478 for ( auto boundIt = bounds.begin(); boundIt != bounds.end(); ++boundIt )
2480 if( Settings::original_polynomial_contraction && mVariables.find((*boundIt).first) == mVariables.end() )
2482 assert( mVariables.find((*boundIt).first) != mVariables.end() );
2483 icp::IcpVariable& icpVar = *mVariables.find((*boundIt).first)->second;
2484 RationalInterval tmp = (*boundIt).second;
2485 const DoubleInterval& icpVarInterval = icpVar.interval();
2486 // mHistoryRoot->addInterval((*boundIt).first, DoubleInterval(tmp.lower(), tmp.lower_bound_type(), tmp.upper(), tmp.upper_bound_type()) );
2487 DoubleInterval newInterval = DoubleInterval(tmp.lower(), tmp.lower_bound_type(), tmp.upper(), tmp.upper_bound_type() );
2488 if( !(icpVarInterval == newInterval) && icpVarInterval.contains(newInterval) )
2490 #ifdef ICP_MODULE_DEBUG_1
2491 std::cout << (*boundIt).first << ": " << (*boundIt).second << std::endl;
2493 updateRelativeContraction( icpVarInterval, newInterval );
2494 icpVar.setInterval( newInterval );
2495 updateRelevantCandidates((*boundIt).first);
2499 // get intervals for slackvariables
2500 const LRAModule<LRASettings1>::ExVariableMap slackVariables = mLRA.slackVariables();
2501 for ( auto slackIt = slackVariables.begin(); slackIt != slackVariables.end(); ++slackIt )
2503 std::map<const icp::LRAVariable*, ContractionCandidates>::iterator linIt = mLinearConstraints.find((*slackIt).second);
2504 if ( linIt != mLinearConstraints.end() )
2506 // dirty hack: expect lhs to be set and take first item of set of CCs --> Todo: Check if it is really set in the constructors of the CCs during inform and assert
2507 RationalInterval tmp = (*slackIt).second->getVariableBounds();
2508 // keep root updated about the initial box.
2509 // mHistoryRoot->rIntervals()[(*(*linIt).second.begin())->lhs()] = DoubleInterval(tmp.lower(), tmp.lower_bound_type(), tmp.upper(), tmp.upper_bound_type());
2510 DoubleInterval newInterval = DoubleInterval(tmp.lower(), tmp.lower_bound_type(), tmp.upper(), tmp.upper_bound_type() );
2511 carl::Variable var = (*(*linIt).second.begin())->lhs();
2512 icp::IcpVariable& icpVar = *mVariables.at(var);
2513 const DoubleInterval& icpVarInterval = icpVar.interval();
2514 if( !(icpVarInterval == newInterval) && icpVarInterval.contains(newInterval) )
2516 updateRelativeContraction( icpVarInterval, newInterval );
2517 icpVar.setInterval( newInterval );
2518 updateRelevantCandidates(var);
2519 #ifdef ICP_MODULE_DEBUG_2
2520 std::cout << "Added interval (slackvariables): " << var << " " << tmp << std::endl;
2527 // remove boundaries from mLRA module after boxChecking.
2528 for( auto boundIt = addedBoundaries.begin(); boundIt != addedBoundaries.end(); )
2530 auto pos = mValidationFormula->find( *boundIt );
2531 if( pos != mValidationFormula->end() )
2534 mValidationFormula->erase( pos );
2536 boundIt = addedBoundaries.erase(boundIt);
2540 assert(addedBoundaries.empty());
2542 if ( boxCheck == UNSAT )
2547 template<class Settings>
2548 void ICPModule<Settings>::pushBoundsToPassedFormula()
2550 carl::carlVariables originalRealVariables(carl::variable_type_filter::real());
2551 rReceivedFormula().gatherVariables(originalRealVariables);
2552 // TODO: store original variables as member, updating them efficiently with assert and remove
2553 auto varIntervalIter = mIntervals.begin();
2554 auto varInitialIntervalIter = mInitialIntervals.begin();
2555 for( std::map<carl::Variable, icp::IcpVariable*>::iterator iter = mVariables.begin(); iter != mVariables.end(); ++iter )
2557 carl::Variable::Arg tmpSymbol = iter->first;
2558 icp::IcpVariable& icpVar = *iter->second;
2559 if( icpVar.isOriginal() && originalRealVariables.has( tmpSymbol ) )
2561 if( icpVar.isExternalUpdated() != icp::Updated::NONE )
2563 while( varIntervalIter->first < tmpSymbol )
2565 assert( varIntervalIter != mIntervals.end() );
2568 while( varInitialIntervalIter != mInitialIntervals.end() && varInitialIntervalIter->first < tmpSymbol )
2570 ++varInitialIntervalIter;
2572 const DoubleInterval& interval = varIntervalIter->second;
2574 icp::Updated icpVarExUpdated = icpVar.isExternalUpdated();
2575 // generate both bounds, left first
2576 if( icpVarExUpdated == icp::Updated::BOTH || icpVarExUpdated == icp::Updated::LEFT )
2578 FormulaT leftTmp = intervalBoundToFormula( tmpSymbol, interval, varInitialIntervalIter, false );
2579 if( icpVar.externalLeftBound() != passedFormulaEnd() )
2581 Module::eraseSubformulaFromPassedFormula( icpVar.externalLeftBound(), true );
2583 if ( leftTmp.is_true() )
2585 icpVar.setExternalLeftBound( passedFormulaEnd() );
2589 addConstraintToInform( leftTmp );
2590 auto res = addSubformulaToPassedFormula( leftTmp );
2593 icpVar.setExternalLeftBound( res.first );
2598 if( icpVarExUpdated == icp::Updated::BOTH || icpVarExUpdated == icp::Updated::RIGHT )
2601 FormulaT rightTmp = intervalBoundToFormula( tmpSymbol, interval, varInitialIntervalIter, true );
2602 if( icpVar.externalRightBound() != passedFormulaEnd() )
2604 Module::eraseSubformulaFromPassedFormula( icpVar.externalRightBound(), true );
2606 if( rightTmp.is_true() )
2608 icpVar.setExternalRightBound( passedFormulaEnd() );
2612 addConstraintToInform( rightTmp );
2613 auto res = addSubformulaToPassedFormula( rightTmp );
2616 icpVar.setExternalRightBound( res.first );
2620 icpVar.setExternalUnmodified();
2626 template<class Settings>
2627 EvalRationalIntervalMap ICPModule<Settings>::getCurrentBoxAsIntervals() const
2629 EvalRationalIntervalMap result;
2630 carl::carlVariables originalRealVariables(carl::variable_type_filter::real());
2631 rReceivedFormula().gatherVariables(originalRealVariables);
2632 // TODO: store original variables as member, updating them efficiently with assert and remove
2633 auto varIntervalIter = mIntervals.begin();
2634 auto varInitialIntervalIter = mInitialIntervals.begin();
2635 for( std::map<carl::Variable, icp::IcpVariable*>::const_iterator iter = mVariables.begin(); iter != mVariables.end(); ++iter )
2637 carl::Variable::Arg tmpSymbol = iter->first;
2638 const icp::IcpVariable& icpVar = *iter->second;
2639 if( icpVar.isOriginal() && originalRealVariables.has( tmpSymbol ) )
2641 while( varIntervalIter->first < tmpSymbol )
2643 assert( varIntervalIter != mIntervals.end() );
2646 while( varInitialIntervalIter != mInitialIntervals.end() && varInitialIntervalIter->first < tmpSymbol )
2648 ++varInitialIntervalIter;
2650 const DoubleInterval& interval = varIntervalIter->second;
2651 assert( result.find( tmpSymbol ) == result.end() );
2652 result.emplace( tmpSymbol, doubleToRationalInterval( tmpSymbol, interval, varInitialIntervalIter ) );
2658 template<class Settings>
2659 FormulasT ICPModule<Settings>::getCurrentBoxAsFormulas() const
2662 carl::carlVariables originalRealVariables(carl::variable_type_filter::real());
2663 rReceivedFormula().gatherVariables(originalRealVariables);
2664 // TODO: store original variables as member, updating them efficiently with assert and remove
2665 auto varIntervalIter = mIntervals.begin();
2666 auto varInitialIntervalIter = mInitialIntervals.begin();
2667 for( std::map<carl::Variable, icp::IcpVariable*>::const_iterator iter = mVariables.begin(); iter != mVariables.end(); ++iter )
2669 carl::Variable::Arg tmpSymbol = iter->first;
2670 const icp::IcpVariable& icpVar = *iter->second;
2671 if( icpVar.isOriginal() && originalRealVariables.has( tmpSymbol ) )
2673 while( varIntervalIter->first < tmpSymbol )
2675 assert( varIntervalIter != mIntervals.end() );
2678 while( varInitialIntervalIter != mInitialIntervals.end() && varInitialIntervalIter->first < tmpSymbol )
2680 ++varInitialIntervalIter;
2682 const DoubleInterval& interval = varIntervalIter->second;
2683 FormulaT leftTmp = intervalBoundToFormula( tmpSymbol, interval, varInitialIntervalIter, false );
2684 if( !leftTmp.is_true() )
2685 result.push_back( leftTmp );
2686 FormulaT rightTmp = intervalBoundToFormula( tmpSymbol, interval, varInitialIntervalIter, true );
2687 if( !rightTmp.is_true() )
2688 result.push_back( rightTmp );
2694 template<class Settings>
2695 RationalInterval ICPModule<Settings>::doubleToRationalInterval( carl::Variable::Arg _var, const DoubleInterval& _interval, EvalRationalIntervalMap::const_iterator _initialIntervalIter ) const
2697 Rational lbound = carl::rationalize<Rational>( _interval.lower() );
2698 Rational ubound = carl::rationalize<Rational>( _interval.upper() );
2699 carl::BoundType lboundType = _interval.lower_bound_type();
2700 carl::BoundType uboundType = _interval.upper_bound_type();
2701 if( _initialIntervalIter != mInitialIntervals.end() && _initialIntervalIter->first == _var )
2703 const RationalInterval& varBounds = _initialIntervalIter->second;
2704 if( varBounds.upper_bound_type() != carl::BoundType::INFTY && (uboundType == carl::BoundType::INFTY || ubound > varBounds.upper()) )
2706 ubound = varBounds.upper();
2707 uboundType = varBounds.upper_bound_type();
2709 if( varBounds.lower_bound_type() != carl::BoundType::INFTY && (lboundType == carl::BoundType::INFTY || lbound < varBounds.lower()) )
2711 lbound = varBounds.lower();
2712 lboundType = varBounds.lower_bound_type();
2715 return RationalInterval( lbound, lboundType, ubound, uboundType );
2718 template<class Settings>
2719 FormulaT ICPModule<Settings>::intervalBoundToFormula( carl::Variable::Arg _var, const DoubleInterval& _interval, EvalRationalIntervalMap::const_iterator _initialIntervalIter, bool _upper ) const
2721 Rational bound = carl::rationalize<Rational>( _upper ? _interval.upper() : _interval.lower() );
2722 carl::BoundType boundType = _upper ? _interval.upper_bound_type() : _interval.lower_bound_type();
2723 if( _initialIntervalIter != mInitialIntervals.end() && _initialIntervalIter->first == _var )
2725 const RationalInterval& varBounds = _initialIntervalIter->second;
2728 if( varBounds.upper_bound_type() != carl::BoundType::INFTY && (boundType == carl::BoundType::INFTY || bound > varBounds.upper()) )
2730 bound = varBounds.upper();
2731 boundType = varBounds.upper_bound_type();
2736 if( varBounds.lower_bound_type() != carl::BoundType::INFTY && (boundType == carl::BoundType::INFTY || bound < varBounds.lower()) )
2738 bound = varBounds.lower();
2739 boundType = varBounds.lower_bound_type();
2744 Poly p = Poly( _var ) - Poly(bound);
2745 FormulaT result( carl::FormulaType::TRUE );
2748 case carl::BoundType::STRICT:
2749 result = FormulaT( p, _upper ? carl::Relation::LESS : carl::Relation::GREATER );
2751 case carl::BoundType::WEAK:
2752 result = FormulaT( p, _upper ? carl::Relation::LEQ : carl::Relation::GEQ );
2760 template<class Settings>
2761 FormulasT ICPModule<Settings>::variableReasonHull( icp::set_icpVariable& _reasons )
2764 for( auto variableIt = _reasons.begin(); variableIt != _reasons.end(); ++variableIt )
2766 if ((*variableIt)->lraVar() != nullptr)
2768 FormulasT definingOriginsTmp = (*variableIt)->lraVar()->getDefiningOrigins();
2769 FormulasT definingOrigins;
2770 for( auto& f : definingOriginsTmp )
2772 if( rReceivedFormula().contains( f ) )
2773 collectOrigins( f, definingOrigins );
2775 for( auto formulaIt = definingOrigins.begin(); formulaIt != definingOrigins.end(); ++formulaIt )
2777 // std::cout << "Defining origin: " << **formulaIt << " FOR " << *(*variableIt) << std::endl;
2778 bool hasAdditionalVariables = false;
2779 carl::carlVariables realValuedVars(carl::variable_type_filter::real());
2780 rReceivedFormula().gatherVariables(realValuedVars);
2781 // TODO: store original variables as member, updating them efficiently with assert and remove
2782 for( auto varIt = realValuedVars.begin(); varIt != realValuedVars.end(); ++varIt )
2784 if(*varIt != (*variableIt)->var() && formulaIt->constraint().variables().has(*varIt))
2786 hasAdditionalVariables = true;
2790 if( hasAdditionalVariables)
2792 // std::cout << "Addidional variables." << std::endl;
2793 for( auto receivedFormulaIt = rReceivedFormula().begin(); receivedFormulaIt != rReceivedFormula().end(); ++receivedFormulaIt )
2795 if( receivedFormulaIt->formula().constraint().variables().has((*variableIt)->var()) && carl::is_bound(receivedFormulaIt->formula().constraint()) )
2797 reasons.push_back( receivedFormulaIt->formula() );
2798 // std::cout << "Also add: " << **receivedFormulaIt << std::endl;
2804 // std::cout << "No additional variables." << std::endl;
2805 auto replacementIt = mDeLinearizations.find( *formulaIt );
2806 assert( replacementIt != mDeLinearizations.end() ); // TODO (from Florian): Do we need this?
2807 reasons.push_back((*replacementIt).second);
2808 } // has no additional variables
2809 } // for all definingOrigins
2815 template<class Settings>
2816 FormulasT ICPModule<Settings>::createConstraintsFromBounds( const EvalDoubleIntervalMap& _map, bool _onlyOriginals )
2818 FormulasT addedBoundaries;
2819 for ( auto variablesIt = mVariables.begin(); variablesIt != mVariables.end(); ++variablesIt )
2821 if( (_onlyOriginals && !variablesIt->second->isOriginal()) || !variablesIt->second->isActive() )
2823 carl::Variable tmpSymbol = variablesIt->first;
2824 if ( _map.find(tmpSymbol) != _map.end() )
2826 if( variablesIt->second->lraVar() != nullptr )
2828 std::pair<ConstraintT, ConstraintT> boundaries = icp::intervalToConstraint(Poly(variablesIt->second->lraVar()->expression()), _map.at(tmpSymbol));
2829 if( boundaries.second != ConstraintT() )
2831 assert( boundaries.second.is_consistent() == 2 );
2832 FormulaT rightBound = FormulaT(boundaries.second);
2833 addedBoundaries.push_back(rightBound);
2834 #ifdef ICP_MODULE_DEBUG_2
2835 std::cout << "Created upper boundary constraint: " << rightBound << std::endl;
2838 if( boundaries.first != ConstraintT() )
2840 assert( boundaries.first.is_consistent() == 2 );
2841 FormulaT leftBound = FormulaT(boundaries.first);
2842 addedBoundaries.push_back(leftBound);
2843 #ifdef ICP_MODULE_DEBUG_2
2844 std::cout << "Created lower boundary constraint: " << leftBound << std::endl;
2848 // if( (*variablesIt).second->isInternalBoundsSet() == icp::Updated::BOTH && (*variablesIt).second->isInternalUpdated() == icp::Updated::NONE )
2850 // addedBoundaries.push_back((*variablesIt).second->internalLeftBound());
2851 // addedBoundaries.push_back((*variablesIt).second->internalRightBound());
2853 // else if( variablesIt->second->lraVar() != nullptr )
2855 // std::pair<ConstraintT, ConstraintT> boundaries = icp::intervalToConstraint(Poly(variablesIt->second->lraVar()->expression()), _map.at(tmpSymbol));
2856 // icp::Updated inBoundsSet = (*variablesIt).second->isInternalBoundsSet();
2857 // icp::Updated inBoundsUpdated = (*variablesIt).second->isInternalUpdated();
2858 // if( boundaries.second != ConstraintT() &&
2859 // (inBoundsUpdated == icp::Updated::BOTH || inBoundsUpdated == icp::Updated::RIGHT || inBoundsSet == icp::Updated::NONE || inBoundsSet == icp::Updated::LEFT) )
2861 // assert( boundaries.second.is_consistent() == 2 );
2862 // FormulaT rightBound = FormulaT(boundaries.second);
2863 // (*variablesIt).second->setInternalRightBound(rightBound);
2864 // addedBoundaries.push_back(rightBound);
2865 // #ifdef ICP_MODULE_DEBUG_2
2866 // std::cout << "Created upper boundary constraint: " << rightBound << std::endl;
2869 // if( boundaries.first != ConstraintT() &&
2870 // (inBoundsUpdated == icp::Updated::BOTH || inBoundsUpdated == icp::Updated::LEFT || inBoundsSet == icp::Updated::NONE || inBoundsSet == icp::Updated::RIGHT) )
2872 // assert( boundaries.first.is_consistent() == 2 );
2873 // FormulaT leftBound = FormulaT(boundaries.first);
2874 // (*variablesIt).second->setInternalLeftBound(leftBound);
2875 // addedBoundaries.push_back(leftBound);
2876 // #ifdef ICP_MODULE_DEBUG_2
2877 // std::cout << "Created lower boundary constraint: " << leftBound << std::endl;
2883 return addedBoundaries;
2886 template<class Settings>
2887 FormulaT ICPModule<Settings>::getReceivedFormulas( const FormulaT& _deduction )
2889 if( _deduction.type() == carl::FormulaType::CONSTRAINT )
2891 auto iter = mDeLinearizations.find( _deduction );
2892 if( iter == mDeLinearizations.end() )
2894 const ConstraintT& c = _deduction.constraint();
2895 return FormulaT( carl::substitute(c.lhs(), mSubstitutions), c.relation() );
2899 return iter->second;
2902 else if( _deduction.type() == carl::FormulaType::NOT )
2904 return FormulaT( carl::FormulaType::NOT, getReceivedFormulas( _deduction.subformula() ) );
2906 else if( _deduction.is_boolean_combination() )
2908 FormulasT subformulas;
2909 for( const FormulaT& subformula : _deduction.subformulas() )
2911 subformulas.push_back( getReceivedFormulas( subformula ) );
2913 return FormulaT( _deduction.type(), subformulas );
2915 else if (_deduction.type() == carl::FormulaType::BOOL) {
2922 return FormulaT( carl::FormulaType::TRUE );
2926 template<class Settings>
2927 void ICPModule<Settings>::remapAndSetLraInfeasibleSubsets()
2929 const std::vector<FormulaSetT>& tmpSet = mLRA.infeasibleSubsets();
2930 for ( auto infSetIt = tmpSet.begin(); infSetIt != tmpSet.end(); ++infSetIt )
2933 for( auto formulaIt = (*infSetIt).begin(); formulaIt != (*infSetIt).end(); ++formulaIt )
2935 auto delinIt = mDeLinearizations.find(*formulaIt);
2936 assert( delinIt != mDeLinearizations.end() );
2937 if( rReceivedFormula().contains( delinIt->second ) )
2939 newSet.insert( delinIt->second );
2942 assert(newSet.size() == (*infSetIt).size());
2943 mInfeasibleSubsets.push_back(std::move(newSet));
2947 template<class Settings>
2948 double ICPModule<Settings>::calculateCurrentBoxSize()
2950 if( mIntervals.empty() ) return 0.0;
2951 double result = 1.0;
2952 for( const auto& interv : mIntervals )
2954 auto varIt = mVariables.find(interv.first);
2955 if( varIt != mVariables.end() && varIt->second->isOriginal() )
2957 result *= interv.second.diameter();
2963 template<class Settings>
2964 void ICPModule<Settings>::addProgress( double _progress )
2966 if( _progress > 0.0 )
2968 mCovererdRegionSize += _progress;
2970 std::cout << std::setprecision(10) << std::setw(20) << (mCovererdRegionSize > 0 ? ((mCovererdRegionSize/mGlobalBoxSize)*100.0) : 0.0) << " %";
2975 template<class Settings>
2976 void ICPModule<Settings>::setBox( icp::HistoryNode* _selection )
2978 assert(_selection != nullptr);
2979 #ifdef ICP_MODULE_DEBUG_1
2980 std::cout << "Set box -> ";
2981 _selection->print(std::cout);
2982 std::cout << ", #intervals: " << mIntervals.size() << " -> " << _selection->intervals().size() << std::endl;
2984 // set intervals - currently we don't change not contained intervals.
2985 for ( auto constraintIt = _selection->rIntervals().begin(); constraintIt != _selection->rIntervals().end(); ++constraintIt )
2987 assert(mIntervals.find((*constraintIt).first) != mIntervals.end());
2988 // only update intervals which changed
2989 if ( !(mIntervals.at((*constraintIt).first)==(*constraintIt).second) )
2991 std::map<carl::Variable, icp::IcpVariable*>::const_iterator icpVar = mVariables.find((*constraintIt).first);
2992 // std::cout << "Searching for " << (*intervalIt).first.get_name() << std::endl;
2993 assert(icpVar != mVariables.end());
2994 (*icpVar).second->setInterval( (*constraintIt).second );
2997 // set actual node as selection
2998 mHistoryActual = _selection;
3001 template<class Settings>
3002 bool ICPModule<Settings>::intervalsEmpty( const EvalDoubleIntervalMap& _intervals ) const
3004 for( const auto& interval : _intervals )
3006 if( interval.second.is_empty() ) return true;
3011 template<class Settings>
3012 bool ICPModule<Settings>::intervalsEmpty( bool _original ) const
3014 for ( auto constraintIt = mIntervals.begin(); constraintIt != mIntervals.end(); ++constraintIt )
3016 auto varIt = mVariables.find((*constraintIt).first);
3017 //assert( varIt != mVariables.end() );//TODO (from FLorian): can we assume this?
3018 if( !_original || (varIt != mVariables.end() && varIt->second->isOriginal()))
3020 if( (*constraintIt).second.is_empty() ) return true;
3026 #ifdef ICP_MODULE_DEBUG_METHODS
3027 template<class Settings>
3028 void ICPModule<Settings>::debugPrint() const
3030 std::cout << "********************* linear Constraints **********************" << std::endl;
3031 for( auto linearIt = mLinearConstraints.begin(); linearIt != mLinearConstraints.end(); ++linearIt){
3032 for ( auto candidateIt = (*linearIt).second.begin(); candidateIt != (*linearIt).second.end(); ++candidateIt )
3034 std::cout << (*candidateIt)->id() << ": " << (*candidateIt)->constraint() << std::endl;
3037 std::cout << "****************** active linear constraints ******************" << std::endl;
3038 for(auto activeLinearIt = mActiveLinearConstraints.begin(); activeLinearIt != mActiveLinearConstraints.end(); ++activeLinearIt){
3039 std::cout << "Count: " << (*activeLinearIt)->activity() << " , ";
3040 (*activeLinearIt)->print();
3042 std::cout << "******************* active linear variables *******************" << std::endl;
3043 for (auto variableIt = mVariables.begin(); variableIt != mVariables.end(); ++variableIt )
3045 if ( (*variableIt).second->is_linear() )
3046 std::cout << (*variableIt).first << ", ";
3048 std::cout << std::endl;
3049 std::cout << "******************** nonlinear constraints ********************" << std::endl;
3050 ContractionCandidates::iterator replacementsIt;
3051 for(auto nonlinearIt = mNonlinearConstraints.begin(); nonlinearIt != mNonlinearConstraints.end(); ++nonlinearIt){
3052 std::cout << (*nonlinearIt).first << std::endl;
3053 std::cout << "\t replacements: " << std::endl;
3054 for(replacementsIt = nonlinearIt->second.begin(); replacementsIt != nonlinearIt->second.end(); ++replacementsIt)
3057 (*replacementsIt)->print();
3060 std::cout << "**************** active nonlinear constraints *****************" << std::endl;
3061 for( auto activeNonlinearIt = mActiveNonlinearConstraints.begin(); activeNonlinearIt != mActiveNonlinearConstraints.end(); ++activeNonlinearIt )
3063 std::cout << "Count: " << (*activeNonlinearIt)->activity() << " , ";
3064 (*activeNonlinearIt)->print();
3066 std::cout << "***************** active nonlinear variables ******************" << std::endl;
3067 for (auto variableIt = mVariables.begin(); variableIt != mVariables.end(); ++variableIt )
3069 if ( (*variableIt).second->is_linear() )
3070 std::cout << (*variableIt).first << ", ";
3072 std::cout << std::endl;
3073 std::cout << "************************** Intervals **************************" << std::endl;
3074 for ( auto constraintIt = mIntervals.begin(); constraintIt != mIntervals.end(); ++constraintIt )
3076 std::cout << (*constraintIt).first << " \t -> \t" << (*constraintIt).second << std::endl;
3078 std::cout << std::endl;
3079 std::cout << "************************* Linearizations ************************" << std::endl;
3080 for ( auto replacementIt = mLinearizations.begin(); replacementIt != mLinearizations.end(); ++replacementIt )
3082 std::cout << (*replacementIt).first << " \t -> \t" << (*replacementIt).second << std::endl;
3084 std::cout << std::endl;
3085 std::cout << "************************* Delinearizations ************************" << std::endl;
3086 for ( auto replacementIt = mDeLinearizations.begin(); replacementIt != mDeLinearizations.end(); ++replacementIt )
3088 std::cout << (*replacementIt).first << " \t -> \t" << (*replacementIt).second << std::endl;
3090 std::cout << std::endl;
3091 std::cout << "************************* ICP carl::Variables ***********************" << std::endl;
3092 for ( auto variablesIt = mVariables.begin(); variablesIt != mVariables.end(); ++variablesIt )
3093 (*variablesIt).second->print( std::cout, true );
3095 std::cout << std::endl;
3096 std::cout << "*********************** ValidationFormula *********************" << std::endl;
3097 std::cout << mValidationFormula << std::endl;
3098 std::cout << "***************************************************************" << std::endl;
3100 std::cout << "************************* Substitution ************************" << std::endl;
3101 for( auto subsIt = mSubstitutions.begin(); subsIt != mSubstitutions.end(); ++subsIt )
3102 std::cout << (*subsIt).first << " -> " << (*subsIt).second << std::endl;
3104 std::cout << "***************************************************************" << std::endl;
3107 template<class Settings>
3108 void ICPModule<Settings>::printAffectedCandidates() const
3110 for ( auto varIt = mVariables.begin(); varIt != mVariables.end(); ++varIt )
3112 for ( auto candidateIt = (*varIt).second->candidates().begin(); candidateIt != (*varIt).second->candidates().end(); ++candidateIt)
3114 std::cout << (*varIt).first << "\t -> ";
3115 (*candidateIt)->print();
3120 template<class Settings>
3121 void ICPModule<Settings>::printIcpVariables() const
3123 for ( auto varIt = mVariables.begin(); varIt != mVariables.end(); ++varIt )
3124 (*varIt).second->print( std::cout, true );
3127 template<class Settings>
3128 void ICPModule<Settings>::printIcpRelevantCandidates() const
3130 std::cout << "Size icpRelevantCandidates: " << mIcpRelevantCandidates.size() << std::endl;
3131 for ( auto candidateIt = mIcpRelevantCandidates.begin(); candidateIt != mIcpRelevantCandidates.end(); ++candidateIt )
3133 std::cout << (*candidateIt).first << " \t " << (*candidateIt).second <<"\t Candidate: ";
3134 icp::ContractionCandidate* cc = mCandidateManager.getCandidate((*candidateIt).second);
3135 assert( cc != nullptr );
3140 template<class Settings>
3141 void ICPModule<Settings>::printIntervals( bool _original ) const
3143 for ( auto constraintIt = mIntervals.begin(); constraintIt != mIntervals.end(); ++constraintIt )
3145 auto varIt = mVariables.find((*constraintIt).first);
3146 //assert( varIt != mVariables.end() );//TODO (from FLorian): can we assume this?
3147 if( !_original || (varIt != mVariables.end() && varIt->second->isOriginal()))
3149 std::cout << std::setw(10) << (*constraintIt).first;
3150 std::stringstream s;
3151 s << (*constraintIt).second;
3152 std::cout << ":" << std::setw(30) << s.str();
3153 std::cout << std::endl;
3158 template<class Settings>
3159 void ICPModule<Settings>::printPreprocessedInput( std::string _init ) const
3161 ConstraintT last = ConstraintT();
3162 for(auto activeLinearIt = mActiveLinearConstraints.begin(); activeLinearIt != mActiveLinearConstraints.end(); ++activeLinearIt){
3163 if( (*activeLinearIt)->constraint() != last )
3165 last = (*activeLinearIt)->constraint();
3166 std::cout << _init << last << std::endl;
3169 last = ConstraintT();
3170 for(auto activeNoninearIt = mActiveNonlinearConstraints.begin(); activeNoninearIt != mActiveNonlinearConstraints.end(); ++activeNoninearIt){
3171 if( (*activeNoninearIt)->constraint() != last )
3173 last = (*activeNoninearIt)->constraint();
3174 std::cout << _init << last << std::endl;
3179 template<class Settings>
3180 void ICPModule<Settings>::printContraction( const icp::ContractionCandidate& _cc, const DoubleInterval& _before, const DoubleInterval& _afterA, const DoubleInterval& _afterB, std::ostream& _out ) const
3182 _out << ((mRelativeContraction > 0 || mAbsoluteContraction > 0) ? "#" : " ");
3183 _out << std::setw(10) << _cc.derivationVar();
3184 std::stringstream s;
3185 s << std::setprecision(20) << _before;
3186 _out << ":" << std::setw(50) << s.str();
3187 std::stringstream s2;
3188 if( _afterB.is_empty() )
3190 s2 << std::setprecision(20) << _afterA;
3194 s2 << std::setprecision(20) << _afterA << " or " << std::setprecision(20) << _afterB;
3196 _out << " -> " << std::setw(50) << std::left << s2.str();
3197 _out << std::right << " with " << _cc.contractor().polynomial() << " (" << _cc.RWA() << ")" << std::endl;
3200 } // namespace smtrat