11 std::shared_ptr<SymbolicExpr>
value;
20 return IntervalUnion::empty();
24 if (den_roots_with_mult.empty()) {
25 return IntervalUnion::entire_line();
28 std::vector<std::shared_ptr<SymbolicExpr>> den_roots;
29 for (
const auto& [root, mult] : den_roots_with_mult) {
30 den_roots.push_back(root);
32 std::sort(den_roots.begin(), den_roots.end(),
34 return root_less_than(lhs, rhs, context);
37 std::vector<Interval> intervals;
41 iv.lower = Endpoint::neg_inf();
42 iv.upper = Endpoint::open(den_roots[0]);
43 intervals.push_back(iv);
45 for (
size_t i = 0; i + 1 < den_roots.size(); ++i) {
47 iv.lower = Endpoint::open(den_roots[i]);
48 iv.upper = Endpoint::open(den_roots[i + 1]);
49 intervals.push_back(iv);
54 iv.lower = Endpoint::open(den_roots.back());
55 iv.upper = Endpoint::pos_inf();
56 intervals.push_back(iv);
58 return IntervalUnion(intervals);
62 const std::shared_ptr<SymbolicExpr>& numerator,
68 std::vector<CriticalPoint> critical_points;
70 for (
const auto& [root, mult] : num_roots_with_mult) {
71 critical_points.push_back({root, mult, 0});
73 for (
const auto& [root, mult] : den_roots_with_mult) {
76 for (
auto& cp : critical_points) {
78 cp.den_multiplicity = mult;
84 critical_points.push_back({root, 0, mult});
88 std::sort(critical_points.begin(), critical_points.end(),
90 return root_less_than(a.value, b.value, context);
92 return critical_points;
96 const std::vector<CriticalPoint>& critical_points,
97 int combined_leading_sign,
int target_sign) {
98 size_t n_cp = critical_points.size();
99 std::vector<int> interval_signs(n_cp + 1);
101 interval_signs[n_cp] = combined_leading_sign;
103 for (
int i = (
int)n_cp - 1; i >= 0; --i) {
104 int total_mult = critical_points[i].num_multiplicity + critical_points[i].den_multiplicity;
105 interval_signs[i] = interval_signs[i + 1];
106 if (total_mult % 2 != 0) {
107 interval_signs[i] = -interval_signs[i];
110 std::vector<Interval> result_intervals;
111 for (
size_t i = 0; i <= n_cp; ++i) {
112 if (interval_signs[i] != target_sign) {
116 interval.lower = i == 0 ? Endpoint::neg_inf() : Endpoint::open(critical_points[i - 1].
value);
117 interval.upper = i == n_cp ? Endpoint::pos_inf() : Endpoint::open(critical_points[i].
value);
118 result_intervals.push_back(
interval);
120 return result_intervals;
124 const std::shared_ptr<SymbolicExpr>& expression,
const std::string&
variable) {
125 auto polynomial = symbolic_to_poly<Rational>(expression,
variable);
130 std::vector<Interval>& intervals,
const std::vector<CriticalPoint>& points,
132 for (
const auto&
point : points) {
133 if (
point.num_multiplicity > 0 &&
point.den_multiplicity == 0) {
141IntervalUnion InequalitySolver::solve_rational_inequality(
142 const std::shared_ptr<SymbolicExpr>& numerator,
149 return IntervalUnion::empty();
152 auto num_conversion = symbolic_to_poly<SymbolicPolyCoeff>(numerator,
variable);
154 if (!num_conversion)
throw std::invalid_argument(num_conversion.error().message);
155 if (!den_conversion)
throw std::invalid_argument(den_conversion.error().message);
156 const auto& num_poly = num_conversion.value();
157 const auto& den_poly = den_conversion.value();
159 if (den_poly.is_zero()) {
160 return IntervalUnion::empty();
163 if (num_poly.is_zero()) {
167 throw std::invalid_argument(
"Numerator is not a supported rational polynomial");
170 throw std::invalid_argument(
"Denominator is not a supported rational polynomial");
175 int combined_leading_sign = num_leading_sign * den_leading_sign;
178 int target_sign = want_positive ? 1 : -1;
183 return IntervalUnion(result_intervals);
void include_rational_zeros(std::vector< Interval > &intervals, const std::vector< CriticalPoint > &points, ComputationContext &context)
bool has_unrecognized_variable_polynomial(const std::shared_ptr< SymbolicExpr > &expression, const std::string &variable)
IntervalUnion zero_numerator_domain(const std::shared_ptr< SymbolicExpr > &denominator, InequalityType type, const std::string &variable, ComputationContext &context)
std::shared_ptr< SymbolicExpr > value
std::vector< Interval > rational_sign_intervals(const std::vector< CriticalPoint > &critical_points, int combined_leading_sign, int target_sign)
std::vector< CriticalPoint > rational_critical_points(const std::shared_ptr< SymbolicExpr > &numerator, const std::shared_ptr< SymbolicExpr > &denominator, const std::string &variable, ComputationContext &context)
std::vector< std::pair< std::shared_ptr< SymbolicExpr >, int > > find_roots_with_multiplicity(const std::shared_ptr< SymbolicExpr > &expr, const std::string &variable, ComputationContext &context)
bool roots_equal(const std::shared_ptr< SymbolicExpr > &a, const std::shared_ptr< SymbolicExpr > &b, ComputationContext &context)
void include_numeric_root(std::vector< Interval > &intervals, const std::shared_ptr< SymbolicExpr > &root, ComputationContext &context)
int determine_leading_sign(const Polynomial< SymbolicPolyCoeff > &poly, ComputationContext &context)
const std::string const LimitExprPtr & point
const std::string & variable
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult interval(ExprPtr lower, ExprPtr upper, bool lower_closed, bool upper_closed)
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
const std::string const ExprPtr & value
const ExprPtr & denominator