LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
inequality_solver_ordering.cpp
浏览该文件的文档.
4#include <cmath>
5
7namespace {
8
9int root_number_sign(const NumberNode& number) {
10 const auto& value = number.value();
11 if (const auto* integer = std::get_if<BigInt>(&value)) {
12 if (integer->is_zero()) {
13 return 0;
14 }
15 return integer->is_negative() ? -1 : 1;
16 }
17 if (const auto* rational = std::get_if<Rational>(&value)) {
18 if (rational->get_numerator().is_zero()) {
19 return 0;
20 }
21 return rational->get_numerator().is_negative() ? -1 : 1;
22 }
23 return 0;
24}
25
27 auto exp_expr = LMCAS::detail::make_expression_ptr(power.exponent());
28 if (auto ev = try_checked_numeric_constant(*exp_expr, context)) {
29 if (*ev > 0 && *ev < 1.0) {
30 return 1;
31 }
32 }
33 auto base_expr = LMCAS::detail::make_expression_ptr(power.base());
34 auto bv_checked = try_checked_numeric_constant(*base_expr, context);
35 auto ev_checked = try_checked_numeric_constant(*exp_expr, context);
36 if (!bv_checked || !ev_checked) {
37 return 0;
38 }
39 double bv = *bv_checked;
40 double ev = *ev_checked;
41 int ei = static_cast<int>(ev);
42 if (std::abs(ev - ei) >= 1e-10) {
43 return 0;
44 }
45 if (bv > 0) {
46 return 1;
47 }
48 if (bv < 0) {
49 return (ei % 2 == 0) ? 1 : -1;
50 }
51 return 0;
52}
53
54int root_node_sign(const std::shared_ptr<const SymbolicNode>& node,
56 if (!node) {
57 return 0;
58 }
59 if (auto number = std::dynamic_pointer_cast<const NumberNode>(node)) {
60 return root_number_sign(*number);
61 }
62 if (auto function = std::dynamic_pointer_cast<const FunctionNode>(node)) {
64 return 1;
65 }
66 }
67 if (auto power = std::dynamic_pointer_cast<const PowerNode>(node)) {
68 return root_power_sign(*power, context);
69 }
70 return 0;
71}
72
73int root_expression_sign(const std::shared_ptr<SymbolicExpr>& expr,
75 if (!expr || !LMCAS::detail::node(expr)) {
76 return 0;
77 }
78 int direct = root_node_sign(LMCAS::detail::node(expr), context);
79 if (direct != 0) {
80 return direct;
81 }
82 auto product = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr));
83 if (!product) {
84 return 0;
85 }
86 int sign = 1;
87 for (const auto& operand : product->operands()) {
88 int factor_sign = root_node_sign(operand, context);
89 if (factor_sign == 0) {
90 return 0;
91 }
92 sign *= factor_sign;
93 }
94 return sign;
95}
96
97}
98
99bool root_less_than(const std::shared_ptr<SymbolicExpr>& a,
100 const std::shared_ptr<SymbolicExpr>& b, ComputationContext& context) {
101 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
102 (context).limits().max_ast_nodes, "transform");
103 if (!a || !b) {
104 return false;
105 }
108 if (va && vb) {
109 return *va < *vb;
110 }
111 auto diff = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::add(a, SymbolicExpr::multiply(b, SymbolicExpr::number(-1)))), transform_budget));
112 if (auto vd = try_checked_numeric_constant(*diff, context)) {
113 return *vd < 0;
114 }
115 return root_expression_sign(diff, context) < 0;
116}
117
118bool roots_equal(const std::shared_ptr<SymbolicExpr>& a,
119 const std::shared_ptr<SymbolicExpr>& b, ComputationContext& context) {
120 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
121 (context).limits().max_ast_nodes, "transform");
122 if (!a || !b) {
123 return false;
124 }
125 auto numeric_a = try_checked_numeric_constant(*a, context);
126 auto numeric_b = try_checked_numeric_constant(*b, context);
127 if (numeric_a && numeric_b) {
128 return *numeric_a == *numeric_b;
129 }
130 auto difference = SymbolicExpr::add(
131 a,
132 SymbolicExpr::multiply(SymbolicExpr::number(-1), b));
133 auto simplified = difference ? detail::make_expression_ptr(detail::normalize_node(detail::node(difference), transform_budget)) : nullptr;
134 return simplified && simplified->is_zero();
135}
136}
@ Sqrt
对数、绝对值、平方根。
const std::variant< BigInt, Rational > & value() const noexcept
幂运算节点,表示 base^exponent。
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
int root_node_sign(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context)
int root_expression_sign(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context)
bool root_less_than(const std::shared_ptr< SymbolicExpr > &a, const std::shared_ptr< SymbolicExpr > &b, ComputationContext &context)
bool roots_equal(const std::shared_ptr< SymbolicExpr > &a, const std::shared_ptr< SymbolicExpr > &b, ComputationContext &context)
std::optional< double > try_checked_numeric_constant(const SymbolicExpr &expr, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::size_t std::size_t ComputationContext & context
ExprResult e()
ExprResult integer(Integer)=delete
const MultiPoly & b
__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
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
ExprResult rational(const Rational &value)
内部 AST 定义。