carl  24.04
Computer ARithmetic Library
ran_interval_extra.h
Go to the documentation of this file.
1 #pragma once
2 
3 
4 #include <map>
5 #include <vector>
6 
7 #include "Ran.h"
8 #include "RealRoots.h"
10 
12 
13 namespace carl::ran::interval {
14 
15 
16 template<typename Number>
18 private:
22  std::map<Variable, const IntRepRealAlgebraicNumber<Number>&> m_ir_assignments;
23 
24 public:
27  m_original_poly(p),
29  {}
30 
31  bool assign(const std::map<Variable, IntRepRealAlgebraicNumber<Number>>& m, bool refine_model = true) {
32  bool evaluated = false;
33 
34  for (const auto& [var, ran] : m) {
35  if (refine_model) {
36  static Number min_width = Number(1)/(Number(1048576)); // 1/2^20, taken from libpoly
37  while (!ran.is_numeric() && ran.interval().diameter() > min_width) {
38  ran.refine();
39  }
40  }
41 
42  if (ran.is_numeric()) {
43  evaluated |= assign(var, ran, false);
44  if (evaluated) return true;
45  }
46  }
47 
48  for (const auto& [var, ran] : m) {
49  if (!ran.is_numeric()) {
50  evaluated |= assign(var, ran, false);
51  if (evaluated) return true;
52  }
53  }
54 
55  return false;
56  }
57 
58  bool assign(Variable var, const IntRepRealAlgebraicNumber<Number>& ran, bool refine_model = true) {
59  assert(m_ir_assignments.find(var) == m_ir_assignments.end());
60  if (m_original_poly.is_constant()) return true;
61  if (!m_poly.has(var)) return false;
62 
63  CARL_LOG_TRACE("carl.ran.interval", "Assign " << var << " -> " << ran);
64 
65  if (refine_model) {
66  static Number min_width = Number(1)/(Number(1048576)); // 1/2^20, taken from libpoly
67  while (!ran.is_numeric() && ran.interval().diameter() > min_width) {
68  ran.refine();
69  }
70  }
71 
72  if (ran.is_numeric()) {
73  CARL_LOG_TRACE("carl.ran.interval", "Numeric: " << ran);
76  CARL_LOG_TRACE("carl.ran.interval", "Remainung poly: " << m_poly << "; original: " << m_original_poly);
77  assert(carl::variables(m_poly).size() > 1 || carl::variables(m_poly) == carlVariables({ m_var }));
78  return carl::variables(m_poly).size() == 1 || m_original_poly.is_constant();
79  } else {
80  CARL_LOG_TRACE("carl.ran.interval", "Still an interval: " << ran);
81  m_ir_assignments.emplace(var, ran);
82  const auto poly = replace_main_variable(ran.polynomial(), var).template convert<MultivariatePolynomial<Number>>();
84  m_poly = carl::resultant(m_poly, poly);
86  CARL_LOG_TRACE("carl.ran.interval", "Remainung poly: " << m_poly << "; original: " << m_original_poly);
87  assert(carl::variables(m_poly).size() > 1 || carl::variables(m_poly) == carlVariables({ m_var }));
88  return carl::variables(m_poly).size() == 1 || m_original_poly.is_constant();
89  }
90  }
91 
92  bool has_value() const {
93  return carl::variables(m_poly).size() == 1 || m_original_poly.is_constant();
94  }
95 
96  auto value() {
98  CARL_LOG_TRACE("carl.ran.interval", "Poly is constant: " << m_original_poly);
100  }
101 
102  assert(carl::variables(m_poly).size() == 1 && m_poly.has(m_var));
103 
104  UnivariatePolynomial<Number> res = carl::squareFreePart(m_poly.toNumberCoefficients());
105 
106  CARL_LOG_TRACE("carl.ran.interval", "Computing value of " << m_original_poly << " at " << m_ir_assignments << " using " << res);
107 
108  std::map<Variable, Interval<Number>> var_to_interval;
109  for (const auto& [var, ran] : m_ir_assignments) {
110  if (!m_original_poly.has(var)) continue;
111  var_to_interval.emplace(var, ran.interval());
112  }
113  CARL_LOG_TRACE("carl.ran.interval", "Got intervals " << var_to_interval);
114  assert(!var_to_interval.empty());
115  Interval<Number> interval = carl::evaluate(m_original_poly, var_to_interval);
116 
117  if (interval.is_point_interval()) {
118  return IntRepRealAlgebraicNumber<Number>(interval.lower());
119  }
120 
121  auto sturm_seq = sturm_sequence(res);
122  // the interval should include at least one root.
123  assert(!carl::is_zero(res));
124  assert(carl::is_root_of(res, interval.lower()) || carl::is_root_of(res, interval.upper()) || count_real_roots(sturm_seq, interval) >= 1);
125  while (!interval.is_point_interval() && (carl::is_root_of(res, interval.lower()) || carl::is_root_of(res, interval.upper()) || count_real_roots(sturm_seq, interval) != 1)) {
126  // refine the result interval until it isolates exactly one real root of the result polynomial
127  for (const auto& [var, ran] : m_ir_assignments) {
128  if (var_to_interval.find(var) == var_to_interval.end()) continue;
129  ran.refine();
130  if (ran.is_numeric()) {
132  for (const auto& entry : m_ir_assignments) {
133  if (!m_original_poly.has(entry.first)) var_to_interval.erase(entry.first);
134  }
135  } else {
136  var_to_interval[var] = ran.interval();
137  }
138  }
139  interval = carl::evaluate(m_original_poly, var_to_interval);
140  }
141  if (interval.is_point_interval()) {
142  return IntRepRealAlgebraicNumber<Number>(interval.lower());
143  } else {
144  return IntRepRealAlgebraicNumber<Number>(res, interval);
145  }
146  }
147 };
148 
149 }
#define CARL_LOG_TRACE(channel, msg)
Definition: carl-logging.h:44
MultivariatePolynomial< C, O, P > squareFreePart(const MultivariatePolynomial< C, O, P > &polynomial)
std::vector< UnivariatePolynomial< Coeff > > sturm_sequence(const UnivariatePolynomial< Coeff > &p, const UnivariatePolynomial< Coeff > &q)
Computes the sturm sequence of two polynomials.
Definition: SturmSequence.h:16
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 ...
Definition: RootCounting.h:19
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
bool evaluate(const BasicConstraint< Poly > &c, const Assignment< Number > &m)
Definition: Evaluation.h:10
bool is_root_of(const UnivariatePolynomial< Coeff > &p, const Coeff &value)
Definition: Evaluation.h:62
UnivariatePolynomial< Coeff > replace_main_variable(const UnivariatePolynomial< Coeff > &p, Variable newVar)
Replaces the main variable in a polynomial.
Variable fresh_real_variable() noexcept
Definition: VariablePool.h:198
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
UnivariatePolynomial< Coeff > pseudo_remainder(const UnivariatePolynomial< Coeff > &dividend, const UnivariatePolynomial< Coeff > &divisor)
Calculates the pseudo-remainder.
Definition: Remainder.h:105
auto resultant(const ContextPolynomial< Coeff, Ordering, Policies > &p, const ContextPolynomial< Coeff, Ordering, Policies > &q)
Definition: Functions.h:22
UnivariatePolynomial< MultivariatePolynomial< typename UnderlyingNumberType< Coeff >::type > > switch_main_variable(const UnivariatePolynomial< Coeff > &p, Variable newVar)
Switches the main variable using a purely syntactical restructuring.
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.
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
The class which contains the interval arithmetic including trigonometric functions.
Definition: Interval.h:134
const Number & upper() const
The getter for the upper boundary of the interval.
Definition: Interval.h:849
const Number & lower() const
The getter for the lower boundary of the interval.
Definition: Interval.h:840
bool is_point_interval() const
Function which determines, if the interval is a pointinterval.
Definition: Interval.h:1071
This class represents a univariate polynomial with coefficients of an arbitrary type.
bool is_constant() const
Check if the polynomial is constant.
const Coeff & constant_part() const
Retrieve the constant term of this polynomial or zero, if there is no constant term.
const auto & value() const
Definition: Ran.h:227
const auto & interval() const
Definition: Ran.h:222
const auto & polynomial() const
Definition: Ran.h:218
bool is_numeric() const
Definition: Ran.h:214
std::map< Variable, const IntRepRealAlgebraicNumber< Number > & > m_ir_assignments
bool assign(const std::map< Variable, IntRepRealAlgebraicNumber< Number >> &m, bool refine_model=true)
MultivariatePolynomial< Number > m_original_poly
bool assign(Variable var, const IntRepRealAlgebraicNumber< Number > &ran, bool refine_model=true)
ran_evaluator(const MultivariatePolynomial< Number > &p)
UnivariatePolynomial< MultivariatePolynomial< Number > > m_poly