LMCAS
Lamina Computer Algebra System
Toggle main menu visibility
载入中...
搜索中...
未找到
differentiation_functions.cpp
浏览该文件的文档.
1
#include "
internal/visitors/differentiation_visitor.hpp
"
2
3
namespace
LMCAS
{
4
5
namespace
{
6
7
std::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()) {
11
case
FunctionNode::FuncType::Sin
:
12
d_outer =
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Cos
, node.arguments());
13
break
;
14
case
FunctionNode::FuncType::Cos
:
15
d_outer =
SymbolicFactory::create_multiply
({
16
SymbolicFactory::create_number
(BigInt(-1)),
17
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Sin
, node.arguments())
18
}, budget);
19
break
;
20
case
FunctionNode::FuncType::Tan
:
21
{
22
auto
sec =
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Sec
, node.arguments());
23
d_outer =
LMCAS::detail::make_node<PowerNode>
(sec,
SymbolicFactory::create_number
(BigInt(2)));
24
}
25
break
;
26
case
FunctionNode::FuncType::Cot
:
27
{
28
auto
csc =
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Csc
, node.arguments());
29
auto
csc_sq =
LMCAS::detail::make_node<PowerNode>
(csc,
SymbolicFactory::create_number
(BigInt(2)));
30
d_outer =
SymbolicFactory::create_multiply
({
31
SymbolicFactory::create_number
(BigInt(-1)),
32
csc_sq
33
}, budget);
34
}
35
break
;
36
case
FunctionNode::FuncType::Sec
:
37
{
38
auto
sec =
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Sec
, node.arguments());
39
auto
tan
=
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Tan
, node.arguments());
40
d_outer =
SymbolicFactory::create_multiply
({sec,
tan
}, budget);
41
}
42
break
;
43
case
FunctionNode::FuncType::Csc
:
44
{
45
auto
csc =
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Csc
, node.arguments());
46
auto
cot =
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Cot
, node.arguments());
47
d_outer =
SymbolicFactory::create_multiply
({
48
SymbolicFactory::create_number
(BigInt(-1)),
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
60
std::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()) {
65
case
FunctionNode::FuncType::ArcSin
:
66
{
67
auto
arg_sq =
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(BigInt(2)));
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);
74
d_outer =
LMCAS::detail::make_node<PowerNode>
(
75
one_minus_sq,
SymbolicFactory::create_number
(Rational(-1, 2)));
76
}
77
break
;
78
case
FunctionNode::FuncType::ArcCos
:
79
{
80
auto
arg_sq =
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(BigInt(2)));
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);
87
auto
inv_sqrt =
LMCAS::detail::make_node<PowerNode>
(
88
one_minus_sq,
SymbolicFactory::create_number
(Rational(-1, 2)));
89
d_outer =
SymbolicFactory::create_multiply
({
90
SymbolicFactory::create_number
(BigInt(-1)), inv_sqrt
91
}, budget);
92
}
93
break
;
94
case
FunctionNode::FuncType::ArcTan
:
95
{
96
auto
arg_sq =
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(BigInt(2)));
97
auto
one_plus_sq =
SymbolicFactory::create_add
({
98
SymbolicFactory::create_number
(BigInt(1)), arg_sq
99
}, budget);
100
d_outer =
LMCAS::detail::make_node<PowerNode>
(
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
111
std::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()) {
115
case
FunctionNode::FuncType::Sinh
:
116
d_outer =
LMCAS::detail::make_node<FunctionNode>
(
117
FunctionNode::FuncType::Cosh
, node.arguments());
118
break
;
119
case
FunctionNode::FuncType::Cosh
:
120
d_outer =
LMCAS::detail::make_node<FunctionNode>
(
121
FunctionNode::FuncType::Sinh
, node.arguments());
122
break
;
123
case
FunctionNode::FuncType::Tanh
:
124
{
125
auto
cosh =
LMCAS::detail::make_node<FunctionNode>
(
126
FunctionNode::FuncType::Cosh
, node.arguments());
127
d_outer =
LMCAS::detail::make_node<PowerNode>
(
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
138
std::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()) {
143
case
FunctionNode::FuncType::Exp
:
144
d_outer =
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::Exp
, node.arguments());
145
break
;
146
case
FunctionNode::FuncType::Ln
:
147
d_outer =
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(BigInt(-1)));
148
break
;
149
case
FunctionNode::FuncType::Sqrt
:
150
d_outer =
SymbolicFactory::create_multiply
({
151
SymbolicFactory::create_number
(Rational(1, 2)),
152
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(Rational(-1, 2)))
153
}, budget);
154
break
;
155
case
FunctionNode::FuncType::Abs
:
156
{
157
auto
abs_arg =
LMCAS::detail::make_node<FunctionNode>
(
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
170
std::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()) {
175
case
FunctionNode::FuncType::LambertW
:
176
{
177
auto
W =
LMCAS::detail::make_node<FunctionNode>
(
FunctionNode::FuncType::LambertW
, node.arguments());
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);
182
auto
numerator =
LMCAS::detail::make_node<FunctionNode>
(
183
FunctionNode::FuncType::Exp
,
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
;
190
case
FunctionNode::FuncType::Erf
:
191
{
192
auto
pi
=
LMCAS::detail::make_node<VariableNode>
(
"pi"
,
true
);
193
auto
sqrt_pi =
LMCAS::detail::make_node<FunctionNode>
(
194
FunctionNode::FuncType::Sqrt
,
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));
199
auto
arg_sq =
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(BigInt(2)));
200
auto
neg_arg_sq =
SymbolicFactory::create_multiply
({neg_one, arg_sq}, budget);
201
auto
exp_term =
LMCAS::detail::make_node<FunctionNode>
(
202
FunctionNode::FuncType::Exp
,
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
;
207
case
FunctionNode::FuncType::Ei
:
208
{
209
auto
exp_arg =
LMCAS::detail::make_node<FunctionNode>
(
210
FunctionNode::FuncType::Exp
, node.arguments());
211
auto
arg_inv =
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(BigInt(-1)));
212
d_outer =
SymbolicFactory::create_multiply
({exp_arg, arg_inv}, budget);
213
}
214
break
;
215
case
FunctionNode::FuncType::Si
:
216
{
217
auto
sin_arg =
LMCAS::detail::make_node<FunctionNode>
(
218
FunctionNode::FuncType::Sin
, node.arguments());
219
auto
arg_inv =
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(BigInt(-1)));
220
d_outer =
SymbolicFactory::create_multiply
({sin_arg, arg_inv}, budget);
221
}
222
break
;
223
case
FunctionNode::FuncType::Ci
:
224
{
225
auto
cos_arg =
LMCAS::detail::make_node<FunctionNode>
(
226
FunctionNode::FuncType::Cos
, node.arguments());
227
auto
arg_inv =
LMCAS::detail::make_node<PowerNode>
(arg,
SymbolicFactory::create_number
(BigInt(-1)));
228
d_outer =
SymbolicFactory::create_multiply
({cos_arg, arg_inv}, budget);
229
}
230
break
;
231
case
FunctionNode::FuncType::Li
:
232
{
233
auto
ln_arg =
LMCAS::detail::make_node<FunctionNode>
(
234
FunctionNode::FuncType::Ln
, node.arguments());
235
d_outer =
LMCAS::detail::make_node<PowerNode>
(ln_arg,
SymbolicFactory::create_number
(BigInt(-1)));
236
}
237
break
;
238
default
:
239
return
nullptr
;
240
}
241
budget->
measure
(d_outer);
242
return
d_outer;
243
}
244
245
bool
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
250
std::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];
254
auto
ln_base =
LMCAS::detail::make_node<FunctionNode>
(
255
FunctionNode::FuncType::Ln
,
256
std::vector<std::shared_ptr<const SymbolicNode>>{base});
257
return
LMCAS::detail::make_node<PowerNode>
(
258
SymbolicFactory::create_multiply
({arg, ln_base}, budget),
259
SymbolicFactory::create_number
(BigInt(-1)));
260
}
261
262
}
263
264
void
DifferentiationVisitor::differentiate_atan2
(
const
FunctionNode
& node) {
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),
274
SymbolicFactory::create_multiply
({
275
SymbolicFactory::create_number
(BigInt(-1)), y, dx}, budget)
276
}, budget);
277
auto
two =
SymbolicFactory::create_number
(BigInt(2));
278
auto
denominator
=
SymbolicFactory::create_add
({
279
LMCAS::detail::make_node<PowerNode>
(x, two),
280
LMCAS::detail::make_node<PowerNode>
(y, two)
281
}, budget);
282
auto
inverse =
LMCAS::detail::make_node<PowerNode>
(
283
denominator
,
SymbolicFactory::create_number
(BigInt(-1)));
284
set_result
(
SymbolicFactory::create_multiply
({numerator, inverse}, budget));
285
}
286
287
void
DifferentiationVisitor::visit
(
const
FunctionNode
& node) {
288
auto
* budget =
rewrite_budget
();
289
if
(node.type() ==
FunctionNode::FuncType::Atan2
&& node.arguments().size() == 2) {
290
differentiate_atan2
(node);
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
}
LMCAS::DifferentiationVisitor::unsupported
void unsupported(const char *node_type) const
定义
differentiation_visitor.hpp:15
LMCAS::DifferentiationVisitor::result
std::shared_ptr< const SymbolicNode > result
求导结果节点。
定义
differentiation_visitor.hpp:22
LMCAS::DifferentiationVisitor::differentiate_atan2
void differentiate_atan2(const FunctionNode &node)
定义
differentiation_functions.cpp:264
LMCAS::DifferentiationVisitor::visit
void visit(const NumberNode &) override
定义
differentiation_arithmetic.cpp:5
LMCAS::DifferentiationVisitor::set_result
void set_result(std::shared_ptr< const SymbolicNode > candidate)
定义
differentiation_visitor.hpp:66
LMCAS::FunctionNode
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
定义
functions.hpp:10
LMCAS::FunctionNode::FuncType::Sin
@ Sin
定义
functions.hpp:13
LMCAS::FunctionNode::FuncType::Tan
@ Tan
定义
functions.hpp:13
LMCAS::FunctionNode::FuncType::Abs
@ Abs
定义
functions.hpp:16
LMCAS::FunctionNode::FuncType::Si
@ Si
正弦积分 Si(x) = ∫₀ˣ sin(t)/t dt。
定义
functions.hpp:23
LMCAS::FunctionNode::FuncType::Sec
@ Sec
定义
functions.hpp:13
LMCAS::FunctionNode::FuncType::Cosh
@ Cosh
定义
functions.hpp:15
LMCAS::FunctionNode::FuncType::Ei
@ Ei
指数积分 Ei(x)。
定义
functions.hpp:22
LMCAS::FunctionNode::FuncType::Atan2
@ Atan2
双参数反正切。
定义
functions.hpp:19
LMCAS::FunctionNode::FuncType::Csc
@ Csc
三角函数。
定义
functions.hpp:13
LMCAS::FunctionNode::FuncType::Ci
@ Ci
余弦积分 Ci(x)。
定义
functions.hpp:24
LMCAS::FunctionNode::FuncType::Li
@ Li
对数积分 Li(x) = ∫₀ˣ 1/ln(t) dt。
定义
functions.hpp:25
LMCAS::FunctionNode::FuncType::Sinh
@ Sinh
定义
functions.hpp:15
LMCAS::FunctionNode::FuncType::Ln
@ Ln
定义
functions.hpp:16
LMCAS::FunctionNode::FuncType::Sqrt
@ Sqrt
对数、绝对值、平方根。
定义
functions.hpp:16
LMCAS::FunctionNode::FuncType::ArcSin
@ ArcSin
定义
functions.hpp:14
LMCAS::FunctionNode::FuncType::ArcCos
@ ArcCos
定义
functions.hpp:14
LMCAS::FunctionNode::FuncType::Exp
@ Exp
指数函数。
定义
functions.hpp:17
LMCAS::FunctionNode::FuncType::Cot
@ Cot
定义
functions.hpp:13
LMCAS::FunctionNode::FuncType::Tanh
@ Tanh
双曲函数。
定义
functions.hpp:15
LMCAS::FunctionNode::FuncType::Log
@ Log
定义
functions.hpp:16
LMCAS::FunctionNode::FuncType::ArcTan
@ ArcTan
反三角函数。
定义
functions.hpp:14
LMCAS::FunctionNode::FuncType::LambertW
@ LambertW
Lambert W 函数。
定义
functions.hpp:18
LMCAS::FunctionNode::FuncType::Erf
@ Erf
误差函数 erf(x) = (2/√π)∫₀ˣ e^(-t²) dt。
定义
functions.hpp:21
LMCAS::FunctionNode::FuncType::Cos
@ Cos
定义
functions.hpp:13
LMCAS::SymbolicFactory::create_add
static std::shared_ptr< const SymbolicNode > create_add(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建加法节点,自动扁平化嵌套加法并消除零项.
定义
symbolic_factory.cpp:12
LMCAS::SymbolicFactory::create_multiply
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
定义
symbolic_factory.cpp:83
LMCAS::SymbolicFactory::create_number
static std::shared_ptr< const SymbolicNode > create_number(const ::LMCAS::BigInt &v)
定义
symbolic_factory.cpp:7
LMCAS::detail::RewriteBudget
定义
rewrite_budget.hpp:15
LMCAS::detail::RewriteBudget::measure
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
定义
rewrite_budget.cpp:179
LMCAS::detail::SymbolicVisitor::rewrite_budget
RewriteBudget * rewrite_budget() const noexcept
定义
base.hpp:220
differentiation_visitor.hpp
微分访问器,对 AST 执行符号求导。
LMCAS::anonymous_namespace{differentiation_functions.cpp}::elementary_outer
std::shared_ptr< const SymbolicNode > elementary_outer(const FunctionNode &node, detail::RewriteBudget *budget)
定义
differentiation_functions.cpp:138
LMCAS::anonymous_namespace{differentiation_functions.cpp}::special_outer
std::shared_ptr< const SymbolicNode > special_outer(const FunctionNode &node, detail::RewriteBudget *budget)
定义
differentiation_functions.cpp:170
LMCAS::anonymous_namespace{differentiation_functions.cpp}::inverse_trigonometric_outer
std::shared_ptr< const SymbolicNode > inverse_trigonometric_outer(const FunctionNode &node, detail::RewriteBudget *budget)
定义
differentiation_functions.cpp:60
LMCAS::anonymous_namespace{differentiation_functions.cpp}::trigonometric_outer
std::shared_ptr< const SymbolicNode > trigonometric_outer(const FunctionNode &node, detail::RewriteBudget *budget)
定义
differentiation_functions.cpp:7
LMCAS::anonymous_namespace{differentiation_functions.cpp}::logarithmic_outer
std::shared_ptr< const SymbolicNode > logarithmic_outer(const FunctionNode &node, detail::RewriteBudget *budget)
定义
differentiation_functions.cpp:250
LMCAS::anonymous_namespace{differentiation_functions.cpp}::valid_log_base
bool valid_log_base(const std::shared_ptr< const SymbolicNode > &base)
定义
differentiation_functions.cpp:245
LMCAS::anonymous_namespace{differentiation_functions.cpp}::hyperbolic_outer
std::shared_ptr< const SymbolicNode > hyperbolic_outer(const FunctionNode &node, detail::RewriteBudget *budget)
定义
differentiation_functions.cpp:111
LMCAS::detail::make_node
std::shared_ptr< const Node > make_node(Args &&... args)
定义
base.hpp:123
LMCAS
定义
assumption.hpp:11
LMCAS::tan
ExprResult tan(const ExprPtr &expression, ComputationContext &context)
定义
expr_elementary.cpp:62
LMCAS::pi
ExprResult pi()
定义
expr_values.cpp:108
LMCAS::denominator
const ExprPtr & denominator
定义
expr.hpp:200
src
differentiation_functions.cpp
生成于
, 为 LMCAS使用
1.18.0