2 * @file VariableBounds.h
3 * @author Florian Corzilius
13 Bound<T>::Bound( Rational* const _limit, Variable<T>* const _variable, Type _type ):
16 mpVariable( _variable ),
17 mpOrigins( new std::set<T,carl::less<T,false>>() )
20 mpOrigins->insert( T() );
32 bool Bound<T>::operator<( const Bound<T>& _bound ) const
34 if( isUpperBound() && _bound.isUpperBound() )
40 if( _bound.isInfinite() )
44 if( *mpLimit < _bound.limit() )
46 else if( *mpLimit == _bound.limit() )
48 if( mType == STRICT_UPPER_BOUND )
49 return (_bound.type() != STRICT_UPPER_BOUND);
50 else if( mType == EQUAL_BOUND )
51 return (_bound.type() == WEAK_UPPER_BOUND);
59 assert( isLowerBound() && _bound.isLowerBound() );
60 if( _bound.isInfinite() )
68 if( *mpLimit < _bound.limit() )
70 else if( *mpLimit == _bound.limit() )
72 if( mType == WEAK_LOWER_BOUND )
73 return (_bound.type() != WEAK_LOWER_BOUND);
74 else if( mType == EQUAL_BOUND )
75 return (_bound.type() == STRICT_LOWER_BOUND);
85 std::ostream& operator<<( std::ostream& _out, const Bound<T>& _bound )
87 if( _bound.isInfinite() )
89 if( _bound.type() == Bound<T>::STRICT_LOWER_BOUND )
95 _out << _bound.limit();
101 void Bound<T>::print( std::ostream& _out, bool _withRelation ) const
107 case STRICT_LOWER_BOUND:
110 case WEAK_LOWER_BOUND:
116 case WEAK_UPPER_BOUND:
119 case STRICT_UPPER_BOUND:
133 Variable<T>::Variable():
134 mUpdatedExactInterval( true ),
135 mUpdatedDoubleInterval( true ),
136 mUpperbounds( Variable<T>::BoundSet() ),
137 mLowerbounds( Variable<T>::BoundSet() )
139 mUpperbounds.insert( new Bound<T>( nullptr, this, Bound<T>::STRICT_UPPER_BOUND ) );
140 mpSupremum = *mUpperbounds.begin();
141 mLowerbounds.insert( new Bound<T>( nullptr, this, Bound<T>::STRICT_LOWER_BOUND ) );
142 mpInfimum = *mLowerbounds.begin();
147 Variable<T>::~Variable()
149 while( !mLowerbounds.empty() )
151 const Bound<T>* toDelete = *mLowerbounds.begin();
152 mLowerbounds.erase( mLowerbounds.begin() );
153 if( toDelete->type() != Bound<T>::EQUAL_BOUND )
156 while( !mUpperbounds.empty() )
158 const Bound<T>* toDelete = *mUpperbounds.begin();
159 mUpperbounds.erase( mUpperbounds.begin() );
166 bool Variable<T>::conflicting() const
168 if( mpSupremum->isInfinite() || mpInfimum->isInfinite() )
172 if( mpSupremum->limit() < mpInfimum->limit() )
174 else if( mpInfimum->limit() == mpSupremum->limit() )
175 return ( mpInfimum->type() == Bound<T>::STRICT_LOWER_BOUND || mpSupremum->type() == Bound<T>::STRICT_UPPER_BOUND );
182 const Bound<T>* Variable<T>::addBound( const ConstraintT& _constraint, const carl::Variable& _var, const T& _origin )
184 assert( _constraint.variables().size() == 1 );
185 if( _constraint.maxDegree( _var ) == 1 )
187 const Rational coeff = _constraint.lhs().lterm().coeff();
188 carl::Relation rel = _constraint.relation();
189 Rational* limit = new Rational( -_constraint.lhs().constant_part()/coeff );
190 std::pair< typename Variable<T>::BoundSet::iterator, bool> result;
191 if( rel == carl::Relation::EQ )
193 Bound<T>* newBound = new Bound<T>( limit, this, Bound<T>::EQUAL_BOUND );
194 result = mUpperbounds.insert( newBound );
198 mLowerbounds.insert( newBound );
200 else if( ( rel == carl::Relation::GEQ && coeff < 0 ) || ( rel == carl::Relation::LEQ && coeff > 0 ) )
202 Bound<T>* newBound = new Bound<T>( limit, this, Bound<T>::WEAK_UPPER_BOUND );
203 result = mUpperbounds.insert( newBound );
207 else if( ( rel == carl::Relation::LEQ && coeff < 0 ) || ( rel == carl::Relation::GEQ && coeff > 0 ) )
209 Bound<T>* newBound = new Bound<T>( limit, this, Bound<T>::WEAK_LOWER_BOUND );
210 result = mLowerbounds.insert( newBound );
214 else if( ( rel == carl::Relation::GREATER && coeff < 0 ) || ( rel == carl::Relation::LESS && coeff > 0 ) )
216 Bound<T>* newBound = new Bound<T>( limit, this, Bound<T>::STRICT_UPPER_BOUND );
217 result = mUpperbounds.insert( newBound );
221 else if( ( rel == carl::Relation::LESS && coeff < 0 ) || ( rel == carl::Relation::GREATER && coeff > 0 ) )
223 Bound<T>* newBound = new Bound<T>( limit, this, Bound<T>::STRICT_LOWER_BOUND );
224 result = mLowerbounds.insert( newBound );
230 (*result.first)->activate( _origin );
231 return *result.first;
233 // else if( _constraint.lhs().nr_terms() == 1 || (_constraint.lhs().nr_terms() == 2 && _constraint.lhs().has_constant_term()) )
235 // // TODO: Retrieve bounds from constraints of the form x^n+b~0
243 bool Variable<T>::updateBounds( const Bound<T>& _changedBound )
245 mUpdatedExactInterval = true;
246 mUpdatedDoubleInterval = true;
247 if( _changedBound.isUpperBound() )
249 // Update the supremum.
250 typename Variable<T>::BoundSet::iterator newBound = mUpperbounds.begin();
251 while( newBound != mUpperbounds.end() )
253 if( (*newBound)->isActive() )
255 mpSupremum = *newBound;
261 if( _changedBound.isLowerBound() )
263 // Update the infimum.
264 typename Variable<T>::BoundSet::reverse_iterator newBound = mLowerbounds.rbegin();
265 while( newBound != mLowerbounds.rend() )
267 if( (*newBound)->isActive() )
269 mpInfimum = *newBound;
275 return conflicting();
280 VariableBounds<T>::VariableBounds():
281 mpConflictingVariable( NULL ),
282 mpVariableMap( new VariableMap() ),
283 mpConstraintBoundMap( new ConstraintBoundMap() ),
285 mDoubleIntervalMap(),
291 VariableBounds<T>::~VariableBounds()
293 delete mpConstraintBoundMap;
294 while( !mpVariableMap->empty() )
296 Variable<T>* toDelete = mpVariableMap->begin()->second;
297 mpVariableMap->erase( mpVariableMap->begin() );
300 delete mpVariableMap;
304 void VariableBounds<T>::clear()
306 mpConflictingVariable = NULL;
307 mpConstraintBoundMap->clear();
308 while( !mpVariableMap->empty() )
310 Variable<T>* toDelete = mpVariableMap->begin()->second;
311 mpVariableMap->erase( mpVariableMap->begin() );
314 mBoundDeductions.clear();
315 mDoubleIntervalMap.clear();
316 mEvalIntervalMap.clear();
320 bool VariableBounds<T>::addBound( const ConstraintT& _constraint, const T& _origin )
322 if( _constraint.relation() != carl::Relation::NEQ )
324 auto vars = carl::variables(_constraint);
325 carl::Variable var = *vars.begin();
326 if( vars.size() == 1 && _constraint.maxDegree( var ) == 1 )
328 typename VariableBounds<T>::ConstraintBoundMap::iterator cbPair = mpConstraintBoundMap->find( _constraint );
329 if( cbPair != mpConstraintBoundMap->end() )
331 const Bound<T>& bound = *cbPair->second;
332 if( bound.activate( _origin ) )
334 if( bound.pVariable()->updateBounds( bound ) )
335 mpConflictingVariable = bound.pVariable();
340 Variable<T>* variable;
341 const Bound<T>* bound;
342 typename VariableBounds<T>::VariableMap::iterator evPair = mpVariableMap->find( var );
343 if( evPair != mpVariableMap->end() )
345 variable = evPair->second;
346 bound = variable->addBound( _constraint, evPair->first, _origin );
350 variable = new Variable<T>();
351 (*mpVariableMap)[var] = variable;
352 bound = variable->addBound( _constraint, var, _origin );
354 mpConstraintBoundMap->insert( std::pair< ConstraintT, const Bound<T>* >( _constraint, bound ) );
355 if( variable->updateBounds( *bound ) )
356 mpConflictingVariable = bound->pVariable();
362 if( mNonBoundConstraints.insert( _constraint ).second )
364 for (auto sym: carl::variables(_constraint))
366 Variable<T>* variable = new Variable<T>();
367 if( !mpVariableMap->insert( std::pair< const carl::Variable, Variable<T>* >( sym, variable ) ).second )
375 for (auto sym: carl::variables(_constraint))
377 Variable<T>* variable = new Variable<T>();
378 if( !mpVariableMap->insert( std::pair< const carl::Variable, Variable<T>* >( sym, variable ) ).second )
386 bool VariableBounds<T>::addBound( const FormulaT& _formula, const T& _origin ) {
387 switch (_formula.type()) {
388 case carl::FormulaType::CONSTRAINT:
389 return addBound(_formula.constraint(), _origin);
390 case carl::FormulaType::NOT: {
391 if (_formula.subformula().type() == carl::FormulaType::CONSTRAINT) {
392 const ConstraintT& c = _formula.subformula().constraint();
393 return addBound(ConstraintT(c.lhs(), carl::inverse(c.relation())), _origin);
397 case carl::FormulaType::AND: {
399 for (const auto& f: _formula.subformulas()) {
400 res = res || addBound(f, _origin);
410 unsigned VariableBounds<T>::removeBound( const ConstraintT& _constraint, const T& _origin )
412 if( _constraint.relation() != carl::Relation::NEQ )
414 auto vars = carl::variables(_constraint);
415 carl::Variable var = *vars.begin();
416 if( vars.size() == 1 && _constraint.maxDegree( var ) == 1 )
418 assert( mpConstraintBoundMap->find( _constraint ) != mpConstraintBoundMap->end() );
419 const Bound<T>& bound = *(*mpConstraintBoundMap)[_constraint];
420 if( bound.deactivate( _origin ) )
422 if( bound.pVariable()->updateBounds( bound ) )
423 mpConflictingVariable = bound.pVariable();
425 mpConflictingVariable = NULL;
432 mNonBoundConstraints.erase( _constraint );
439 unsigned VariableBounds<T>::removeBound( const ConstraintT& _constraint, const T& _origin, carl::Variable*& _changedVariable )
441 if( _constraint.relation() != carl::Relation::NEQ )
443 auto vars = carl::variables(_constraint);
444 carl::Variable var = *vars.begin();
445 if( vars.size() == 1 && _constraint.maxDegree( var ) == 1 )
447 assert( mpConstraintBoundMap->find( _constraint ) != mpConstraintBoundMap->end() );
448 const Bound<T>& bound = *(*mpConstraintBoundMap)[_constraint];
449 if( bound.deactivate( _origin ) )
451 if( bound.pVariable()->updateBounds( bound ) )
452 mpConflictingVariable = bound.pVariable();
454 mpConflictingVariable = NULL;
455 _changedVariable = new carl::Variable( var );
462 mNonBoundConstraints.erase( _constraint );
469 unsigned VariableBounds<T>::removeBound(const FormulaT& _formula, const T& _origin) {
470 switch (_formula.type()) {
471 case carl::FormulaType::CONSTRAINT:
472 return removeBound(_formula.constraint(), _origin);
473 case carl::FormulaType::NOT: {
474 if (_formula.subformula().type() == carl::FormulaType::CONSTRAINT) {
475 const ConstraintT& c = _formula.subformula().constraint();
476 return removeBound(ConstraintT(c.lhs(), carl::inverse(c.relation())), _origin);
480 case carl::FormulaType::AND: {
482 for (const auto& f: _formula.subformulas()) {
483 res = std::max(res, removeBound(f, _origin));
492 #define CONVERT_BOUND(type, namesp) (type != Bound<T>::WEAK_UPPER_BOUND && type != Bound<T>::WEAK_LOWER_BOUND && type != Bound<T>::EQUAL_BOUND ) ? namesp::STRICT : namesp::WEAK
495 const smtrat::EvalRationalIntervalMap& VariableBounds<T>::getEvalIntervalMap() const
497 assert( mpConflictingVariable == NULL );
498 for( auto varVarPair = mpVariableMap->begin(); varVarPair != mpVariableMap->end(); ++varVarPair )
500 Variable<T>& var = *varVarPair->second;
501 if( var.updatedExactInterval() )
503 carl::BoundType lowerBoundType;
504 Rational lowerBoundValue;
505 carl::BoundType upperBoundType;
506 Rational upperBoundValue;
507 if( var.infimum().isInfinite() )
509 lowerBoundType = carl::BoundType::INFTY;
514 lowerBoundType = CONVERT_BOUND( var.infimum().type(), carl::BoundType );
515 lowerBoundValue = var.infimum().limit();
517 if( var.supremum().isInfinite() )
519 upperBoundType = carl::BoundType::INFTY;
524 upperBoundType = CONVERT_BOUND( var.supremum().type(), carl::BoundType );
525 upperBoundValue = var.supremum().limit();
527 mEvalIntervalMap[varVarPair->first] = RationalInterval( lowerBoundValue, lowerBoundType, upperBoundValue, upperBoundType );
528 var.exactIntervalHasBeenUpdated();
531 return mEvalIntervalMap;
536 const RationalInterval& VariableBounds<T>::getInterval( const carl::Variable& _var ) const
538 assert( mpConflictingVariable == NULL );
539 typename VariableMap::iterator varVarPair = mpVariableMap->find( _var );
540 if( varVarPair == mpVariableMap->end() )
542 Variable<T>* var = new Variable<T>();
543 mpVariableMap->emplace( _var, var );
544 auto ret = mEvalIntervalMap.emplace( _var, RationalInterval::unbounded_interval() );
545 var->exactIntervalHasBeenUpdated();
546 mDoubleIntervalMap.emplace( _var, carl::Interval<double>::unbounded_interval() );
547 var->doubleIntervalHasBeenUpdated();
548 return ret.first->second;
552 Variable<T>& var = *varVarPair->second;
553 if( var.updatedExactInterval() )
555 carl::BoundType lowerBoundType;
556 Rational lowerBoundValue;
557 carl::BoundType upperBoundType;
558 Rational upperBoundValue;
559 if( var.infimum().isInfinite() )
561 lowerBoundType = carl::BoundType::INFTY;
566 lowerBoundType = CONVERT_BOUND( var.infimum().type(), carl::BoundType );
567 lowerBoundValue = var.infimum().limit();
569 if( var.supremum().isInfinite() )
571 upperBoundType = carl::BoundType::INFTY;
576 upperBoundType = CONVERT_BOUND( var.supremum().type(), carl::BoundType );
577 upperBoundValue = var.supremum().limit();
579 mEvalIntervalMap[_var] = RationalInterval( lowerBoundValue, lowerBoundType, upperBoundValue, upperBoundType );
580 var.exactIntervalHasBeenUpdated();
583 return mEvalIntervalMap[_var];
587 RationalInterval VariableBounds<T>::getInterval( carl::Monomial::Arg _mon ) const
589 RationalInterval res(1);
590 for (const auto& vexp: *_mon) {
591 const RationalInterval& i = getInterval(vexp.first);
592 res *= carl::pow(i, vexp.second);
598 RationalInterval VariableBounds<T>::getInterval( const TermT& _term ) const
600 if (_term.is_constant()) return RationalInterval(_term.coeff());
601 return getInterval(_term.monomial()) * _term.coeff();
605 const smtrat::EvalDoubleIntervalMap& VariableBounds<T>::getIntervalMap() const
607 assert( mpConflictingVariable == NULL );
608 for( auto varVarPair = mpVariableMap->begin(); varVarPair != mpVariableMap->end(); ++varVarPair )
610 Variable<T>& var = *varVarPair->second;
611 if( var.updatedDoubleInterval() )
613 carl::BoundType lowerBoundType;
614 Rational lowerBoundValue;
615 carl::BoundType upperBoundType;
616 Rational upperBoundValue;
617 if( var.infimum().isInfinite() )
619 lowerBoundType = carl::BoundType::INFTY;
624 lowerBoundType = CONVERT_BOUND( var.infimum().type(), carl::BoundType );
625 lowerBoundValue = var.infimum().limit();
627 if( var.supremum().isInfinite() )
629 upperBoundType = carl::BoundType::INFTY;
634 upperBoundType = CONVERT_BOUND( var.supremum().type(), carl::BoundType );
635 upperBoundValue = var.supremum().limit();
637 mDoubleIntervalMap[varVarPair->first] = carl::Interval<double>( lowerBoundValue, lowerBoundType, upperBoundValue, upperBoundType );
638 var.doubleIntervalHasBeenUpdated();
641 return mDoubleIntervalMap;
646 const carl::Interval<double>& VariableBounds<T>::getDoubleInterval( const carl::Variable& _var ) const
648 assert( mpConflictingVariable == NULL );
649 typename VariableMap::iterator varVarPair = mpVariableMap->find( _var );
651 if( varVarPair == mpVariableMap->end() )
653 Variable<T>* var = new Variable<T>();
654 mpVariableMap->emplace( _var, var );
655 mEvalIntervalMap.emplace( _var, RationalInterval::unbounded_interval() );
656 var->exactIntervalHasBeenUpdated();
657 auto ret = mDoubleIntervalMap.emplace( _var, carl::Interval<double>::unbounded_interval() );
658 var->doubleIntervalHasBeenUpdated();
659 return ret.first->second;
663 Variable<T>& var = *varVarPair->second;
664 if( var.updatedDoubleInterval() )
666 carl::BoundType lowerBoundType;
667 Rational lowerBoundValue;
668 carl::BoundType upperBoundType;
669 Rational upperBoundValue;
670 if( var.infimum().isInfinite() )
672 lowerBoundType = carl::BoundType::INFTY;
677 lowerBoundType = CONVERT_BOUND( var.infimum().type(), carl::BoundType );
678 lowerBoundValue = var.infimum().limit();
680 if( var.supremum().isInfinite() )
682 upperBoundType = carl::BoundType::INFTY;
687 upperBoundType = CONVERT_BOUND( var.supremum().type(), carl::BoundType );
688 upperBoundValue = var.supremum().limit();
690 mDoubleIntervalMap[_var] = carl::Interval<double>( lowerBoundValue, lowerBoundType, upperBoundValue, upperBoundType );
691 var.doubleIntervalHasBeenUpdated();
694 return mDoubleIntervalMap[_var];
698 std::vector<T> VariableBounds<T>::getOriginsOfBounds( const carl::Variable& _var ) const
700 std::vector<T> originsOfBounds;
701 auto varVarPair = mpVariableMap->find( _var );
702 if( varVarPair != mpVariableMap->end() )
704 if( !varVarPair->second->infimum().isInfinite() ) originsOfBounds.push_back( *varVarPair->second->infimum().origins().begin() );
705 if( !varVarPair->second->supremum().isInfinite() ) originsOfBounds.push_back( *varVarPair->second->supremum().origins().begin() );
707 return originsOfBounds;
711 std::vector<T> VariableBounds<T>::getOriginsOfBounds( const carl::Variables& _variables ) const
713 std::vector<T> originsOfBounds;
714 for( auto var = _variables.begin(); var != _variables.end(); ++var )
716 auto varVarPair = mpVariableMap->find( *var );
717 if( varVarPair != mpVariableMap->end() )
719 if( !varVarPair->second->infimum().isInfinite() ) originsOfBounds.push_back( *varVarPair->second->infimum().origins().begin() );
720 if( !varVarPair->second->supremum().isInfinite() ) originsOfBounds.push_back( *varVarPair->second->supremum().origins().begin() );
723 return originsOfBounds;
727 std::vector<T> VariableBounds<T>::getOriginsOfBounds() const
729 std::vector<T> originsOfBounds;
730 for( auto varVarPair = mpVariableMap->begin(); varVarPair != mpVariableMap->end(); ++varVarPair )
732 const Variable<T>& var = *varVarPair->second;
733 if( !var.infimum().isInfinite() ) originsOfBounds.push_back( *var.infimum().origins().begin() );
734 if( !var.supremum().isInfinite() ) originsOfBounds.push_back( *var.supremum().origins().begin() );
736 return originsOfBounds;
740 std::set<T> VariableBounds<T>::getOriginSetOfBounds() const
742 std::set<T> originsOfBounds;
743 for( auto varVarPair = mpVariableMap->begin(); varVarPair != mpVariableMap->end(); ++varVarPair )
745 const Variable<T>& var = *varVarPair->second;
746 if( !var.infimum().isInfinite() ) originsOfBounds.insert( *var.infimum().origins().begin() );
747 if( !var.supremum().isInfinite() ) originsOfBounds.insert( *var.supremum().origins().begin() );
749 return originsOfBounds;
753 std::set<T> VariableBounds<T>::getOriginSetOfBounds( const carl::Variable& _var ) const
755 std::set<T> originsOfBounds;
756 auto varVarPair = mpVariableMap->find( _var );
757 if( varVarPair != mpVariableMap->end() )
759 if( !varVarPair->second->infimum().isInfinite() ) originsOfBounds.insert( *varVarPair->second->infimum().origins().begin() );
760 if( !varVarPair->second->supremum().isInfinite() ) originsOfBounds.insert( *varVarPair->second->supremum().origins().begin() );
762 return originsOfBounds;
766 std::set<T> VariableBounds<T>::getOriginSetOfBounds( const carl::Variables& _variables ) const
768 std::set<T> originsOfBounds;
769 for( auto var = _variables.begin(); var != _variables.end(); ++var )
771 auto varVarPair = mpVariableMap->find( *var );
772 if( varVarPair != mpVariableMap->end() )
774 if( !varVarPair->second->infimum().isInfinite() ) originsOfBounds.insert( *varVarPair->second->infimum().origins().begin() );
775 if( !varVarPair->second->supremum().isInfinite() ) originsOfBounds.insert( *varVarPair->second->supremum().origins().begin() );
778 return originsOfBounds;
782 std::vector<std::pair<std::vector<ConstraintT>, ConstraintT>> VariableBounds<T>::getBoundDeductions() const
784 std::vector<std::pair<std::vector<ConstraintT>, ConstraintT>> result;;
785 for( auto cons = mNonBoundConstraints.begin(); cons != mNonBoundConstraints.end(); ++cons )
787 assert( cons->relation() != carl::Relation::NEQ );
788 std::vector<ConstraintT> boundConstraints;
789 carl::Variables boundedVars;
790 carl::Variables notBoundedVars;
791 for( auto carlVar: cons->variables() )
793 const Variable<T>& var = *(mpVariableMap->find( carlVar )->second);
794 if( !var.infimum().isInfinite() || !var.supremum().isInfinite() )
796 boundedVars.insert( carlVar );
797 if( !var.infimum().isInfinite() )
799 boundConstraints.push_back( (*var.infimum().origins().begin())->constraint() );
801 if( !var.supremum().isInfinite() )
803 boundConstraints.push_back( (*var.supremum().origins().begin())->constraint() );
808 notBoundedVars.insert( carlVar );
809 if( notBoundedVars.size() > 1 )
813 if( boundedVars.size() == 0 || notBoundedVars.size() > 1 || cons->maxDegree( *notBoundedVars.begin() ) > 1 )
815 EvalRationalIntervalMap bounds = getEvalIntervalMap();
816 boundConstraints.push_back( *cons );
817 if( mBoundDeductions.find( boundConstraints ) == mBoundDeductions.end() )
819 // std::cout << std::endl << (*cons) << std::endl;
820 // std::cout << "find variable" << std::endl;
821 // Check whether all variables in the constraint but one are bounded (upper, lower or both)
822 if( notBoundedVars.size() == 1 )
824 carl::Variable var = *notBoundedVars.begin();
825 // std::cout << "var = " << var << std::endl;
826 // std::cout << "with the bounds: " << std::endl;
827 // for( auto bcons = boundConstraints.begin(); bcons != boundConstraints.end(); ++bcons )
828 // std::cout << (*bcons) << std::endl;
829 Poly varCoeff = cons->coefficient( var, 1 );
830 assert( !carl::is_zero(varCoeff) );
831 RationalInterval varCoeffEvaluated = carl::evaluate( varCoeff, bounds );
832 Poly remainder = carl::substitute(cons->lhs(), var, Poly(0) );
833 RationalInterval remainderEvaluated = carl::evaluate( remainder, bounds ).inverse();
835 RationalInterval newBoundsA;
836 RationalInterval newBoundsB;
837 if( remainderEvaluated.div_ext( varCoeffEvaluated, newBoundsA, newBoundsB ) )
839 // std::cout << "case a: " << newBoundsA << " and " << newBoundsB << std::endl;
840 carl::BoundType lt = carl::BoundType::INFTY;
841 carl::BoundType rt = carl::BoundType::INFTY;
844 if( newBoundsA <= newBoundsB )
846 lt = newBoundsA.lower_bound_type();
847 rt = newBoundsB.upper_bound_type();
848 if( lt != carl::BoundType::INFTY ) lb = newBoundsA.lower();
849 if( rt != carl::BoundType::INFTY ) rb = newBoundsB.upper();
853 assert( newBoundsA >= newBoundsB );
854 lt = newBoundsB.lower_bound_type();
855 rt = newBoundsA.upper_bound_type();
856 if( lt != carl::BoundType::INFTY ) lb = newBoundsB.lower();
857 if( rt != carl::BoundType::INFTY ) rb = newBoundsA.upper();
859 if( cons->relation() == carl::Relation::EQ )
861 if( newBoundsA.lower_bound_type() != carl::BoundType::INFTY )
863 typename Poly::PolyType boundLhs = typename Poly::PolyType( var ) - newBoundsA.lower();
864 carl::Relation boundRel = newBoundsA.lower_bound_type() == carl::BoundType::STRICT ? carl::Relation::LEQ : carl::Relation::LESS;
865 ConstraintT newBoundConstraint = ConstraintT( boundLhs, boundRel );
866 result.push_back( std::pair<std::vector<ConstraintT>, ConstraintT >( boundConstraints, newBoundConstraint ) );
868 if( newBoundsB.upper_bound_type() != carl::BoundType::INFTY )
870 typename Poly::PolyType boundLhs = typename Poly::PolyType( var ) - newBoundsB.upper();
871 carl::Relation boundRel = newBoundsA.upper_bound_type() == carl::BoundType::STRICT ? carl::Relation::LEQ : carl::Relation::LESS;
872 ConstraintT newBoundConstraint = ConstraintT( boundLhs, boundRel );
873 result.push_back( std::pair<std::vector< ConstraintT >, ConstraintT >( boundConstraints, newBoundConstraint ) );
879 if( !varCoeffEvaluated.contains( Rational(0) ) || cons->relation() == carl::Relation::EQ )
881 carl::Relation rel = cons->relation();
882 if( varCoeffEvaluated.sgn() == carl::Sign::NEGATIVE )
886 case carl::Relation::LEQ:
887 rel = carl::Relation::GEQ;
889 case carl::Relation::GEQ:
890 rel = carl::Relation::LEQ;
892 case carl::Relation::LESS:
893 rel = carl::Relation::GREATER;
895 case carl::Relation::GREATER:
896 rel = carl::Relation::LESS;
902 if( newBoundsA.lower_bound_type() != carl::BoundType::INFTY )
904 if( rel == carl::Relation::EQ || rel == carl::Relation::GEQ || rel == carl::Relation::GREATER )
906 typename Poly::PolyType boundLhs = typename Poly::PolyType( var ) - newBoundsA.lower();
907 carl::Relation boundRel = carl::Relation::GEQ;
908 if( newBoundsA.lower_bound_type() == carl::BoundType::STRICT || rel == carl::Relation::GREATER )
909 boundRel = carl::Relation::GREATER;
910 ConstraintT newBoundConstraint = ConstraintT( boundLhs, boundRel );
911 result.push_back( std::pair<std::vector< ConstraintT >, ConstraintT >( boundConstraints, newBoundConstraint ) );
914 if( newBoundsA.upper_bound_type() != carl::BoundType::INFTY )
916 if( rel == carl::Relation::EQ || rel == carl::Relation::LEQ || rel == carl::Relation::LESS )
918 typename Poly::PolyType boundLhs = typename Poly::PolyType( var ) - newBoundsA.upper();
919 carl::Relation boundRel = carl::Relation::LEQ;
920 if( newBoundsA.upper_bound_type() == carl::BoundType::STRICT || rel == carl::Relation::LESS )
921 boundRel = carl::Relation::LESS;
922 ConstraintT newBoundConstraint = ConstraintT( boundLhs, boundRel );
923 result.push_back( std::pair<std::vector< ConstraintT >, ConstraintT >( boundConstraints, newBoundConstraint ) );
929 mBoundDeductions.insert( boundConstraints );
931 boundConstraints.pop_back();
938 void VariableBounds<T>::print( std::ostream& _out, const std::string _init, bool _printAllBounds ) const
940 for( auto varVarPair = mpVariableMap->begin(); varVarPair != mpVariableMap->end(); ++varVarPair )
943 std::stringstream outA;
944 outA << varVarPair->first;
945 _out << std::setw( 15 ) << outA.str();
947 if( varVarPair->second->infimum().type() == Bound<T>::STRICT_LOWER_BOUND )
951 std::stringstream outB;
952 outB << varVarPair->second->infimum();
953 _out << std::setw( 12 ) << outB.str();
955 std::stringstream outC;
956 outC << varVarPair->second->supremum();
957 _out << std::setw( 12 ) << outC.str();
958 if( varVarPair->second->supremum().type() == Bound<T>::STRICT_UPPER_BOUND )
963 if( _printAllBounds )
965 _out << _init << " Upper bounds:" << std::endl;
966 for( auto _uBound = varVarPair->second->upperbounds().begin(); _uBound != varVarPair->second->upperbounds().end(); ++_uBound )
968 _out << _init << " ";
969 (*_uBound)->print( _out, true );
971 for( auto origin = (*_uBound)->origins().begin(); origin != (*_uBound)->origins().end(); ++origin )
972 _out << " " << *origin;
973 _out << " }" << std::endl;
975 _out << _init << " Lower bounds:" << std::endl;
976 for( auto _lBound = varVarPair->second->lowerbounds().rbegin(); _lBound != varVarPair->second->lowerbounds().rend(); ++_lBound )
978 _out << _init << " ";
979 (*_lBound)->print( _out, true );
981 for( auto origin = (*_lBound)->origins().begin(); origin != (*_lBound)->origins().end(); ++origin )
982 _out << " " << *origin;
983 _out << " }" << std::endl;
989 } // namespace smtrat