4 #include <carl-arith/poly/Conversion.h>
43 inline IR CellApproximator::apx_bound<ApxPoly::SIMPLE>(
const IR& ,
const RAN& bound,
bool below) {
44 Rational root = approximate_root<ApxSettings::root>(main_sample(),bound,below);
45 return IR(proj().polys()(carl::get_denom(root)*
Polynomial(proj().polys().context(),
var()) - carl::get_num(root)), 1);
49 inline IR CellApproximator::apx_bound<ApxPoly::LINEAR_GRADIENT>(
const IR& p,
const RAN& bound,
bool below) {
50 Poly carl_poly = carl::convert<Poly,Polynomial>(proj().polys()(p.
poly));
51 Poly derivative = carl::derivative(carl_poly,
var());
53 if (carl::is_zero(gradient))
return apx_bound<ApxPoly::SIMPLE>(p, bound, below);
54 Poly carl_res = gradient*
Poly(
var()) - gradient*approximate_root<ApxSettings::root>(main_sample(),bound,below);
55 Polynomial res = carl::convert<Polynomial, Poly>(proj().polys().context(), carl_res);
56 return IR(proj().polys()(res), 1);
60 inline IR CellApproximator::apx_bound<ApxPoly::TAYLOR>(
const IR& p,
const RAN& bound,
bool below) {
64 Poly carl_poly = carl::convert<Poly,Polynomial>(proj().polys()(p.
poly));
66 std::size_t dim = sample().size();
68 auto sample_root = sample();
69 sample_root[
var()] = bound;
70 auto sample_new_root = sample();
71 sample_new_root[
var()] =
RAN(approximate_root<ApxSettings::root>(main_sample(), bound, below));
72 #ifdef SMTRAT_DEVOPTION_Statistics
73 std::size_t leftOutVars = 0;
74 for (
const auto& [
var, val] : sample_new_root) {
75 if (!val.is_numeric()) ++leftOutVars;
77 OCApproximationStatistics::get_instance().taylorIgnoredVars(leftOutVars, dim);
79 auto apx_sample = sample_root;
82 auto one_step_differentiate = [&] (
const Poly& poly,
Poly&
result, std::vector<Poly>& jacobian) {
84 for (std::size_t i = 0; i < dim; i++) {
86 if (!sample_new_root[var_order[i]].is_numeric())
continue;
87 jacobian[i] = carl::derivative(poly, var_order[i]);
89 if (evaluated_deriv.get_den() != 1) {
93 Rational c = carl::ceil(evaluated_deriv);
94 Rational f = carl::floor(evaluated_deriv);
98 if (c < ub) evaluated_deriv = c;
99 else if (lb < f) evaluated_deriv = f;
100 else evaluated_deriv = carl::sample_stern_brocot(
RationalInterval(lb,ub),
false);
105 if (carl::is_zero(evaluated_deriv))
return 0;
106 else if (evaluated_deriv > 0)
return 1;
109 std::vector<Poly> jacobian(dim);
112 int jacobian_sign = one_step_differentiate(carl_poly,
result, jacobian);
113 if ((
apx_settings().taylor_deg < 2) && (jacobian_sign == 0)) {
117 #ifdef SMTRAT_DEVOPTION_Statistics
118 OCApproximationStatistics::get_instance().taylorFailure();
120 return apx_bound<ApxPoly::SIMPLE>(p, bound, below);
124 int hessian_sign = 0;
125 for (std::size_t i = 0; i < dim; i++) {
126 if (!sample_new_root[var_order[i]].is_numeric())
continue;
127 std::vector<Poly> hessian_row(dim);
129 hessian_sign = one_step_differentiate(jacobian[i], res_i, hessian_row);
132 if (hessian_sign == 0 && jacobian_sign == 0) {
133 #ifdef SMTRAT_DEVOPTION_Statistics
134 OCApproximationStatistics::get_instance().taylorFailure();
136 return apx_bound<ApxPoly::SIMPLE>(p, bound, below);
137 }
else if (hessian_sign*jacobian_sign == 1) {
138 Polynomial result_lp = carl::convert<Polynomial,Poly>(proj().polys().context(),
result);
139 return IR(proj().polys()(result_lp), 2);
142 Polynomial result_lp = carl::convert<Polynomial,Poly>(proj().polys().context(),
result);
143 return IR(proj().polys()(result_lp), 1);
147 inline IR CellApproximator::apx_bound<ApxPoly::TAYLOR_LIN>(
const IR& p,
const RAN& bound,
bool below) {
151 Poly carl_poly = carl::convert<Poly,Polynomial>(proj().polys()(p.
poly));
153 std::size_t dim = sample().size();
155 auto sample_root = sample();
156 sample_root[
var()] = bound;
157 auto sample_new_root = sample();
158 sample_new_root[
var()] =
RAN(approximate_root<ApxSettings::root>(main_sample(), bound, below));
159 #ifdef SMTRAT_DEVOPTION_Statistics
160 std::size_t leftOutVars = 0;
161 for (
const auto& [
var, val] : sample_new_root) {
162 if (!val.is_numeric()) ++leftOutVars;
164 OCApproximationStatistics::get_instance().taylorIgnoredVars(leftOutVars, dim);
166 auto apx_sample = sample_root;
167 for (
const auto& [key, value] : sample_root) apx_sample[key] =
approximate_RAN_sb(value);
169 auto one_step_differentiate = [&] (
const Poly& poly,
Poly&
result, std::vector<Poly>& jacobian, std::size_t d) {
171 for (std::size_t i = 0; i < d; i++) {
173 if (!sample_new_root[var_order[i]].is_numeric())
continue;
174 jacobian[i] = carl::derivative(poly, var_order[i]);
176 if (evaluated_deriv.get_den() != 1) {
180 Rational c = carl::ceil(evaluated_deriv);
181 Rational f = carl::floor(evaluated_deriv);
185 if (c < ub) evaluated_deriv = c;
186 else if (lb < f) evaluated_deriv = f;
187 else evaluated_deriv = carl::sample_stern_brocot(
RationalInterval(lb,ub),
false);
192 if (carl::is_zero(evaluated_deriv))
return 0;
193 else if (evaluated_deriv > 0)
return 1;
196 std::vector<Poly> jacobian(dim);
199 int jacobian_sign = one_step_differentiate(carl_poly,
result, jacobian, dim);
200 if (jacobian_sign == 0) {
201 #ifdef SMTRAT_DEVOPTION_Statistics
202 OCApproximationStatistics::get_instance().taylorFailure();
204 return apx_bound<ApxPoly::SIMPLE>(p, bound, below);
208 for (std::size_t i = 0; i < dim-1; i++) {
209 if (!sample_new_root[var_order[i]].is_numeric())
continue;
210 std::vector<Poly> hessian_row(dim-1);
212 one_step_differentiate(jacobian[i], res_i, hessian_row, dim-1);
216 Polynomial result_lp = carl::convert<Polynomial,Poly>(proj().polys().context(),
result);
217 return IR(proj().polys()(result_lp), 1);
221 inline IR CellApproximator::apx_bound<ApxPoly::MAXIMIZE>(
const IR& p,
const RAN& bound,
bool below) {
226 if (sample().size() < 2) {
227 return IR(proj().polys()(carl::get_denom(outer) *
Polynomial(proj().polys().context(),
var()) - carl::get_num(outer)), 1);
230 Rational extra_root = approximate_root<ApxRoot::FIXED_RATIO>(inner, outer, below);
232 RAN lower_var_value = sample()[proj().polys().var_order()[sample().size() - 2]];
234 bool left_unbounded =
false, right_unbounded =
false;
235 RAN lb = main_sample(), ub = main_sample();
240 Polynomial artificial_bound = carl::get_denom(extra_root) *
Polynomial(proj().polys().context(),
var()) - carl::get_num(extra_root);
242 carl::RealRootsResult<RAN> roots_result = carl::real_roots(res, sample());
243 assert(!roots_result.is_nullified());
244 std::vector<RAN> roots = roots_result.roots();
246 if (roots.empty())
break;
249 auto it = roots.begin();
250 while (it != roots.end() && lower_var_value > *it) it++;
252 if (it == roots.begin()) {
253 if (right_unbounded) {
254 extra_root = approximate_root<ApxRoot::SIMPLE_REPRESENTATION>(extra_root, outer, below);
257 if (left_unbounded && ub > *it)
break;
261 if (!left_unbounded) {
262 left_unbounded =
true;
265 }
else if (it == roots.end()) {
267 if (left_unbounded) {
268 extra_root = approximate_root<ApxRoot::SIMPLE_REPRESENTATION>(extra_root, outer, below);
271 if (right_unbounded && lb < *it)
break;
275 if (!right_unbounded) {
276 right_unbounded =
true;
280 if (left_unbounded || right_unbounded)
break;
284 if ((l > lb) && (u < ub))
break;
289 new_area = (extra_root - inner)*(apx_u - apx_l);
290 if (below) new_area = -new_area;
292 if (new_area <= area)
break;
298 extra_root = approximate_root<ApxRoot::FIXED_RATIO>(inner, outer, below);
300 return IR(proj().polys()(carl::get_denom(outer) *
Polynomial(proj().polys().context(),
var()) - carl::get_num(outer)), 1);
304 inline IR CellApproximator::apx_between<ApxPoly::SIMPLE>(
const IR& ,
const IR& ,
const RAN& l,
const RAN& u) {
305 Rational root = approximate_root<ApxSettings::root>(l,u,
false);
306 return IR(proj().polys()(carl::get_denom(root) *
Polynomial(proj().polys().context(),
var()) - carl::get_num(root)), 1);
310 #ifdef SMTRAT_DEVOPTION_Statistics
311 OCApproximationStatistics::get_instance().approximated(
proj().degree(p.
poly));
313 IR result = apx_bound<ApxSettings::bound>(p, bound, below);
319 #ifdef SMTRAT_DEVOPTION_Statistics
320 OCApproximationStatistics::get_instance().approximated(std::max(
proj().degree(p_l.
poly),
proj().degree(p_u.
poly)));
322 return apx_between<ApxSettings::between>(p_l, p_u, l, u);
326 if (
cell().is_section()) {
328 }
else if (
cell().lower_unbounded() &&
cell().upper_unbounded()) {
330 }
else if (
cell().lower_unbounded()) {
335 }
else if (
cell().upper_unbounded()) {
static Bound strict(RootFunction value)
An interval of a delineation.
Represents the delineation of a set of polynomials (at a sample), that is.
Encapsulates all computations on polynomials.
A symbolic interal whose bounds are defined by indexed root expressions.
static bool side(datastructures::Projections &proj, const IR &ir, datastructures::RootMap::const_iterator start, datastructures::RootMap::const_iterator end)
static void inform(const Polynomial &p, std::size_t root_index)
IR apx_bound(const IR &p, const RAN &bound, bool below)
const datastructures::Delineation & del() const
const datastructures::DelineationInterval & cell() const
datastructures::Projections & proj()
IR approximate_bound(const IR &p, const RAN &bound, bool below)
IR apx_between(const IR &p_l, const IR &p_u, const RAN &l, const RAN &u)
IR approximate_between(const IR &p_l, const IR &p_u, const RAN &l, const RAN &u)
datastructures::SymbolicInterval compute_cell()
datastructures::Projections & m_r_proj
Assignment sample() const
const datastructures::DelineationInterval & m_r_cell
carl::Variable var() const
CellApproximator(datastructures::SampledDerivationRef< T > &der)
const datastructures::Delineation & m_r_del
Poly resultant(carl::Variable variable, const Poly &p, const Poly &q)
Computes the resultant of two polynomials.
std::shared_ptr< SampledDerivation< Properties > > SampledDerivationRef
Rational approximate_RAN_above(const RAN &r)
Rational approximate_RAN(const RAN &r)
Rational approximate_RAN_sb(const RAN &r)
datastructures::IndexedRoot IR
const ApxSettings & apx_settings()
Rational approximate_RAN_below(const RAN &r)
std::optional< datastructures::IndexedRoot > simplest_bound(datastructures::Projections &proj, const std::vector< datastructures::TaggedIndexedRoot > &bounds, datastructures::PolyRef origin_filter)
std::vector< carl::Variable > VariableOrdering
carl::Assignment< RAN > Assignment
carl::ContextPolynomial< Rational > Polynomial
Rational evaluate(carl::Variable v, const Poly &p, const Rational &r)
bool substitute(const FormulaT &constr, const carl::Variable var, const carl::vs::Term< Poly > &term, FormulaT &result)
carl::Interval< Rational > RationalInterval
carl::MultivariatePolynomial< Rational > Poly
Represents the i-th root of a multivariate polynomial at its main variable (given an appropriate samp...
PolyRef poly
A multivariate polynomial.
const std::size_t maximize_n_iter
Note: If connected(i) holds, then the indexed root ordering must contain an ordering between the inte...