LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
differentiation_functions.cpp
浏览该文件的文档.
2
3namespace LMCAS {
4
5namespace {
6
7std::shared_ptr<const SymbolicNode> trigonometric_outer(
8 const FunctionNode& node, detail::RewriteBudget* budget) {
9 std::shared_ptr<const SymbolicNode> d_outer;
10 switch (node.type()) {
13 break;
18 }, budget);
19 break;
21 {
24 }
25 break;
27 {
32 csc_sq
33 }, budget);
34 }
35 break;
37 {
40 d_outer = SymbolicFactory::create_multiply({sec, tan}, budget);
41 }
42 break;
44 {
49 csc, cot
50 }, budget);
51 }
52 break;
53 default:
54 return nullptr;
55 }
56 budget->measure(d_outer);
57 return d_outer;
58}
59
60std::shared_ptr<const SymbolicNode> inverse_trigonometric_outer(
61 const FunctionNode& node, detail::RewriteBudget* budget) {
62 const auto& arg = node.arguments()[0];
63 std::shared_ptr<const SymbolicNode> d_outer;
64 switch (node.type()) {
66 {
68 auto neg_arg_sq = SymbolicFactory::create_multiply({
69 SymbolicFactory::create_number(BigInt(-1)), arg_sq
70 }, budget);
71 auto one_minus_sq = SymbolicFactory::create_add({
72 SymbolicFactory::create_number(BigInt(1)), neg_arg_sq
73 }, budget);
75 one_minus_sq, SymbolicFactory::create_number(Rational(-1, 2)));
76 }
77 break;
79 {
81 auto neg_arg_sq = SymbolicFactory::create_multiply({
82 SymbolicFactory::create_number(BigInt(-1)), arg_sq
83 }, budget);
84 auto one_minus_sq = SymbolicFactory::create_add({
85 SymbolicFactory::create_number(BigInt(1)), neg_arg_sq
86 }, budget);
88 one_minus_sq, SymbolicFactory::create_number(Rational(-1, 2)));
90 SymbolicFactory::create_number(BigInt(-1)), inv_sqrt
91 }, budget);
92 }
93 break;
95 {
97 auto one_plus_sq = SymbolicFactory::create_add({
98 SymbolicFactory::create_number(BigInt(1)), arg_sq
99 }, budget);
101 one_plus_sq, SymbolicFactory::create_number(BigInt(-1)));
102 }
103 break;
104 default:
105 return nullptr;
106 }
107 budget->measure(d_outer);
108 return d_outer;
109}
110
111std::shared_ptr<const SymbolicNode> hyperbolic_outer(
112 const FunctionNode& node, detail::RewriteBudget* budget) {
113 std::shared_ptr<const SymbolicNode> d_outer;
114 switch (node.type()) {
117 FunctionNode::FuncType::Cosh, node.arguments());
118 break;
121 FunctionNode::FuncType::Sinh, node.arguments());
122 break;
124 {
126 FunctionNode::FuncType::Cosh, node.arguments());
128 cosh, SymbolicFactory::create_number(BigInt(-2)));
129 }
130 break;
131 default:
132 return nullptr;
133 }
134 budget->measure(d_outer);
135 return d_outer;
136}
137
138std::shared_ptr<const SymbolicNode> elementary_outer(
139 const FunctionNode& node, detail::RewriteBudget* budget) {
140 const auto& arg = node.arguments()[0];
141 std::shared_ptr<const SymbolicNode> d_outer;
142 switch (node.type()) {
145 break;
148 break;
151 SymbolicFactory::create_number(Rational(1, 2)),
153 }, budget);
154 break;
156 {
158 FunctionNode::FuncType::Abs, node.arguments());
159 auto abs_inv = LMCAS::detail::make_node<PowerNode>(abs_arg, SymbolicFactory::create_number(BigInt(-1)));
160 d_outer = SymbolicFactory::create_multiply({arg, abs_inv}, budget);
161 }
162 break;
163 default:
164 return nullptr;
165 }
166 budget->measure(d_outer);
167 return d_outer;
168}
169
170std::shared_ptr<const SymbolicNode> special_outer(
171 const FunctionNode& node, detail::RewriteBudget* budget) {
172 const auto& arg = node.arguments()[0];
173 std::shared_ptr<const SymbolicNode> d_outer;
174 switch (node.type()) {
176 {
178 auto one = SymbolicFactory::create_number(BigInt(1));
179 auto one_plus_W = SymbolicFactory::create_add({one, W}, budget);
180 auto minus_W = SymbolicFactory::create_multiply({
181 SymbolicFactory::create_number(BigInt(-1)), W}, budget);
184 std::vector<std::shared_ptr<const SymbolicNode>>{minus_W});
185 auto denominator_inverse = LMCAS::detail::make_node<PowerNode>(
186 one_plus_W, SymbolicFactory::create_number(BigInt(-1)));
187 d_outer = SymbolicFactory::create_multiply({numerator, denominator_inverse}, budget);
188 }
189 break;
191 {
195 std::vector<std::shared_ptr<const SymbolicNode>>{pi});
196 auto sqrt_pi_inv = LMCAS::detail::make_node<PowerNode>(sqrt_pi, SymbolicFactory::create_number(BigInt(-1)));
197 auto two = SymbolicFactory::create_number(BigInt(2));
198 auto neg_one = SymbolicFactory::create_number(BigInt(-1));
200 auto neg_arg_sq = SymbolicFactory::create_multiply({neg_one, arg_sq}, budget);
203 std::vector<std::shared_ptr<const SymbolicNode>>{neg_arg_sq});
204 d_outer = SymbolicFactory::create_multiply({two, sqrt_pi_inv, exp_term}, budget);
205 }
206 break;
208 {
210 FunctionNode::FuncType::Exp, node.arguments());
212 d_outer = SymbolicFactory::create_multiply({exp_arg, arg_inv}, budget);
213 }
214 break;
216 {
218 FunctionNode::FuncType::Sin, node.arguments());
220 d_outer = SymbolicFactory::create_multiply({sin_arg, arg_inv}, budget);
221 }
222 break;
224 {
226 FunctionNode::FuncType::Cos, node.arguments());
228 d_outer = SymbolicFactory::create_multiply({cos_arg, arg_inv}, budget);
229 }
230 break;
232 {
234 FunctionNode::FuncType::Ln, node.arguments());
236 }
237 break;
238 default:
239 return nullptr;
240 }
241 budget->measure(d_outer);
242 return d_outer;
243}
244
245bool valid_log_base(const std::shared_ptr<const SymbolicNode>& base) {
246 auto number = std::dynamic_pointer_cast<const NumberNode>(base);
247 return number && number->is_positive() && !number->is_one();
248}
249
250std::shared_ptr<const SymbolicNode> logarithmic_outer(
251 const FunctionNode& node, detail::RewriteBudget* budget) {
252 const auto& arg = node.arguments()[0];
253 const auto& base = node.arguments()[1];
256 std::vector<std::shared_ptr<const SymbolicNode>>{base});
258 SymbolicFactory::create_multiply({arg, ln_base}, budget),
260}
261
262}
263
265 auto* budget = rewrite_budget();
266 const auto& y = node.arguments()[0];
267 const auto& x = node.arguments()[1];
268 y->accept(*this);
269 auto dy = result;
270 x->accept(*this);
271 auto dx = result;
272 auto numerator = SymbolicFactory::create_add({
273 SymbolicFactory::create_multiply({x, dy}, budget),
275 SymbolicFactory::create_number(BigInt(-1)), y, dx}, budget)
276 }, budget);
277 auto two = SymbolicFactory::create_number(BigInt(2));
281 }, budget);
284 set_result(SymbolicFactory::create_multiply({numerator, inverse}, budget));
285}
286
288 auto* budget = rewrite_budget();
289 if (node.type() == FunctionNode::FuncType::Atan2 && node.arguments().size() == 2) {
291 return;
292 }
293 if (node.type() == FunctionNode::FuncType::Log && node.arguments().size() == 2) {
294 const auto& arg = node.arguments()[0];
295 if (!valid_log_base(node.arguments()[1])) {
296 unsupported("FunctionNode");
297 }
298 arg->accept(*this);
299 auto d_arg = result;
300 if (d_arg->is_zero()) return;
301 auto inverse = logarithmic_outer(node, budget);
302 set_result(SymbolicFactory::create_multiply({std::move(d_arg), inverse}, budget));
303 return;
304 }
305 if (node.arguments().size() != 1) unsupported("FunctionNode");
306 node.arguments()[0]->accept(*this);
307 auto d_arg = result;
308 if (d_arg->is_zero()) {
309 return;
310 }
311
312 auto d_outer = trigonometric_outer(node, budget);
313 if (!d_outer) d_outer = inverse_trigonometric_outer(node, budget);
314 if (!d_outer) d_outer = hyperbolic_outer(node, budget);
315 if (!d_outer) d_outer = elementary_outer(node, budget);
316 if (!d_outer) d_outer = special_outer(node, budget);
317 if (!d_outer) unsupported("FunctionNode");
318 set_result(SymbolicFactory::create_multiply({std::move(d_outer), std::move(d_arg)}, budget));
319}
320
321}
void unsupported(const char *node_type) const
std::shared_ptr< const SymbolicNode > result
求导结果节点。
void differentiate_atan2(const FunctionNode &node)
void visit(const NumberNode &) override
void set_result(std::shared_ptr< const SymbolicNode > candidate)
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
@ Si
正弦积分 Si(x) = ∫₀ˣ sin(t)/t dt。
@ Atan2
双参数反正切。
@ Li
对数积分 Li(x) = ∫₀ˣ 1/ln(t) dt。
@ Sqrt
对数、绝对值、平方根。
@ Erf
误差函数 erf(x) = (2/√π)∫₀ˣ e^(-t²) dt。
static std::shared_ptr< const SymbolicNode > create_add(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建加法节点,自动扁平化嵌套加法并消除零项.
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
static std::shared_ptr< const SymbolicNode > create_number(const ::LMCAS::BigInt &v)
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
RewriteBudget * rewrite_budget() const noexcept
微分访问器,对 AST 执行符号求导。
std::shared_ptr< const SymbolicNode > elementary_outer(const FunctionNode &node, detail::RewriteBudget *budget)
std::shared_ptr< const SymbolicNode > special_outer(const FunctionNode &node, detail::RewriteBudget *budget)
std::shared_ptr< const SymbolicNode > inverse_trigonometric_outer(const FunctionNode &node, detail::RewriteBudget *budget)
std::shared_ptr< const SymbolicNode > trigonometric_outer(const FunctionNode &node, detail::RewriteBudget *budget)
std::shared_ptr< const SymbolicNode > logarithmic_outer(const FunctionNode &node, detail::RewriteBudget *budget)
bool valid_log_base(const std::shared_ptr< const SymbolicNode > &base)
std::shared_ptr< const SymbolicNode > hyperbolic_outer(const FunctionNode &node, detail::RewriteBudget *budget)
std::shared_ptr< const Node > make_node(Args &&... args)
ExprResult tan(const ExprPtr &expression, ComputationContext &context)
ExprResult pi()
const ExprPtr & denominator