Line data Source code
1 :
2 : /* -------------------------------------------------------------------------- *
3 : * lepton *
4 : * -------------------------------------------------------------------------- *
5 : * This is part of the lepton expression parser. *
6 : * See https://openmm.org/development. *
7 : * *
8 : * Portions copyright (c) 2009-2021 Stanford University and the Authors. *
9 : * Authors: Peter Eastman *
10 : * Contributors: *
11 : * *
12 : * Permission is hereby granted, free of charge, to any person obtaining a *
13 : * copy of this software and associated documentation files (the "Software"), *
14 : * to deal in the Software without restriction, including without limitation *
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
16 : * and/or sell copies of the Software, and to permit persons to whom the *
17 : * Software is furnished to do so, subject to the following conditions: *
18 : * *
19 : * The above copyright notice and this permission notice shall be included in *
20 : * all copies or substantial portions of the Software. *
21 : * *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
23 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
25 : * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
26 : * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
27 : * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
28 : * USE OR OTHER DEALINGS IN THE SOFTWARE. *
29 : * -------------------------------------------------------------------------- */
30 :
31 : #include "Operation.h"
32 : #include "ExpressionTreeNode.h"
33 : #include "MSVC_erfc.h"
34 :
35 : namespace PLMD {
36 : using namespace lepton;
37 : using namespace std;
38 :
39 38930 : static bool isZero(const ExpressionTreeNode& node) {
40 38930 : if (node.getOperation().getId() != Operation::CONSTANT)
41 : return false;
42 26057 : return dynamic_cast<const Operation::Constant&>(node.getOperation()).getValue() == 0.0;
43 : }
44 :
45 222 : double Operation::Erf::evaluate(double* args, const map<string, double>& variables) const {
46 222 : return erf(args[0]);
47 : }
48 :
49 204 : double Operation::Erfc::evaluate(double* args, const map<string, double>& variables) const {
50 204 : return erfc(args[0]);
51 : }
52 :
53 6849 : ExpressionTreeNode Operation::Constant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
54 6849 : return ExpressionTreeNode(new Operation::Constant(0.0));
55 : }
56 :
57 10881 : ExpressionTreeNode Operation::Variable::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
58 10881 : if (variable == name)
59 5636 : return ExpressionTreeNode(new Operation::Constant(1.0));
60 5245 : return ExpressionTreeNode(new Operation::Constant(0.0));
61 : }
62 :
63 0 : ExpressionTreeNode Operation::Custom::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
64 0 : if (function->getNumArguments() == 0)
65 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
66 0 : ExpressionTreeNode result;
67 : bool foundTerm = false;
68 0 : for (int i = 0; i < getNumArguments(); i++) {
69 0 : if (!isZero(childDerivs[i])) {
70 0 : if (foundTerm)
71 0 : result = ExpressionTreeNode(new Operation::Add(),
72 : result,
73 0 : ExpressionTreeNode(new Operation::Multiply(), ExpressionTreeNode(new Operation::Custom(*this, i), children), childDerivs[i]));
74 : else {
75 0 : result = ExpressionTreeNode(new Operation::Multiply(), ExpressionTreeNode(new Operation::Custom(*this, i), children), childDerivs[i]);
76 : foundTerm = true;
77 : }
78 : }
79 : }
80 0 : if (foundTerm)
81 0 : return result;
82 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
83 0 : }
84 :
85 3902 : ExpressionTreeNode Operation::Add::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
86 3902 : if (isZero(childDerivs[0]))
87 1002 : return childDerivs[1];
88 2900 : if (isZero(childDerivs[1]))
89 872 : return childDerivs[0];
90 2028 : return ExpressionTreeNode(new Operation::Add(), childDerivs[0], childDerivs[1]);
91 : }
92 :
93 2268 : ExpressionTreeNode Operation::Subtract::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
94 2268 : if (isZero(childDerivs[0])) {
95 1387 : if (isZero(childDerivs[1]))
96 1042 : return ExpressionTreeNode(new Operation::Constant(0.0));
97 345 : return ExpressionTreeNode(new Operation::Negate(), childDerivs[1]);
98 : }
99 881 : if (isZero(childDerivs[1]))
100 668 : return childDerivs[0];
101 213 : return ExpressionTreeNode(new Operation::Subtract(), childDerivs[0], childDerivs[1]);
102 : }
103 :
104 8291 : ExpressionTreeNode Operation::Multiply::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
105 8291 : if (isZero(childDerivs[0])) {
106 5436 : if (isZero(childDerivs[1]))
107 2368 : return ExpressionTreeNode(new Operation::Constant(0.0));
108 3068 : return ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]);
109 : }
110 2855 : if (isZero(childDerivs[1]))
111 1113 : return ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]);
112 1742 : return ExpressionTreeNode(new Operation::Add(),
113 3484 : ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]),
114 5226 : ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]));
115 : }
116 :
117 3184 : ExpressionTreeNode Operation::Divide::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
118 3184 : ExpressionTreeNode subexp;
119 3184 : if (isZero(childDerivs[0])) {
120 1124 : if (isZero(childDerivs[1]))
121 257 : return ExpressionTreeNode(new Operation::Constant(0.0));
122 867 : subexp = ExpressionTreeNode(new Operation::Negate(), ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]));
123 : }
124 2060 : else if (isZero(childDerivs[1]))
125 1938 : subexp = ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]);
126 : else
127 244 : subexp = ExpressionTreeNode(new Operation::Subtract(),
128 244 : ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
129 366 : ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]));
130 2927 : return ExpressionTreeNode(new Operation::Divide(), subexp, ExpressionTreeNode(new Operation::Square(), children[1]));
131 3184 : }
132 :
133 1624 : ExpressionTreeNode Operation::Power::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
134 1624 : return ExpressionTreeNode(new Operation::Add(),
135 3248 : ExpressionTreeNode(new Operation::Multiply(),
136 3248 : ExpressionTreeNode(new Operation::Multiply(),
137 : children[1],
138 3248 : ExpressionTreeNode(new Operation::Power(),
139 3248 : children[0], ExpressionTreeNode(new Operation::AddConstant(-1.0), children[1]))),
140 : childDerivs[0]),
141 3248 : ExpressionTreeNode(new Operation::Multiply(),
142 3248 : ExpressionTreeNode(new Operation::Multiply(),
143 3248 : ExpressionTreeNode(new Operation::Log(), children[0]),
144 3248 : ExpressionTreeNode(new Operation::Power(), children[0], children[1])),
145 3248 : childDerivs[1]));
146 : }
147 :
148 2085 : ExpressionTreeNode Operation::Negate::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
149 2085 : if (isZero(childDerivs[0]))
150 1069 : return ExpressionTreeNode(new Operation::Constant(0.0));
151 1016 : return ExpressionTreeNode(new Operation::Negate(), childDerivs[0]);
152 : }
153 :
154 468 : ExpressionTreeNode Operation::Sqrt::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
155 468 : if (isZero(childDerivs[0]))
156 56 : return ExpressionTreeNode(new Operation::Constant(0.0));
157 412 : return ExpressionTreeNode(new Operation::Multiply(),
158 824 : ExpressionTreeNode(new Operation::MultiplyConstant(0.5),
159 824 : ExpressionTreeNode(new Operation::Reciprocal(),
160 824 : ExpressionTreeNode(new Operation::Sqrt(), children[0]))),
161 412 : childDerivs[0]);
162 : }
163 :
164 1300 : ExpressionTreeNode Operation::Exp::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
165 1300 : if (isZero(childDerivs[0]))
166 121 : return ExpressionTreeNode(new Operation::Constant(0.0));
167 1179 : return ExpressionTreeNode(new Operation::Multiply(),
168 2358 : ExpressionTreeNode(new Operation::Exp(), children[0]),
169 1179 : childDerivs[0]);
170 : }
171 :
172 191 : ExpressionTreeNode Operation::Log::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
173 191 : if (isZero(childDerivs[0]))
174 25 : return ExpressionTreeNode(new Operation::Constant(0.0));
175 166 : return ExpressionTreeNode(new Operation::Multiply(),
176 332 : ExpressionTreeNode(new Operation::Reciprocal(), children[0]),
177 166 : childDerivs[0]);
178 : }
179 :
180 148 : ExpressionTreeNode Operation::Sin::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
181 148 : if (isZero(childDerivs[0]))
182 37 : return ExpressionTreeNode(new Operation::Constant(0.0));
183 111 : return ExpressionTreeNode(new Operation::Multiply(),
184 222 : ExpressionTreeNode(new Operation::Cos(), children[0]),
185 111 : childDerivs[0]);
186 : }
187 :
188 343 : ExpressionTreeNode Operation::Cos::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
189 343 : if (isZero(childDerivs[0]))
190 70 : return ExpressionTreeNode(new Operation::Constant(0.0));
191 273 : return ExpressionTreeNode(new Operation::Multiply(),
192 546 : ExpressionTreeNode(new Operation::Negate(),
193 546 : ExpressionTreeNode(new Operation::Sin(), children[0])),
194 273 : childDerivs[0]);
195 : }
196 :
197 2 : ExpressionTreeNode Operation::Sec::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
198 2 : if (isZero(childDerivs[0]))
199 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
200 2 : return ExpressionTreeNode(new Operation::Multiply(),
201 4 : ExpressionTreeNode(new Operation::Multiply(),
202 4 : ExpressionTreeNode(new Operation::Sec(), children[0]),
203 4 : ExpressionTreeNode(new Operation::Tan(), children[0])),
204 2 : childDerivs[0]);
205 : }
206 :
207 2 : ExpressionTreeNode Operation::Csc::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
208 2 : if (isZero(childDerivs[0]))
209 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
210 2 : return ExpressionTreeNode(new Operation::Multiply(),
211 4 : ExpressionTreeNode(new Operation::Negate(),
212 4 : ExpressionTreeNode(new Operation::Multiply(),
213 4 : ExpressionTreeNode(new Operation::Csc(), children[0]),
214 4 : ExpressionTreeNode(new Operation::Cot(), children[0]))),
215 2 : childDerivs[0]);
216 : }
217 :
218 2 : ExpressionTreeNode Operation::Tan::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
219 2 : if (isZero(childDerivs[0]))
220 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
221 2 : return ExpressionTreeNode(new Operation::Multiply(),
222 4 : ExpressionTreeNode(new Operation::Square(),
223 4 : ExpressionTreeNode(new Operation::Sec(), children[0])),
224 2 : childDerivs[0]);
225 : }
226 :
227 2 : ExpressionTreeNode Operation::Cot::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
228 2 : if (isZero(childDerivs[0]))
229 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
230 2 : return ExpressionTreeNode(new Operation::Multiply(),
231 4 : ExpressionTreeNode(new Operation::Negate(),
232 4 : ExpressionTreeNode(new Operation::Square(),
233 4 : ExpressionTreeNode(new Operation::Csc(), children[0]))),
234 2 : childDerivs[0]);
235 : }
236 :
237 2 : ExpressionTreeNode Operation::Asin::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
238 2 : if (isZero(childDerivs[0]))
239 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
240 2 : return ExpressionTreeNode(new Operation::Multiply(),
241 4 : ExpressionTreeNode(new Operation::Reciprocal(),
242 4 : ExpressionTreeNode(new Operation::Sqrt(),
243 4 : ExpressionTreeNode(new Operation::Subtract(),
244 4 : ExpressionTreeNode(new Operation::Constant(1.0)),
245 4 : ExpressionTreeNode(new Operation::Square(), children[0])))),
246 2 : childDerivs[0]);
247 : }
248 :
249 23 : ExpressionTreeNode Operation::Acos::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
250 23 : if (isZero(childDerivs[0]))
251 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
252 23 : return ExpressionTreeNode(new Operation::Multiply(),
253 46 : ExpressionTreeNode(new Operation::Negate(),
254 46 : ExpressionTreeNode(new Operation::Reciprocal(),
255 46 : ExpressionTreeNode(new Operation::Sqrt(),
256 46 : ExpressionTreeNode(new Operation::Subtract(),
257 46 : ExpressionTreeNode(new Operation::Constant(1.0)),
258 46 : ExpressionTreeNode(new Operation::Square(), children[0]))))),
259 23 : childDerivs[0]);
260 : }
261 :
262 2 : ExpressionTreeNode Operation::Atan::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
263 2 : if (isZero(childDerivs[0]))
264 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
265 2 : return ExpressionTreeNode(new Operation::Multiply(),
266 4 : ExpressionTreeNode(new Operation::Reciprocal(),
267 4 : ExpressionTreeNode(new Operation::AddConstant(1.0),
268 4 : ExpressionTreeNode(new Operation::Square(), children[0]))),
269 2 : childDerivs[0]);
270 : }
271 :
272 54 : ExpressionTreeNode Operation::Atan2::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
273 54 : return ExpressionTreeNode(new Operation::Divide(),
274 108 : ExpressionTreeNode(new Operation::Subtract(),
275 108 : ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
276 108 : ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1])),
277 108 : ExpressionTreeNode(new Operation::Add(),
278 108 : ExpressionTreeNode(new Operation::Square(), children[0]),
279 162 : ExpressionTreeNode(new Operation::Square(), children[1])));
280 : }
281 :
282 28 : ExpressionTreeNode Operation::Sinh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
283 28 : if (isZero(childDerivs[0]))
284 13 : return ExpressionTreeNode(new Operation::Constant(0.0));
285 15 : return ExpressionTreeNode(new Operation::Multiply(),
286 30 : ExpressionTreeNode(new Operation::Cosh(),
287 : children[0]),
288 15 : childDerivs[0]);
289 : }
290 :
291 2 : ExpressionTreeNode Operation::Cosh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
292 2 : if (isZero(childDerivs[0]))
293 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
294 2 : return ExpressionTreeNode(new Operation::Multiply(),
295 4 : ExpressionTreeNode(new Operation::Sinh(),
296 : children[0]),
297 2 : childDerivs[0]);
298 : }
299 :
300 18 : ExpressionTreeNode Operation::Tanh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
301 18 : if (isZero(childDerivs[0]))
302 6 : return ExpressionTreeNode(new Operation::Constant(0.0));
303 12 : return ExpressionTreeNode(new Operation::Multiply(),
304 24 : ExpressionTreeNode(new Operation::Subtract(),
305 24 : ExpressionTreeNode(new Operation::Constant(1.0)),
306 24 : ExpressionTreeNode(new Operation::Square(),
307 24 : ExpressionTreeNode(new Operation::Tanh(), children[0]))),
308 12 : childDerivs[0]);
309 : }
310 :
311 3 : ExpressionTreeNode Operation::Erf::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
312 3 : if (isZero(childDerivs[0]))
313 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
314 3 : return ExpressionTreeNode(new Operation::Multiply(),
315 6 : ExpressionTreeNode(new Operation::Multiply(),
316 6 : ExpressionTreeNode(new Operation::Constant(2.0/sqrt(M_PI))),
317 6 : ExpressionTreeNode(new Operation::Exp(),
318 6 : ExpressionTreeNode(new Operation::Negate(),
319 6 : ExpressionTreeNode(new Operation::Square(), children[0])))),
320 3 : childDerivs[0]);
321 : }
322 :
323 2 : ExpressionTreeNode Operation::Erfc::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
324 2 : if (isZero(childDerivs[0]))
325 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
326 2 : return ExpressionTreeNode(new Operation::Multiply(),
327 4 : ExpressionTreeNode(new Operation::Multiply(),
328 4 : ExpressionTreeNode(new Operation::Constant(-2.0/sqrt(M_PI))),
329 4 : ExpressionTreeNode(new Operation::Exp(),
330 4 : ExpressionTreeNode(new Operation::Negate(),
331 4 : ExpressionTreeNode(new Operation::Square(), children[0])))),
332 2 : childDerivs[0]);
333 : }
334 :
335 265 : ExpressionTreeNode Operation::Step::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
336 265 : return ExpressionTreeNode(new Operation::Delta(),children[0]);
337 : }
338 :
339 3 : ExpressionTreeNode Operation::Delta::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
340 3 : return ExpressionTreeNode(new Operation::Nandelta(), children[0]);
341 : }
342 :
343 3 : ExpressionTreeNode Operation::Nandelta::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
344 3 : return ExpressionTreeNode(new Operation::Nandelta(), children[0]);
345 : }
346 :
347 2 : ExpressionTreeNode Operation::Square::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
348 2 : if (isZero(childDerivs[0]))
349 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
350 2 : return ExpressionTreeNode(new Operation::Multiply(),
351 4 : ExpressionTreeNode(new Operation::MultiplyConstant(2.0),
352 : children[0]),
353 2 : childDerivs[0]);
354 : }
355 :
356 2 : ExpressionTreeNode Operation::Cube::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
357 2 : if (isZero(childDerivs[0]))
358 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
359 2 : return ExpressionTreeNode(new Operation::Multiply(),
360 4 : ExpressionTreeNode(new Operation::MultiplyConstant(3.0),
361 4 : ExpressionTreeNode(new Operation::Square(), children[0])),
362 2 : childDerivs[0]);
363 : }
364 :
365 2 : ExpressionTreeNode Operation::Reciprocal::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
366 2 : if (isZero(childDerivs[0]))
367 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
368 2 : return ExpressionTreeNode(new Operation::Multiply(),
369 4 : ExpressionTreeNode(new Operation::Negate(),
370 4 : ExpressionTreeNode(new Operation::Reciprocal(),
371 4 : ExpressionTreeNode(new Operation::Square(), children[0]))),
372 2 : childDerivs[0]);
373 : }
374 :
375 0 : ExpressionTreeNode Operation::AddConstant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
376 0 : return childDerivs[0];
377 : }
378 :
379 0 : ExpressionTreeNode Operation::MultiplyConstant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
380 0 : if (isZero(childDerivs[0]))
381 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
382 0 : return ExpressionTreeNode(new Operation::MultiplyConstant(value),
383 0 : childDerivs[0]);
384 : }
385 :
386 0 : ExpressionTreeNode Operation::PowerConstant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
387 0 : if (isZero(childDerivs[0]))
388 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
389 0 : return ExpressionTreeNode(new Operation::Multiply(),
390 0 : ExpressionTreeNode(new Operation::MultiplyConstant(value),
391 0 : ExpressionTreeNode(new Operation::PowerConstant(value-1),
392 : children[0])),
393 0 : childDerivs[0]);
394 : }
395 :
396 4 : ExpressionTreeNode Operation::Min::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
397 4 : ExpressionTreeNode step(new Operation::Step(),
398 8 : ExpressionTreeNode(new Operation::Subtract(), children[0], children[1]));
399 20 : return ExpressionTreeNode(new Operation::Select(), {step, childDerivs[1], childDerivs[0]});
400 8 : }
401 :
402 4 : ExpressionTreeNode Operation::Max::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
403 4 : ExpressionTreeNode step(new Operation::Step(),
404 8 : ExpressionTreeNode(new Operation::Subtract(), children[0], children[1]));
405 20 : return ExpressionTreeNode(new Operation::Select(), {step, childDerivs[0], childDerivs[1]});
406 8 : }
407 :
408 13 : ExpressionTreeNode Operation::Abs::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
409 13 : if (isZero(childDerivs[0]))
410 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
411 13 : ExpressionTreeNode step(new Operation::Step(), children[0]);
412 13 : return ExpressionTreeNode(new Operation::Multiply(),
413 : childDerivs[0],
414 26 : ExpressionTreeNode(new Operation::AddConstant(-1),
415 39 : ExpressionTreeNode(new Operation::MultiplyConstant(2), step)));
416 13 : }
417 :
418 2 : ExpressionTreeNode Operation::Floor::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
419 2 : return ExpressionTreeNode(new Operation::Constant(0.0));
420 : }
421 :
422 2 : ExpressionTreeNode Operation::Ceil::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
423 2 : return ExpressionTreeNode(new Operation::Constant(0.0));
424 : }
425 :
426 34 : ExpressionTreeNode Operation::Select::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
427 34 : vector<ExpressionTreeNode> derivChildren;
428 34 : derivChildren.push_back(children[0]);
429 34 : derivChildren.push_back(childDerivs[1]);
430 34 : derivChildren.push_back(childDerivs[2]);
431 68 : return ExpressionTreeNode(new Operation::Select(), derivChildren);
432 34 : }
433 :
434 : #define LEPTON_CONST(x) ExpressionTreeNode(new Operation::Constant(x))
435 : #define LEPTON_OP1(name,x) ExpressionTreeNode(new Operation::name(),x)
436 : #define LEPTON_OP2(name,x,y) ExpressionTreeNode(new Operation::name(),x,y)
437 : #define LEPTON_ADD_CONST(x,y) ExpressionTreeNode(new Operation::AddConstant(x),y)
438 :
439 3 : ExpressionTreeNode Operation::Acot::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
440 : return
441 3 : LEPTON_OP2(Multiply,
442 : LEPTON_OP1(Negate,
443 : LEPTON_OP1(Reciprocal,
444 : LEPTON_ADD_CONST(1.0,
445 : LEPTON_OP1(Square,children[0])
446 : )
447 : )
448 : ),
449 : childDerivs[0]
450 : );
451 : }
452 :
453 2 : ExpressionTreeNode Operation::Asec::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
454 : return
455 2 : LEPTON_OP2(Multiply,
456 : LEPTON_OP1(Reciprocal,
457 : LEPTON_OP2(Multiply,
458 : LEPTON_OP1(Abs,children[0]),
459 : LEPTON_OP1(Sqrt,
460 : LEPTON_OP2(Subtract,
461 : LEPTON_OP1(Square,children[0]),
462 : LEPTON_CONST(1.0)
463 : )
464 : )
465 : )
466 : ),
467 : childDerivs[0]
468 : );
469 : }
470 :
471 2 : ExpressionTreeNode Operation::Acsc::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
472 : return
473 2 : LEPTON_OP2(Multiply,
474 : LEPTON_OP1(Negate,
475 : LEPTON_OP1(Reciprocal,
476 : LEPTON_OP2(Multiply,
477 : LEPTON_OP1(Abs,children[0]),
478 : LEPTON_OP1(Sqrt,
479 : LEPTON_OP2(Subtract,
480 : LEPTON_OP1(Square,children[0]),
481 : LEPTON_CONST(1.0)
482 : )
483 : )
484 : )
485 : )
486 : ),
487 : childDerivs[0]
488 : );
489 : }
490 :
491 2 : ExpressionTreeNode Operation::Coth::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
492 : return
493 2 : LEPTON_OP2(Multiply,
494 : LEPTON_OP2(Subtract,
495 : LEPTON_CONST(1.0),
496 : LEPTON_OP1(Square,
497 : LEPTON_OP1(Coth,children[0])
498 : )
499 : ),
500 : childDerivs[0]
501 : );
502 : }
503 :
504 3 : ExpressionTreeNode Operation::Sech::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
505 : return
506 3 : LEPTON_OP2(Multiply,
507 : LEPTON_OP1(Negate,
508 : LEPTON_OP2(Multiply,
509 : LEPTON_OP1(Tanh,children[0]),
510 : LEPTON_OP1(Sech,children[0])
511 : )
512 : ),
513 : childDerivs[0]
514 : );
515 : }
516 :
517 2 : ExpressionTreeNode Operation::Csch::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
518 : return
519 2 : LEPTON_OP2(Multiply,
520 : LEPTON_OP1(Negate,
521 : LEPTON_OP2(Multiply,
522 : LEPTON_OP1(Coth,children[0]),
523 : LEPTON_OP1(Csch,children[0])
524 : )
525 : ),
526 : childDerivs[0]
527 : );
528 : }
529 :
530 2 : ExpressionTreeNode Operation::Acosh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
531 : return
532 2 : LEPTON_OP2(Multiply,
533 : LEPTON_OP1(Reciprocal,
534 : LEPTON_OP1(Sqrt,
535 : LEPTON_OP2(Subtract,
536 : LEPTON_OP1(Square,children[0]),
537 : LEPTON_CONST(1.0)
538 : )
539 : )
540 : ),
541 : childDerivs[0]
542 : );
543 : }
544 :
545 2 : ExpressionTreeNode Operation::Atanh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
546 : return
547 2 : LEPTON_OP2(Multiply,
548 : LEPTON_OP1(Reciprocal,
549 : LEPTON_OP2(Subtract,
550 : LEPTON_CONST(1.0),
551 : LEPTON_OP1(Square,children[0])
552 : )
553 : ),
554 : childDerivs[0]
555 : );
556 : }
557 :
558 2 : ExpressionTreeNode Operation::Asinh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
559 : return
560 2 : LEPTON_OP2(Multiply,
561 : LEPTON_OP1(Reciprocal,
562 : LEPTON_OP1(Sqrt,
563 : LEPTON_ADD_CONST(1.0,
564 : LEPTON_OP1(Square,children[0])
565 : )
566 : )
567 : ),
568 : childDerivs[0]
569 : );
570 : }
571 :
572 2 : ExpressionTreeNode Operation::Acoth::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
573 : return
574 2 : LEPTON_OP2(Multiply,
575 : LEPTON_OP1(Reciprocal,
576 : LEPTON_OP2(Subtract,
577 : LEPTON_CONST(1.0),
578 : LEPTON_OP1(Square,children[0])
579 : )
580 : ),
581 : childDerivs[0]
582 : );
583 : }
584 :
585 2 : ExpressionTreeNode Operation::Asech::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
586 : return
587 2 : LEPTON_OP2(Multiply,
588 : LEPTON_OP1(Negate,
589 : LEPTON_OP1(Reciprocal,
590 : LEPTON_OP2(Multiply,
591 : children[0],
592 : LEPTON_OP2(Multiply,
593 : LEPTON_ADD_CONST(1.0,
594 : children[0]
595 : ),
596 : LEPTON_OP1(Sqrt,
597 : LEPTON_OP2(Divide,
598 : LEPTON_OP2(Subtract,
599 : LEPTON_CONST(1.0),
600 : children[0]
601 : ),
602 : LEPTON_ADD_CONST(1.0,
603 : children[0]
604 : )
605 : )
606 : )
607 : )
608 : )
609 : )
610 : ),
611 : childDerivs[0]
612 : );
613 : }
614 :
615 2 : ExpressionTreeNode Operation::Acsch::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
616 : return
617 2 : LEPTON_OP2(Multiply,
618 : LEPTON_OP1(Negate,
619 : LEPTON_OP1(Reciprocal,
620 : LEPTON_OP2(Multiply,
621 : LEPTON_OP1(Square,children[0]),
622 : LEPTON_OP1(Sqrt,
623 : LEPTON_ADD_CONST(1.0,
624 : LEPTON_OP1(Reciprocal,
625 : LEPTON_OP1(Square,children[0])
626 : )
627 : )
628 : )
629 : )
630 : )
631 : ),
632 : childDerivs[0]
633 : );
634 : }
635 :
636 : }
|