23 return Interval{Endpoint::closed(SymbolicExpr::number(
lower)),
24 Endpoint::closed(SymbolicExpr::number(
upper))};
36 ~Leave() {
context.leave_recursion(); }
39 if (
dynamic_cast<const NumberNode*
>(node.get())) {
46 if (
const auto*
add =
dynamic_cast<const AddNode*
>(node.get())) {
49 if (
const auto* multiply =
dynamic_cast<const MultiplyNode*
>(node.get())) {
52 if (
const auto* power =
dynamic_cast<const PowerNode*
>(node.get())) {
72 if (
order.value() > 0 || (
order.value() == 0 &&
79 for (
const auto& operand :
add.operands()) {
94 std::optional<Interval> numerator;
96 for (
const auto& operand : multiply.operands()) {
97 const auto* power =
dynamic_cast<const PowerNode*
>(operand.get());
99 ? std::dynamic_pointer_cast<const NumberNode>(
103 auto next =
propagate(power && inverse ? power->base() : operand);
104 if (!next) {
return next; }
105 auto& accumulated = inverse ?
denominator : numerator;
107 accumulated = std::move(next.value());
110 if (!product) {
return product; }
111 accumulated = std::move(product.value());
114 if (!numerator) { numerator =
closed_bounds(Rational(1), Rational(1)); }
121 std::dynamic_pointer_cast<const NumberNode>(power.
exponent());
122 BigInt integer_exponent;
126 const bool square = integer_exponent == BigInt(2);
127 const bool inverse =
exponent->is_negative_one();
130 if (!base) {
return base; }
134 auto a =
arithmetic(bounds.value().first, bounds.value().first,
'*');
136 auto b =
arithmetic(bounds.value().second, bounds.value().second,
'*');
138 if (bounds.value().first >= Rational(0))
140 if (bounds.value().second <= Rational(0))
149 if (!step)
return step;
150 const std::size_t a_bits = std::max(
a.get_numerator().bit_length(),
a.get_denominator().bit_length());
151 const std::size_t b_bits = std::max(
b.get_numerator().bit_length(),
b.get_denominator().bit_length());
152 if (a_bits >= std::numeric_limits<std::size_t>::max() - b_bits)
166 bool separate_zero =
false) {
169 auto&
value = comparable.value();
173 auto& algebraic = *
value.algebraic;
179 while (sign.value() > 0 ? algebraic.lower <= Rational(0) : algebraic.upper >= Rational(0)) {
200 if (divide &&
rhs.value().first <= Rational(0) &&
rhs.value().second >= Rational(0))
202 std::array<Rational, 4> corners;
203 std::size_t index = 0;
204 for (
const Rational*
a : {&lhs.value().first, &lhs.value().second}) {
205 for (
const Rational*
b : {&
rhs.value().first, &
rhs.value().second}) {
208 corners[index++] = std::move(corner.value());
211 for (
const auto& corner : corners) {
215 auto extrema = std::minmax_element(corners.begin(), corners.end());
220 if (
lower ? endpoint.is_neg_infinity : endpoint.is_pos_infinity) {
234 auto value = SymbolicExpr::number(
lower ? bounds.value().first : bounds.value().second);
243 const auto& argument =
function.arguments()[0];
247 auto argument_bounds =
propagate(argument);
249 {
return argument_bounds; }
250 if (!argument_bounds) {
261 Interval input = argument_bounds ? std::move(argument_bounds.
value())
262 : Interval{Endpoint::neg_inf(), Endpoint::pos_inf()};
277std::optional<Interval> InferenceEngine::propagate_bounds(
const SymbolicExpr& expr)
const {
279 BoundsPropagation propagation(impl_->ctx, *
this);
280 auto result = propagation.propagate(
detail::node(expr));
281 if (result)
return std::move(result.value());
282 }
catch (
const CasError&) {
284 }
catch (
const std::bad_alloc&) {
286 }
catch (
const std::length_error&) {
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
Result< Rational > rational_endpoint_bound(const Endpoint &endpoint, bool lower, bool separate_zero=false)
Result< Interval > power_bounds(const PowerNode &power)
Result< Interval > arctangent_bounds(Result< Interval > &argument_bounds)
Result< RationalBounds > rational_bounds(const Interval &interval, bool separate_zero=false)
Result< void > arithmetic_budget(const Rational &a, const Rational &b)
Result< Interval > variable_bounds(const VariableNode &variable)
Result< Rational > arithmetic(const Rational &a, const Rational &b, char operation)
BoundsPropagation(const AssumptionContext &assumptions, const InferenceEngine &engine)
Result< Interval > sum_bounds(const AddNode &add)
ComputationContext context_
Result< Interval > product_bounds(const MultiplyNode &multiply)
Result< Endpoint > arctangent_endpoint(const Endpoint &endpoint, bool lower)
Result< Interval > function_bounds(const FunctionNode &function)
Result< Interval > propagate(const std::shared_ptr< const SymbolicNode > &node)
detail::AssumptionFacts facts_
std::optional< detail::ExactConstantInterval > pi_bounds_
const AssumptionContext & assumptions_
Result< Interval > multiply_intervals(const Interval &left, const Interval &right, bool divide)
Result< Interval > unknown_bounds()
constexpr const char * bounds_operation
Interval closed_bounds(const Rational &lower, const Rational &upper)
std::pair< Rational, Rational > RationalBounds
Result< ComparableEndpoint > comparable_endpoint(const Endpoint &endpoint, ComputationContext &context, const std::string &operation)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
Result< Tribool > query_definedness(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context, bool *violated_real_restriction)
Result< void > refine_exact_real_algebraic(ExactRealAlgebraic &value, ComputationContext &context, const std::string &operation)
Result< ExactConstantInterval > exact_atan_bounds(const Rational &value, std::size_t precision_bits, ComputationContext &context)
Result< ExactConstantInterval > exact_pi_bounds(std::size_t precision_bits, ComputationContext &context)
Result< Tribool > query_real_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
Result< int > compare_comparable(const ComparableEndpoint &left, const ComparableEndpoint &right, ComputationContext &context)
const std::string & variable
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult interval(ExprPtr lower, ExprPtr upper, bool lower_closed, bool upper_closed)
bool try_get_integer_value(const std::shared_ptr< const NumberNode > &node, BigInt &value)
ExprResult real(const ExprPtr &expression, ComputationContext &context)
const std::vector< FGLMPoly > const MonomialOrder & order
std::size_t std::size_t std::size_t growth
@ True
Property definitely holds
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
__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
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)