LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
query_conditions.cpp
浏览该文件的文档.
2
3namespace LMCAS {
4
5namespace {
6
7using ConditionSet = QueryInterface::ConditionSet;
8using ConditionSets = std::vector<ConditionSet>;
9
10std::shared_ptr<const SymbolicNode> subtracted_operand(
11 const std::shared_ptr<const SymbolicNode>& node) {
12 const auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node);
13 if (!mul || mul->operands().size() != 2) return nullptr;
14 for (std::size_t j = 0; j < 2; ++j) {
15 const auto coefficient =
16 std::dynamic_pointer_cast<const NumberNode>(mul->operands()[j]);
17 if (coefficient && coefficient->is_negative_one()) {
18 return mul->operands()[1 - j];
19 }
20 }
21 return nullptr;
22}
23
25 const std::shared_ptr<const SymbolicNode>& pos_operand,
26 const std::shared_ptr<const SymbolicNode>& neg_operand, Sign target) {
27 const auto lhs_var = std::dynamic_pointer_cast<const VariableNode>(pos_operand);
28 const auto rhs_var = std::dynamic_pointer_cast<const VariableNode>(neg_operand);
29 if (!lhs_var || lhs_var->is_constant() ||
30 !rhs_var || rhs_var->is_constant()) return {};
31 if (target == Sign::Positive) {
32 ConditionSet cs1;
33 cs1.sign_conditions.emplace_back(lhs_var->name(), Sign::Positive);
34 cs1.sign_conditions.emplace_back(rhs_var->name(), Sign::Negative);
35 ConditionSet cs2;
36 auto lhs_expr = LMCAS::detail::expression_from_node(pos_operand);
37 auto rhs_expr = LMCAS::detail::expression_from_node(neg_operand);
38 Relation rel{lhs_expr, rhs_expr, RelationalNode::Op::GT};
39 cs2.relational_conditions.push_back(rel);
40 cs2.sign_conditions.emplace_back(rhs_var->name(), Sign::NonNegative);
41
42 return {cs1, cs2};
43 } else if (target == Sign::Negative) {
44 ConditionSet cs1;
45 cs1.sign_conditions.emplace_back(lhs_var->name(), Sign::Negative);
46 cs1.sign_conditions.emplace_back(rhs_var->name(), Sign::Positive);
47
48 ConditionSet cs2;
49 auto lhs_expr = LMCAS::detail::expression_from_node(pos_operand);
50 auto rhs_expr = LMCAS::detail::expression_from_node(neg_operand);
51 Relation rel{rhs_expr, lhs_expr, RelationalNode::Op::GT};
52 cs2.relational_conditions.push_back(rel);
53 cs2.sign_conditions.emplace_back(lhs_var->name(), Sign::NonNegative);
54
55 return {cs1, cs2};
56 } else if (target == Sign::NonNegative) {
57 ConditionSet cs1;
58 cs1.sign_conditions.emplace_back(lhs_var->name(), Sign::NonNegative);
59 cs1.sign_conditions.emplace_back(rhs_var->name(), Sign::NonPositive);
60
61 ConditionSet cs2;
62 auto lhs_expr = LMCAS::detail::expression_from_node(pos_operand);
63 auto rhs_expr = LMCAS::detail::expression_from_node(neg_operand);
64 Relation rel{lhs_expr, rhs_expr, RelationalNode::Op::GEQ};
65 cs2.relational_conditions.push_back(rel);
66
67 return {cs1, cs2};
68 }
69 return {};
70}
71
73 const std::vector<std::shared_ptr<const SymbolicNode>>& operands, Sign target) {
74 ConditionSet cs;
75 for (const auto& operand : operands) {
76 const auto variable = std::dynamic_pointer_cast<const VariableNode>(operand);
77 if (!variable || variable->is_constant()) return {};
78 cs.sign_conditions.emplace_back(variable->name(), target);
79 }
80 if (cs.sign_conditions.empty()) return {};
81 return {cs};
82}
83
85 if (add.operands().size() == 2) {
86 for (std::size_t i = 0; i < 2; ++i) {
87 const auto negative = subtracted_operand(add.operands()[i]);
88 if (!negative) continue;
89 auto result = difference_conditions(add.operands()[1 - i], negative, target);
90 if (!result.empty()) return result;
91 break;
92 }
93 }
95 return variable_operand_conditions(add.operands(), target);
96 }
97 return {};
98}
99
101 const std::shared_ptr<const SymbolicNode>& numerator,
102 const std::shared_ptr<const SymbolicNode>& denominator, Sign target) {
103 const auto num_var = std::dynamic_pointer_cast<const VariableNode>(numerator);
104 const auto den_var = std::dynamic_pointer_cast<const VariableNode>(denominator);
105 if (!num_var || num_var->is_constant() ||
106 !den_var || den_var->is_constant()) return {};
107 if (target == Sign::Positive) {
108 ConditionSet cs1;
109 cs1.sign_conditions.emplace_back(num_var->name(), Sign::Positive);
110 cs1.sign_conditions.emplace_back(den_var->name(), Sign::Positive);
111
112 ConditionSet cs2;
113 cs2.sign_conditions.emplace_back(num_var->name(), Sign::Negative);
114 cs2.sign_conditions.emplace_back(den_var->name(), Sign::Negative);
115
116 return {cs1, cs2};
117 } else if (target == Sign::Negative) {
118 ConditionSet cs1;
119 cs1.sign_conditions.emplace_back(num_var->name(), Sign::Positive);
120 cs1.sign_conditions.emplace_back(den_var->name(), Sign::Negative);
121
122 ConditionSet cs2;
123 cs2.sign_conditions.emplace_back(num_var->name(), Sign::Negative);
124 cs2.sign_conditions.emplace_back(den_var->name(), Sign::Positive);
125
126 return {cs1, cs2};
127 }
128 return {};
129}
130
132 if (mul.operands().size() == 2) {
133 for (std::size_t i = 0; i < 2; ++i) {
134 const auto power = std::dynamic_pointer_cast<const PowerNode>(mul.operands()[i]);
135 const auto exponent =
136 power ? std::dynamic_pointer_cast<const NumberNode>(
137 power->exponent())
138 : nullptr;
139 if (exponent && exponent->is_negative_one()) {
140 return quotient_conditions(mul.operands()[1 - i], power->base(), target);
141 }
142 }
143 }
144 if (target == Sign::Positive) {
146 }
147 return {};
148}
149
150}
151
152QueryInterface::QueryConditionSetsResult QueryInterface::query_conditions(
153 const SymbolicExpr& expr, Sign target) const {
154 return query_conditions_checked(expr, target);
155}
156
157std::vector<QueryInterface::ConditionSet> QueryInterface::query_conditions_impl(
158 const SymbolicExpr& expr, Sign target) const {
159 if (!LMCAS::detail::node(expr)) {
160 return {};
161 }
162 if (auto var = std::dynamic_pointer_cast<const VariableNode>(LMCAS::detail::node(expr))) {
163 if (var->is_constant()) return {};
164 ConditionSet cs;
165 cs.sign_conditions.emplace_back(var->name(), target);
166 return {cs};
167 }
168 if (const auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
169 return sum_conditions(*add, target);
170 }
171 if (const auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
172 return product_conditions(*mul, target);
173 }
174 return {};
175}
176
177QueryInterface::QueryConditionSetsResult QueryInterface::query_conditions_checked(
178 const SymbolicExpr& expr, Sign target) const {
180 expr, "query_conditions", [&]() {
181 return query_conditions_impl(expr, target);
182 });
183}
184
185}
加法节点,表示多个操作数的求和。
乘法节点,表示多个操作数的乘积。
ConditionSets quotient_conditions(const std::shared_ptr< const SymbolicNode > &numerator, const std::shared_ptr< const SymbolicNode > &denominator, Sign target)
ConditionSets product_conditions(const MultiplyNode &mul, Sign target)
ConditionSets variable_operand_conditions(const std::vector< std::shared_ptr< const SymbolicNode > > &operands, Sign target)
ConditionSets difference_conditions(const std::shared_ptr< const SymbolicNode > &pos_operand, const std::shared_ptr< const SymbolicNode > &neg_operand, Sign target)
std::shared_ptr< const SymbolicNode > subtracted_operand(const std::shared_ptr< const SymbolicNode > &node)
ConditionSets sum_conditions(const AddNode &add, Sign target)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
Result< T > checked_expression_result(const SymbolicExpr &expr, const std::string &operation, Query &&query)
const std::string & variable
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const ExprPtr & exponent
const ExprPtr & target
const ExprPtr & denominator
Sign
Sign classification for symbols and expressions.
A stored relational constraint between two symbolic expressions.