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-2019 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 4761 : static bool isZero(const ExpressionTreeNode& node) {
74 4761 : if (node.getOperation().getId() != Operation::CONSTANT)
75 : return false;
76 2790 : return dynamic_cast<const Operation::Constant&>(node.getOperation()).getValue() == 0.0;
77 : }
78 :
79 202 : double Operation::Erf::evaluate(double* args, const map<string, double>& variables) const {
80 202 : return erf(args[0]);
81 : }
82 :
83 202 : double Operation::Erfc::evaluate(double* args, const map<string, double>& variables) const {
84 202 : return erfc(args[0]);
85 : }
86 :
87 1114 : ExpressionTreeNode Operation::Constant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
88 1114 : return ExpressionTreeNode(new Operation::Constant(0.0));
89 : }
90 :
91 1119 : ExpressionTreeNode Operation::Variable::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
92 1119 : if (variable == name)
93 594 : return ExpressionTreeNode(new Operation::Constant(1.0));
94 525 : 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 577 : ExpressionTreeNode Operation::Add::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
120 577 : if (isZero(childDerivs[0]))
121 124 : return childDerivs[1];
122 453 : if (isZero(childDerivs[1]))
123 360 : return childDerivs[0];
124 93 : return ExpressionTreeNode(new Operation::Add(), childDerivs[0], childDerivs[1]);
125 : }
126 :
127 340 : ExpressionTreeNode Operation::Subtract::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
128 340 : if (isZero(childDerivs[0])) {
129 75 : if (isZero(childDerivs[1]))
130 60 : return ExpressionTreeNode(new Operation::Constant(0.0));
131 15 : return ExpressionTreeNode(new Operation::Negate(), childDerivs[1]);
132 : }
133 265 : if (isZero(childDerivs[1]))
134 66 : return childDerivs[0];
135 199 : return ExpressionTreeNode(new Operation::Subtract(), childDerivs[0], childDerivs[1]);
136 : }
137 :
138 1226 : ExpressionTreeNode Operation::Multiply::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
139 1226 : if (isZero(childDerivs[0])) {
140 902 : if (isZero(childDerivs[1]))
141 313 : return ExpressionTreeNode(new Operation::Constant(0.0));
142 589 : return ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]);
143 : }
144 324 : if (isZero(childDerivs[1]))
145 26 : return ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]);
146 298 : return ExpressionTreeNode(new Operation::Add(),
147 596 : ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]),
148 894 : ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]));
149 : }
150 :
151 128 : ExpressionTreeNode Operation::Divide::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
152 128 : ExpressionTreeNode subexp;
153 128 : if (isZero(childDerivs[0])) {
154 99 : if (isZero(childDerivs[1]))
155 68 : return ExpressionTreeNode(new Operation::Constant(0.0));
156 31 : subexp = ExpressionTreeNode(new Operation::Negate(), ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]));
157 : }
158 29 : else if (isZero(childDerivs[1]))
159 16 : subexp = ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]);
160 : else
161 26 : subexp = ExpressionTreeNode(new Operation::Subtract(),
162 26 : ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
163 39 : ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]));
164 60 : return ExpressionTreeNode(new Operation::Divide(), subexp, ExpressionTreeNode(new Operation::Square(), children[1]));
165 128 : }
166 :
167 111 : ExpressionTreeNode Operation::Power::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
168 111 : return ExpressionTreeNode(new Operation::Add(),
169 222 : ExpressionTreeNode(new Operation::Multiply(),
170 222 : ExpressionTreeNode(new Operation::Multiply(),
171 : children[1],
172 222 : ExpressionTreeNode(new Operation::Power(),
173 222 : children[0], ExpressionTreeNode(new Operation::AddConstant(-1.0), children[1]))),
174 : childDerivs[0]),
175 222 : ExpressionTreeNode(new Operation::Multiply(),
176 222 : ExpressionTreeNode(new Operation::Multiply(),
177 222 : ExpressionTreeNode(new Operation::Log(), children[0]),
178 222 : ExpressionTreeNode(new Operation::Power(), children[0], children[1])),
179 222 : childDerivs[1]));
180 : }
181 :
182 11 : ExpressionTreeNode Operation::Negate::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
183 11 : if (isZero(childDerivs[0]))
184 3 : return ExpressionTreeNode(new Operation::Constant(0.0));
185 8 : return ExpressionTreeNode(new Operation::Negate(), childDerivs[0]);
186 : }
187 :
188 41 : ExpressionTreeNode Operation::Sqrt::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
189 41 : if (isZero(childDerivs[0]))
190 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
191 41 : return ExpressionTreeNode(new Operation::Multiply(),
192 82 : ExpressionTreeNode(new Operation::MultiplyConstant(0.5),
193 82 : ExpressionTreeNode(new Operation::Reciprocal(),
194 82 : ExpressionTreeNode(new Operation::Sqrt(), children[0]))),
195 41 : childDerivs[0]);
196 : }
197 :
198 3 : ExpressionTreeNode Operation::Exp::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
199 3 : if (isZero(childDerivs[0]))
200 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
201 3 : return ExpressionTreeNode(new Operation::Multiply(),
202 6 : ExpressionTreeNode(new Operation::Exp(), children[0]),
203 3 : childDerivs[0]);
204 : }
205 :
206 2 : ExpressionTreeNode Operation::Log::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
207 2 : if (isZero(childDerivs[0]))
208 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
209 2 : return ExpressionTreeNode(new Operation::Multiply(),
210 4 : ExpressionTreeNode(new Operation::Reciprocal(), children[0]),
211 2 : childDerivs[0]);
212 : }
213 :
214 55 : ExpressionTreeNode Operation::Sin::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
215 55 : if (isZero(childDerivs[0]))
216 2 : return ExpressionTreeNode(new Operation::Constant(0.0));
217 53 : return ExpressionTreeNode(new Operation::Multiply(),
218 106 : ExpressionTreeNode(new Operation::Cos(), children[0]),
219 53 : childDerivs[0]);
220 : }
221 :
222 198 : ExpressionTreeNode Operation::Cos::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
223 198 : if (isZero(childDerivs[0]))
224 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
225 198 : return ExpressionTreeNode(new Operation::Multiply(),
226 396 : ExpressionTreeNode(new Operation::Negate(),
227 396 : ExpressionTreeNode(new Operation::Sin(), children[0])),
228 198 : 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 2 : ExpressionTreeNode Operation::Acos::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
284 2 : if (isZero(childDerivs[0]))
285 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
286 2 : return ExpressionTreeNode(new Operation::Multiply(),
287 4 : ExpressionTreeNode(new Operation::Negate(),
288 4 : ExpressionTreeNode(new Operation::Reciprocal(),
289 4 : ExpressionTreeNode(new Operation::Sqrt(),
290 4 : ExpressionTreeNode(new Operation::Subtract(),
291 4 : ExpressionTreeNode(new Operation::Constant(1.0)),
292 4 : ExpressionTreeNode(new Operation::Square(), children[0]))))),
293 2 : 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 8 : ExpressionTreeNode Operation::Atan2::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
307 8 : return ExpressionTreeNode(new Operation::Divide(),
308 16 : ExpressionTreeNode(new Operation::Subtract(),
309 16 : ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
310 16 : ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1])),
311 16 : ExpressionTreeNode(new Operation::Add(),
312 16 : ExpressionTreeNode(new Operation::Square(), children[0]),
313 24 : 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 2 : ExpressionTreeNode Operation::Tanh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
335 2 : if (isZero(childDerivs[0]))
336 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
337 2 : return ExpressionTreeNode(new Operation::Multiply(),
338 4 : ExpressionTreeNode(new Operation::Subtract(),
339 4 : ExpressionTreeNode(new Operation::Constant(1.0)),
340 4 : ExpressionTreeNode(new Operation::Square(),
341 4 : ExpressionTreeNode(new Operation::Tanh(), children[0]))),
342 2 : 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 13 : ExpressionTreeNode Operation::Step::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
370 13 : 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 4 : return ExpressionTreeNode(new Operation::Subtract(),
434 8 : ExpressionTreeNode(new Operation::Multiply(), childDerivs[1], step),
435 8 : ExpressionTreeNode(new Operation::Multiply(), childDerivs[0],
436 16 : ExpressionTreeNode(new Operation::AddConstant(-1), step)));
437 4 : }
438 :
439 4 : ExpressionTreeNode Operation::Max::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
440 4 : ExpressionTreeNode step(new Operation::Step(),
441 8 : ExpressionTreeNode(new Operation::Subtract(), children[0], children[1]));
442 4 : return ExpressionTreeNode(new Operation::Subtract(),
443 8 : ExpressionTreeNode(new Operation::Multiply(), childDerivs[0], step),
444 8 : ExpressionTreeNode(new Operation::Multiply(), childDerivs[1],
445 16 : ExpressionTreeNode(new Operation::AddConstant(-1), step)));
446 4 : }
447 :
448 3 : ExpressionTreeNode Operation::Abs::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
449 3 : if (isZero(childDerivs[0]))
450 0 : return ExpressionTreeNode(new Operation::Constant(0.0));
451 3 : ExpressionTreeNode step(new Operation::Step(), children[0]);
452 3 : return ExpressionTreeNode(new Operation::Multiply(),
453 : childDerivs[0],
454 6 : ExpressionTreeNode(new Operation::AddConstant(-1),
455 9 : ExpressionTreeNode(new Operation::MultiplyConstant(2), step)));
456 3 : }
457 :
458 2 : ExpressionTreeNode Operation::Floor::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
459 2 : return ExpressionTreeNode(new Operation::Constant(0.0));
460 : }
461 :
462 2 : ExpressionTreeNode Operation::Ceil::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
463 2 : return ExpressionTreeNode(new Operation::Constant(0.0));
464 : }
465 :
466 12 : ExpressionTreeNode Operation::Select::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
467 : vector<ExpressionTreeNode> derivChildren;
468 12 : derivChildren.push_back(children[0]);
469 12 : derivChildren.push_back(childDerivs[1]);
470 12 : derivChildren.push_back(childDerivs[2]);
471 24 : return ExpressionTreeNode(new Operation::Select(), derivChildren);
472 12 : }
473 :
474 : #define LEPTON_CONST(x) ExpressionTreeNode(new Operation::Constant(x))
475 : #define LEPTON_OP1(name,x) ExpressionTreeNode(new Operation::name(),x)
476 : #define LEPTON_OP2(name,x,y) ExpressionTreeNode(new Operation::name(),x,y)
477 : #define LEPTON_ADD_CONST(x,y) ExpressionTreeNode(new Operation::AddConstant(x),y)
478 :
479 2 : ExpressionTreeNode Operation::Acot::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
480 : return
481 2 : LEPTON_OP2(Multiply,
482 : LEPTON_OP1(Negate,
483 : LEPTON_OP1(Reciprocal,
484 : LEPTON_ADD_CONST(1.0,
485 : LEPTON_OP1(Square,children[0])
486 : )
487 : )
488 : ),
489 : childDerivs[0]
490 : );
491 : }
492 :
493 2 : ExpressionTreeNode Operation::Asec::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
494 : return
495 2 : LEPTON_OP2(Multiply,
496 : LEPTON_OP1(Reciprocal,
497 : LEPTON_OP2(Multiply,
498 : LEPTON_OP1(Abs,children[0]),
499 : LEPTON_OP1(Sqrt,
500 : LEPTON_OP2(Subtract,
501 : LEPTON_OP1(Square,children[0]),
502 : LEPTON_CONST(1.0)
503 : )
504 : )
505 : )
506 : ),
507 : childDerivs[0]
508 : );
509 : }
510 :
511 2 : ExpressionTreeNode Operation::Acsc::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
512 : return
513 2 : LEPTON_OP2(Multiply,
514 : LEPTON_OP1(Negate,
515 : LEPTON_OP1(Reciprocal,
516 : LEPTON_OP2(Multiply,
517 : LEPTON_OP1(Abs,children[0]),
518 : LEPTON_OP1(Sqrt,
519 : LEPTON_OP2(Subtract,
520 : LEPTON_OP1(Square,children[0]),
521 : LEPTON_CONST(1.0)
522 : )
523 : )
524 : )
525 : )
526 : ),
527 : childDerivs[0]
528 : );
529 : }
530 :
531 2 : ExpressionTreeNode Operation::Coth::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
532 : return
533 2 : LEPTON_OP2(Multiply,
534 : LEPTON_OP2(Subtract,
535 : LEPTON_CONST(1.0),
536 : LEPTON_OP1(Square,
537 : LEPTON_OP1(Coth,children[0])
538 : )
539 : ),
540 : childDerivs[0]
541 : );
542 : }
543 :
544 2 : ExpressionTreeNode Operation::Sech::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
545 : return
546 2 : LEPTON_OP2(Multiply,
547 : LEPTON_OP1(Negate,
548 : LEPTON_OP2(Multiply,
549 : LEPTON_OP1(Tanh,children[0]),
550 : LEPTON_OP1(Sech,children[0])
551 : )
552 : ),
553 : childDerivs[0]
554 : );
555 : }
556 :
557 2 : ExpressionTreeNode Operation::Csch::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
558 : return
559 2 : LEPTON_OP2(Multiply,
560 : LEPTON_OP1(Negate,
561 : LEPTON_OP2(Multiply,
562 : LEPTON_OP1(Coth,children[0]),
563 : LEPTON_OP1(Csch,children[0])
564 : )
565 : ),
566 : childDerivs[0]
567 : );
568 : }
569 :
570 2 : ExpressionTreeNode Operation::Acosh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
571 : return
572 2 : LEPTON_OP2(Multiply,
573 : LEPTON_OP1(Reciprocal,
574 : LEPTON_OP1(Sqrt,
575 : LEPTON_OP2(Subtract,
576 : LEPTON_OP1(Square,children[0]),
577 : LEPTON_CONST(1.0)
578 : )
579 : )
580 : ),
581 : childDerivs[0]
582 : );
583 : }
584 :
585 2 : ExpressionTreeNode Operation::Atanh::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(Reciprocal,
589 : LEPTON_OP2(Subtract,
590 : LEPTON_CONST(1.0),
591 : LEPTON_OP1(Square,children[0])
592 : )
593 : ),
594 : childDerivs[0]
595 : );
596 : }
597 :
598 2 : ExpressionTreeNode Operation::Asinh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
599 : return
600 2 : LEPTON_OP2(Multiply,
601 : LEPTON_OP1(Reciprocal,
602 : LEPTON_OP1(Sqrt,
603 : LEPTON_ADD_CONST(1.0,
604 : LEPTON_OP1(Square,children[0])
605 : )
606 : )
607 : ),
608 : childDerivs[0]
609 : );
610 : }
611 :
612 2 : ExpressionTreeNode Operation::Acoth::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
613 : return
614 2 : LEPTON_OP2(Multiply,
615 : LEPTON_OP1(Reciprocal,
616 : LEPTON_OP2(Subtract,
617 : LEPTON_CONST(1.0),
618 : LEPTON_OP1(Square,children[0])
619 : )
620 : ),
621 : childDerivs[0]
622 : );
623 : }
624 :
625 2 : ExpressionTreeNode Operation::Asech::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
626 : return
627 2 : LEPTON_OP2(Multiply,
628 : LEPTON_OP1(Negate,
629 : LEPTON_OP1(Reciprocal,
630 : LEPTON_OP2(Multiply,
631 : children[0],
632 : LEPTON_OP2(Multiply,
633 : LEPTON_ADD_CONST(1.0,
634 : children[0]
635 : ),
636 : LEPTON_OP1(Sqrt,
637 : LEPTON_OP2(Divide,
638 : LEPTON_OP2(Subtract,
639 : LEPTON_CONST(1.0),
640 : children[0]
641 : ),
642 : LEPTON_ADD_CONST(1.0,
643 : children[0]
644 : )
645 : )
646 : )
647 : )
648 : )
649 : )
650 : ),
651 : childDerivs[0]
652 : );
653 : }
654 :
655 2 : ExpressionTreeNode Operation::Acsch::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
656 : return
657 2 : LEPTON_OP2(Multiply,
658 : LEPTON_OP1(Negate,
659 : LEPTON_OP1(Reciprocal,
660 : LEPTON_OP2(Multiply,
661 : LEPTON_OP1(Square,children[0]),
662 : LEPTON_OP1(Sqrt,
663 : LEPTON_ADD_CONST(1.0,
664 : LEPTON_OP1(Reciprocal,
665 : LEPTON_OP1(Square,children[0])
666 : )
667 : )
668 : )
669 : )
670 : )
671 : ),
672 : childDerivs[0]
673 : );
674 : }
675 :
676 : }
|