19 if (!result) {
return result; }
21 std::size_t nodes = 0;
22 for (
const auto& branch : result.
value().cases) {
24 for (
const auto&
interval : branch.solution.intervals()) {
35 "parameter signs or quadratic roots cannot be certified",
41 ? IntervalUnion::entire_line()
42 : IntervalUnion::empty();
56 const std::shared_ptr<SymbolicExpr>& coefficient,
int sign) {
57 const auto op = sign > 0 ? RelationalNode::Op::GT
58 : sign < 0 ? RelationalNode::Op::LT : RelationalNode::Op::EQ;
63template <
typename Node>
65 const std::vector<std::string>& parameters,
77 if (!step)
return step;
78 if (
const auto number = std::dynamic_pointer_cast<const NumberNode>(node)) {
80 }
else if (
const auto symbol = std::dynamic_pointer_cast<const VariableNode>(node)) {
81 if (!symbol->is_constant() &&
83 std::find(parameters.begin(), parameters.end(), symbol->name()) != parameters.end())) {
86 }
else if (
const auto sum = std::dynamic_pointer_cast<const AddNode>(node)) {
88 }
else if (
const auto product = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
90 }
else if (
const auto power = std::dynamic_pointer_cast<const PowerNode>(node)) {
92 power->exponent(), 0, std::numeric_limits<int>::max())) {
101template <
typename Node>
103 const std::vector<std::string>& parameters,
105 for (
const auto& operand : node.operands()) {
108 if (!checked)
return checked;
114 const std::vector<std::shared_ptr<SymbolicExpr>>& coeffs,
120 if (*slope == Rational(0)) {
123 std::optional<detail::AssumptionFacts> facts;
127 SymbolicExpr::multiply(SymbolicExpr::number(-1), coeffs[0]), coeffs[1])),
133 const bool above = greater != slope->get_numerator().is_negative();
134 const auto endpoint = strict ? Endpoint::open(root)
135 : Endpoint::closed(root);
136 return above ? Interval{endpoint, Endpoint::pos_inf()}
137 : Interval{Endpoint::neg_inf(), endpoint};
143 auto solved = InequalitySolver::solve_inequality_checked(expr, type,
variable,
context);
145 PiecewiseIntervalResult result;
146 result.cases.push_back({
nullptr, std::move(solved.value())});
152 PiecewiseIntervalResult result;
153 for (
int sign : {1, 0, -1}) {
154 result.cases.push_back({
156 satisfies(sign, type) ? IntervalUnion::entire_line()
157 : IntervalUnion::empty()});
164 PiecewiseIntervalResult result;
165 for (
int sign : {1, 0, -1}) {
168 {SymbolicExpr::number(0)}, {2}, sign, type,
context);
169 result.cases.push_back({
sign_condition(coefficient, sign), std::move(solution)});
174 const std::vector<std::shared_ptr<SymbolicExpr>>& coeffs,
177 if (!coeffs[0]->is_zero() || !coeffs[1]->is_zero())
return inconclusive();
182 const std::shared_ptr<SymbolicExpr>& expr,
const std::string&
variable,
183 const std::vector<std::string>& parameters) {
190 if (std::find(parameters.begin(), parameters.end(),
variable) != parameters.end()) {
201 std::vector<std::shared_ptr<SymbolicExpr>> coeffs;
202 coeffs.reserve(poly.
coeffs.size());
203 std::optional<detail::AssumptionFacts> facts;
205 std::size_t nodes = 0;
206 for (
const auto& coefficient : poly.
coeffs) {
211 coeffs.push_back(std::move(
value));
217Result<PiecewiseIntervalResult> InequalitySolver::solve_parametric_inequality_checked(
218 const std::shared_ptr<SymbolicExpr>& expr,
221 const std::vector<std::string>& parameters,
223 auto arguments = check_arguments(expr,
variable, parameters);
225 return PiecewiseResult::failure(arguments.error());
230 context.limits().max_ast_nodes, kParametricOperation);
232 if (parameters.empty()) {
237 return PiecewiseResult::failure(converted.error());
239 const auto& poly = converted.value();
240 if (poly.degree() > 2) {
247 return PiecewiseResult::failure(exact.error());
250 if (poly.is_zero()) {
251 PiecewiseIntervalResult result;
256 bool symbolic =
false;
259 return PiecewiseResult::failure(simplified.error());
261 const auto& coeffs = simplified.value();
267 if (poly.degree() != 1) {
274 PiecewiseIntervalResult result;
275 result.cases.push_back({
nullptr, IntervalUnion::from_checked_normalized(
279 return PiecewiseResult::failure(error);
280 }
catch (
const std::length_error& error) {
282 }
catch (
const std::bad_alloc&) {
283 return PiecewiseResult::failure(
285 kParametricOperation);
286 }
catch (
const std::exception& error) {
287 return PiecewiseResult::failure(
293 const std::shared_ptr<SymbolicExpr>& expr,
296 const std::vector<std::string>& parameters) {
298 return solve_parametric_inequality_checked(expr, type,
variable, parameters,
context);
const std::shared_ptr< const AssumptionContext > & assumptions() const noexcept
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
ComputationContext & context() const noexcept
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
std::size_t append_size(std::size_t current, std::size_t child)
bool satisfies(int sign, InequalityType type)
Result< PiecewiseIntervalResult > PiecewiseResult
PiecewiseResult constant_solution(const std::shared_ptr< SymbolicExpr > &coefficient, InequalityType type)
PiecewiseResult quadratic_solution(const std::shared_ptr< SymbolicExpr > &coefficient, InequalityType type, ComputationContext &context)
Result< void > check_arguments(const std::shared_ptr< SymbolicExpr > &expr, const std::string &variable, const std::vector< std::string > ¶meters)
IntervalUnion zero_polynomial_solution(InequalityType type)
Result< void > exact_operands(const Node &node, const std::string &variable, const std::vector< std::string > ¶meters, ComputationContext &context, std::size_t depth)
std::shared_ptr< SymbolicExpr > sign_condition(const std::shared_ptr< SymbolicExpr > &coefficient, int sign)
Result< std::vector< std::shared_ptr< SymbolicExpr > > > simplify_coefficients(const Polynomial< SymbolicPolyCoeff > &poly, bool &symbolic, detail::RewriteBudget &budget)
PiecewiseResult nonlinear_solution(const std::vector< std::shared_ptr< SymbolicExpr > > &coeffs, int degree, InequalityType type, ComputationContext &context)
constexpr const char * kParametricOperation
Result< Interval > linear_interval(const std::vector< std::shared_ptr< SymbolicExpr > > &coeffs, InequalityType type, detail::RewriteBudget &budget)
PiecewiseResult checked_piecewise(PiecewiseResult result, detail::RewriteBudget &budget)
PiecewiseResult inconclusive()
Result< void > exact_polynomial_nodes(const detail::SymbolicNodePtr &node, const std::string &variable, const std::vector< std::string > ¶meters, ComputationContext &context, std::size_t depth)
PiecewiseResult solved_inequality(const std::shared_ptr< SymbolicExpr > &expr, InequalityType type, const std::string &variable, ComputationContext &context)
IntervalUnion build_parametric_intervals(const std::vector< std::shared_ptr< SymbolicExpr > > &symbolic_roots, const std::vector< int > &multiplicities, int leading_sign, InequalityType type, ComputationContext &context)
Result< Polynomial< SymbolicPolyCoeff > > symbolic_to_poly_checked(const SymbolicExpr &expression, const std::string &variable, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
const FactsQuery & no_facts() noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
std::optional< Rational > exact_rational_value(const NumberNode &number)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
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)
const ExprPtr RelationOp op
std::size_t std::size_t depth
std::optional< int > exact_small_integer_node(const detail::SymbolicNodePtr &node, int min_value, int max_value)
const std::string const ExprPtr & value