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