12 #include <boost/logic/tribool_io.hpp>
29 template<
typename Number>
31 CARL_LOG_DEBUG(
"carl.ran.interval",
"Evaluating " << p <<
" on " << m);
34 for (
const auto& [var, ran] : m) {
35 if (!p.
has(var))
continue;
37 CARL_LOG_TRACE(
"carl.ran.interval",
"Refine " << var <<
" = " << ran);
38 static Number min_width = Number(1) / (Number(1048576));
39 while (!ran.is_numeric() && ran.interval().diameter() > min_width) {
43 if (ran.is_numeric()) {
44 CARL_LOG_TRACE(
"carl.ran.interval",
"Substitute " << var <<
" = " << ran);
56 std::map<Variable, Interval<Number>> var_to_interval;
57 for (
const auto& [var, ran] : m) {
59 assert(!ran.is_numeric());
60 var_to_interval.emplace(var, ran.interval());
63 CARL_LOG_TRACE(
"carl.ran.interval",
"Interval map: " << var_to_interval);
65 assert(!var_to_interval.empty());
66 if (var_to_interval.size() == 1) {
69 assert(poly.main_var() == var_to_interval.begin()->first);
70 CARL_LOG_TRACE(
"carl.ran.interval",
"Consider univariate poly " << poly);
71 if (
sgn(m.at(var_to_interval.begin()->first), poly) ==
Sign::ZERO) {
81 CARL_LOG_DEBUG(
"carl.ran.interval",
"Interval is point interval " << interval);
87 std::vector<UnivariatePolynomial<MultivariatePolynomial<Number>>> algebraic_information;
88 for (
const auto& [var, ran] : m) {
89 if (var_to_interval.find(var) == var_to_interval.end())
continue;
90 assert(!ran.is_numeric());
94 std::sort(algebraic_information.begin(), algebraic_information.end(), [](
const auto& a,
const auto& b){
95 return a.degree() > b.degree();
105 CARL_LOG_TRACE(
"carl.ran.interval",
"var_to_interval = " << var_to_interval);
118 for (
const auto& [var, ran] : m) {
119 if (var_to_interval.find(var) == var_to_interval.end())
continue;
121 if (ran.is_numeric()) {
123 for (
const auto& entry : m) {
124 if (!p.
has(entry.first)) var_to_interval.erase(entry.first);
127 var_to_interval[var] = ran.interval();
133 CARL_LOG_DEBUG(
"carl.ran.interval",
"Result is " << *res <<
" " << interval);
141 template<
typename Number>
143 CARL_LOG_DEBUG(
"carl.ran.interval",
"Evaluating " << c <<
" on " << m);
145 if (!use_root_bounds) {
146 CARL_LOG_DEBUG(
"carl.ran.interval",
"Evaluate constraint by evaluating poly");
148 if (!res)
return boost::indeterminate;
155 for (
const auto& [var, ran] : m) {
156 if (!p.
has(var))
continue;
158 static Number min_width = Number(1) / (Number(1048576));
159 while (!ran.is_numeric() && ran.interval().diameter() > min_width) {
163 if (ran.is_numeric()) {
165 CARL_LOG_TRACE(
"carl.ran.interval",
"Substituting numeric value p["<<ran.value()<<
"/"<<var<<
"] = " << p);
170 CARL_LOG_DEBUG(
"carl.ran.interval",
"Left hand side is constant");
175 CARL_LOG_DEBUG(
"carl.ran.interval",
"Constraint already evaluates to value");
179 CARL_LOG_TRACE(
"carl.ran.interval",
"p = " << p <<
" (after simplification)");
181 std::map<Variable, Interval<Number>> var_to_interval;
182 for (
const auto& [var, ran] : m) {
184 assert(!ran.is_numeric());
185 var_to_interval.emplace(var, ran.interval());
191 CARL_LOG_TRACE(
"carl.ran.interval",
"Interval evaluation of " << p <<
" under " << var_to_interval <<
" results in " << interval);
193 CARL_LOG_TRACE(
"carl.ran.interval",
"Obtained " << interval <<
" " << constr.
relation() <<
" 0 -> " << (indeterminate(int_res) ? -1 : (
bool)int_res));
194 if (!indeterminate(int_res)) {
195 CARL_LOG_DEBUG(
"carl.ran.interval",
"Result obtained by interval evaluation");
196 return (
bool)int_res;
200 CARL_LOG_DEBUG(
"carl.ran.interval",
"Evaluate constraint using resultants and root bounds");
201 assert(var_to_interval.size() > 0);
202 if (var_to_interval.size() == 1) {
205 assert(poly.main_var() == var_to_interval.begin()->first);
206 CARL_LOG_TRACE(
"carl.ran.interval",
"Consider univariate poly " << poly);
207 if (
sgn(m.at(var_to_interval.begin()->first), poly) ==
Sign::ZERO) {
215 std::vector<UnivariatePolynomial<MultivariatePolynomial<Number>>> algebraic_information;
216 for (
const auto& [var, ran] : m) {
217 if (var_to_interval.find(var) == var_to_interval.end())
continue;
218 assert(!ran.is_numeric());
222 std::sort(algebraic_information.begin(), algebraic_information.end(), [](
const auto& a,
const auto& b){
223 return a.degree() > b.degree();
228 return boost::indeterminate;
232 CARL_LOG_DEBUG(
"carl.ran.interval",
"var_to_interval = " << var_to_interval);
241 CARL_LOG_TRACE(
"carl.ran.interval",
"positive root lower bound: " << pos_lb);
252 CARL_LOG_TRACE(
"carl.ran.interval",
"negative root upper bound: " << neg_ub);
263 if (pos_lb == 0 && neg_ub == 0) {
272 CARL_LOG_DEBUG(
"carl.ran.interval",
"Refine until interval is in (" << neg_ub <<
"," << pos_lb <<
") or interval is positive or negative");
273 while (!((neg_ub < interval.
lower() || neg_ub == 0) && (interval.
upper() < pos_lb || pos_lb == 0))) {
274 for (
const auto& [var, ran] : m) {
275 if (var_to_interval.find(var) == var_to_interval.end())
continue;
277 if (ran.is_numeric()) {
279 for (
const auto& entry : m) {
280 if (!p.
has(entry.first)) var_to_interval.erase(entry.first);
283 var_to_interval[var] = ran.interval();
288 if (!indeterminate(int_res)) {
290 return (
bool)int_res;
300 template<
typename Coeff,
typename Ordering,
typename Policies>
305 template<
typename Coeff,
typename Ordering,
typename Policies>
This file contains carl::algebraic_substitution which performs what we call an algebraic substitution...
#define CARL_LOG_TRACE(channel, msg)
#define CARL_LOG_DEBUG(channel, msg)
carl is the main namespace for the library.
MultivariatePolynomial< C, O, P > squareFreePart(const MultivariatePolynomial< C, O, P > &polynomial)
UnivariatePolynomial< C > to_univariate_polynomial(const MultivariatePolynomial< C, O, P > &p)
Convert a univariate polynomial that is currently (mis)represented by a 'MultivariatePolynomial' into...
std::vector< UnivariatePolynomial< Coeff > > sturm_sequence(const UnivariatePolynomial< Coeff > &p, const UnivariatePolynomial< Coeff > &q)
Computes the sturm sequence of two polynomials.
int count_real_roots(const std::vector< UnivariatePolynomial< Coefficient >> &seq, const Interval< Coefficient > &i)
Calculate the number of real roots of a polynomial within a given interval based on a sturm sequence ...
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
bool evaluate(const BasicConstraint< Poly > &c, const Assignment< Number > &m)
bool is_root_of(const UnivariatePolynomial< Coeff > &p, const Coeff &value)
UnivariatePolynomial< Coeff > replace_main_variable(const UnivariatePolynomial< Coeff > &p, Variable newVar)
Replaces the main variable in a polynomial.
Sign sgn(const Number &n)
Obtain the sign of the given number.
BasicConstraint< ToPoly > convert(const typename ToPoly::ContextType &context, const BasicConstraint< FromPoly > &c)
Variable fresh_real_variable() noexcept
Coeff lagrangePositiveLowerBound(const UnivariatePolynomial< Coeff > &p)
Computes a lower bound on the value of the positive real roots of the given univariate polynomial.
std::map< Variable, T > Assignment
Coeff lagrangeNegativeUpperBound(const UnivariatePolynomial< Coeff > &p)
Computes an upper bound on the value of the negative real roots of the given univariate polynomial.
void substitute_inplace(MultivariateRoot< Poly > &mr, Variable var, const Poly &poly)
Create a copy of the underlying polynomial with the given variable replaced by the given polynomial.
BasicConstraint< Pol > create_normalized_constraint(const Pol &lhs, Relation rel)
std::optional< UnivariatePolynomial< Number > > algebraic_substitution(const UnivariatePolynomial< MultivariatePolynomial< Number >> &p, const std::vector< UnivariatePolynomial< MultivariatePolynomial< Number >>> &polynomials, AlgebraicSubstitutionStrategy strategy=AlgebraicSubstitutionStrategy::RESULTANT)
Computes the algebraic substitution of the given defining polynomials into a multivariate polynomial ...
Represent a polynomial (in)equality against zero.
unsigned is_consistent() const
Relation relation() const
A Variable represents an algebraic variable that can be used throughout carl.
The class which contains the interval arithmetic including trigonometric functions.
const Number & upper() const
The getter for the upper boundary of the interval.
const Number & lower() const
The getter for the lower boundary of the interval.
bool is_point_interval() const
Function which determines, if the interval is a pointinterval.
This class represents a univariate polynomial with coefficients of an arbitrary type.
const Coeff & constant_part() const
Retrieve the constant term of this polynomial or zero, if there is no constant term.
bool is_number() const
Check if the polynomial is a number, i.e., a constant.
bool has(Variable v) const
const UnivariatePolynomial< MultivariatePolynomial< Coeff, Ordering, Policies > > & content() const
typename UnivariatePolynomial< NumberType >::RootType RootType