21 template<
typename Polynomial>
32 std::shared_ptr<const typename Polynomial::MonomType>
mDenominator;
55 #ifdef CONTRACTION_DEBUG
56 std::cout << __func__ <<
": [Polynome]: " << p <<
" [#Terms]: " << p.nr_terms() << std::endl;
61 assert(!p.has_constant_term());
62 assert(p.is_linear() || (p.nr_terms() == 2 && (
carl::is_one(p.begin()->coeff()) ||
carl::is_one(p.rbegin()->coeff()))
63 && ((p.begin()->has(x) && !p.rbegin()->has(x))
64 || (p.rbegin()->has(x) && !p.begin()->has(x)))));
68 #ifdef CONTRACTION_DEBUG
69 std::cout << __func__ <<
": Propagating... " << std::endl;
75 #ifdef CONTRACTION_DEBUG
76 std::cout << __func__ <<
": Case 1. (linear)... " << std::endl;
78 for (
const auto& t: p) {
79 assert(t.monomial() !=
nullptr);
86 #ifdef CONTRACTION_DEBUG
87 std::cout << __func__ <<
": Setting mNumerator:" <<
mNumerator << std::endl;
98 #ifdef CONTRACTION_DEBUG
99 std::cout << __func__ <<
": Case 2. (non-linear)... " << std::endl;
102 assert(p.nr_terms() == 2);
103 typename Polynomial::TermsType::const_iterator yIter;
104 typename Polynomial::TermsType::const_iterator xIter;
105 if (p.begin()->has(x))
118 assert(xIter->monomial() !=
nullptr);
119 assert(!xIter->is_linear() || xIter->coeff() == (-1));
121 if (xIter->is_linear())
127 mRoot = xIter->monomial()->exponent_of_variable(x);
128 #ifdef CONTRACTION_DEBUG
129 std::cout << __func__ <<
": Setting mRoot:" <<
mRoot << std::endl;
133 #ifdef CONTRACTION_DEBUG
134 std::cout << __func__ <<
": Setting mDenominator:" <<
mDenominator << std::endl;
138 #ifdef CONTRACTION_DEBUG
139 std::cout << __func__ <<
": Setting mNumerator:" <<
mNumerator << std::endl;
153 CARL_LOG_DEBUG(
"carl.contraction", tmp <<
" and " << -tmp <<
" = " << rootA <<
" and " << rootB);
158 CARL_LOG_DEBUG(
"carl.contraction",
"first intersected with " << _varInterval <<
" = " << rootA);
160 _result.push_back(std::move(rootA));
165 CARL_LOG_DEBUG(
"carl.contraction",
"second intersected with " << _varInterval <<
" = " << rootB);
167 _result.push_back(std::move(rootB));
171 CARL_LOG_DEBUG(
"carl.contraction", tmp <<
" and " << -tmp <<
" = " << rootA <<
" and " << rootB);
177 _result.push_back(std::move(rootA));
185 _result.push_back( std::move(tmp) );
199 std::vector<Interval<double>> result;
200 assert( intervals.find(
mVar) != intervals.end() );
206 addRoot( numerator, varInterval, result );
207 CARL_LOG_DEBUG(
"carl.contraction",
"no denominator -> " << result);
214 bool split = numerator.
div_ext(denominator, result1, result2);
215 CARL_LOG_DEBUG(
"carl.contraction", numerator <<
" / " << denominator <<
" -> " << result1 <<
" and " << result2);
217 assert(
mRoot <= std::numeric_limits<int>::max());
224 addRoot( tmpA, varInterval, result );
225 addRoot( tmpB, varInterval, result );
229 addRoot( tmpA, varInterval, result );
234 addRoot( result1, varInterval, result );
241 template <
template<
typename>
class Operator,
typename Polynomial>
249 std::map<Variable, MultivariateHorner<Polynomial,strategy>>
mDerivatives;
259 Operator<Polynomial>(),
263 mHornerForm(constraint),
270 Contraction(
const Polynomial& constraint,
const Polynomial& _original ):
271 Operator<Polynomial>(),
275 mHornerForm(
mpOriginal == nullptr ? constraint : _original ),
284 Operator<Polynomial>(),
288 mHornerForm(std::move(_contraction.mHornerForm)),
294 _contraction.mpOriginal =
nullptr;
313 bool splitOccurredInContraction =
false;
317 typename std::map<Variable, MultivariateHorner<Polynomial,strategy>>::const_iterator it =
mDerivatives.find(variable);
319 typename std::map<Variable, Polynomial>::const_iterator it =
mDerivatives.find(variable);
338 #ifdef CONTRACTION_DEBUG
339 std::cout << __func__ <<
": contraction of " << variable <<
" with " << intervals <<
" in " <<
mConstraint <<
" mpOriginal: " <<
mpOriginal << std::endl;
343 splitOccurredInContraction = Operator<Polynomial>::contract(intervals, variable, mHornerForm, (*it).second, resA, resB, useNiceCenter);
345 splitOccurredInContraction = Operator<Polynomial>::contract(intervals, variable, (
mpOriginal ==
nullptr ?
mConstraint : *
mpOriginal), (*it).second, resA, resB, useNiceCenter);
351 resA = intervals.at(variable);
355 CARL_LOG_DEBUG(
"carl.contraction",
" after propagation: " << resA <<
" / " << resB);
356 CARL_LOG_DEBUG(
"carl.contraction",
" Split? " << splitOccurredInContraction);
360 typename std::map<Variable, VarSolutionFormula<Polynomial>>::const_iterator const_iterator_VarSolutionFormula =
mVarSolutionFormulas.find(variable);
367 std::vector<Interval<double>> resultPropagation = const_iterator_VarSolutionFormula->second.evaluate( intervals );
369 #ifdef CONTRACTION_DEBUG
370 std::cout <<
" propagation result: " << resultPropagation << std::endl;
373 if( resultPropagation.empty() )
377 CARL_LOG_DEBUG(
"carl.contraction",
" after propagation: " << resA <<
" / " << resB);
382 std::vector<Interval<double>> resultingIntervals;
383 if( splitOccurredInContraction )
386 for(
const auto& i : resultPropagation )
389 CARL_LOG_DEBUG(
"carl.contraction",
" intersection(" << i <<
", " << resA <<
") = " << tmp);
391 resultingIntervals.push_back(tmp);
393 CARL_LOG_DEBUG(
"carl.contraction",
" intersection(" << i <<
", " << resB <<
") = " << tmp);
395 resultingIntervals.push_back(tmp);
402 for(
const auto& i : resultPropagation )
405 CARL_LOG_DEBUG(
"carl.contraction",
" intersection(" << i <<
", " << resA <<
") = " << tmp);
407 resultingIntervals.push_back(tmp);
410 if( resultingIntervals.empty() )
414 CARL_LOG_DEBUG(
"carl.contraction",
" after propagation: " << resA <<
" / " << resB);
417 if( resultingIntervals.size() == 1 )
419 resA = resultingIntervals[0];
421 CARL_LOG_DEBUG(
"carl.contraction",
" after propagation: " << resA <<
" / " << resB);
424 if( resultingIntervals.size() == 2 )
426 if( resultingIntervals[0] < resultingIntervals[1] )
428 resA = resultingIntervals[0];
429 resB = resultingIntervals[1];
433 assert(resultingIntervals[1] < resultingIntervals[0]);
434 resA = resultingIntervals[1];
435 resB = resultingIntervals[0];
437 CARL_LOG_DEBUG(
"carl.contraction",
" after propagation: " << resA <<
" / " << resB);
442 std::sort( resultPropagation.begin(), resultPropagation.end(),
444 { if(i<j){return true;}
else { assert(j<i); return false; } }
446 auto intervalBeforeBiggestGap = resultPropagation.begin();
447 auto iter = resultPropagation.begin();
449 double bestDistance = intervalBeforeBiggestGap->distance(*iter);
450 for( ; iter != resultPropagation.end(); ++iter )
454 if( jter == resultPropagation.end() )
460 double distance = iter->distance(*jter);
461 if( bestDistance < distance )
463 bestDistance = distance;
464 intervalBeforeBiggestGap = iter;
468 resA = *intervalBeforeBiggestGap;
469 for( iter = resultPropagation.begin(); iter != intervalBeforeBiggestGap; ++iter )
475 for( ; iter != resultPropagation.end(); ++iter )
479 #ifdef CONTRACTION_DEBUG
480 std::cout <<
" after propagation: " << resA;
if( !resB.
is_empty() ) { std::cout <<
" and " << resB; } std::cout << std::endl;
485 return splitOccurredInContraction;
489 template<
typename Polynomial>
493 template <
typename evalType>
496 const evalType& constraint,
500 bool useNiceCenter =
false)
502 bool splitOccurred =
false;
505 if(
center == std::numeric_limits<double>::infinity() ||
center == -std::numeric_limits<double>::infinity() )
507 resA = intervals.at(variable);
512 #ifdef CONTRACTION_DEBUG
513 std::cout <<
"variable = " << variable << std::endl;
514 std::cout <<
"constraint = " << constraint << std::endl;
515 std::cout <<
"derivative = " <<
derivative << std::endl;
516 std::cout << __func__ <<
": centerInterval: " << centerInterval << std::endl;
521 substitutedIntervalMap[variable] = centerInterval;
535 #ifdef CONTRACTION_DEBUG
536 std::cout << __func__ <<
": numerator: " << numerator <<
", denominator: " << denominator << std::endl;
539 bool split = numerator.
div_ext(denominator, result1, result2);
541 #ifdef CONTRACTION_DEBUG
542 std::cout << __func__ <<
": caused split: " << result1 <<
" and " << result2 << std::endl;
544 splitOccurred =
true;
545 if(result1 >= result2) {
554 if (variable.
type() == VariableType::VT_INT) {
558 #ifdef CONTRACTION_DEBUG
559 std::cout << __func__ <<
": result after intersection: " << resA <<
" and " << resB << std::endl;
563 splitOccurred =
false;
569 splitOccurred =
false;
575 resA = std::move(tmpA);
577 splitOccurred =
false;
581 #ifdef CONTRACTION_DEBUG
582 std::cout << __func__ <<
": result: " << result1 << std::endl;
583 std::cout << __func__ <<
": center: " << centerInterval << std::endl;
584 std::cout << __func__ <<
": center sub: " << centerInterval.
sub(result1) << std::endl;
585 std::cout << __func__ <<
": intersecting " << intervals.at(variable) <<
" and " << centerInterval.
sub(result1) << std::endl;
588 if (variable.
type() == VariableType::VT_INT) {
591 #ifdef CONTRACTION_DEBUG
592 std::cout << __func__ <<
": result after intersection: " << resA << std::endl;
595 return splitOccurred;
#define CARL_LOG_DEBUG(channel, msg)
carl is the main namespace for the library.
const T & derivative(const T &t, Variable, std::size_t n=1)
Computes the n'th derivative of a number, which is either the number itself (for n = 0) or zero.
Number sample(const Interval< Number > &i, bool includingBounds=true)
Searches for some point in this interval, preferably near the midpoint and with a small representatio...
Number center(const Interval< Number > &i)
Returns the center point of the interval.
bool evaluate(const BasicConstraint< Poly > &c, const Assignment< Number > &m)
bool set_union(const Interval< Number > &lhs, const Interval< Number > &rhs, Interval< Number > &resA, Interval< Number > &resB)
Computes the union of two intervals (can result in two distinct intervals).
Interval< Number > set_intersection(const Interval< Number > &lhs, const Interval< Number > &rhs)
Intersects two intervals in a set-theoretic manner.
bool is_linear(const ContextPolynomial< Coeff, Ordering, Policies > &p)
bool is_one(const Interval< Number > &i)
Check if this interval is a point-interval containing 1.
A Variable represents an algebraic variable that can be used throughout carl.
constexpr VariableType type() const noexcept
Retrieves the type of the variable.
bool div_ext(const Interval< Number > &rhs, Interval< Number > &a, Interval< Number > &b) const
Implements extended interval division with intervals containting zero.
bool is_empty() const
Function which determines, if the interval is empty.
Interval< Number > root(int deg) const
Calculates the nth root of the interval with respect to natural interval arithmetic.
static Interval< Number > empty_interval()
Method which returns the empty interval rooted at 0.
Interval< Number > convex_hull(const Interval< Number > &interval) const
Interval< Number > sub(const Interval< Number > &rhs) const
Subtracts two intervals according to natural interval arithmetic.
Interval< Number > integral_part() const
Computes the integral part of the given interval.
VarSolutionFormula()=delete
void addRoot(const Interval< double > &_interv, const Interval< double > &_varInterval, std::vector< Interval< double >> &_result) const
VarSolutionFormula(const Polynomial &p, Variable::Arg x)
Constructs the solution formula for the given variable x in the equation p = 0, where p is the given ...
std::shared_ptr< const typename Polynomial::MonomType > mDenominator
Stores the denominator, which is one, if mDenominator == nullptr.
Variable mVar
The variable, for which to solve.
Polynomial mNumerator
Stores the numerator.
uint mRoot
Stores n, if the nth root has to be taken of mNumerator/mDenominator.
std::vector< Interval< double > > evaluate(const Interval< double >::evalintervalmap &intervals) const
Evaluates this solution formula for the given mapping of the variables occurring in the solution form...
std::map< Variable, VarSolutionFormula< Polynomial > > mVarSolutionFormulas
Contraction(const Contraction &)=delete
Contraction(const Polynomial &constraint)
Contraction & operator=(Contraction &&)=delete
Contraction(Contraction &&_contraction)
const Polynomial & polynomial() const
std::map< Variable, Polynomial > mDerivatives
bool operator()(const Interval< double >::evalintervalmap &intervals, Variable::Arg variable, Interval< double > &resA, Interval< double > &resB, bool useNiceCenter=false, bool usePropagation=false)
Contraction & operator=(const Contraction &)=delete
Contraction(const Polynomial &constraint, const Polynomial &_original)
std::map< Polynomial, MultivariateHorner< Polynomial, strategy > > mHornerSchemes
bool contract(const Interval< double >::evalintervalmap &intervals, Variable::Arg variable, const evalType &constraint, const evalType &derivative, Interval< double > &resA, Interval< double > &resB, bool useNiceCenter=false)