1Math::Symbolic(3) User Contributed Perl Documentation Math::Symbolic(3)
2
3
4
6 Math::Symbolic - Symbolic calculations
7
9 use Math::Symbolic;
10
11 my $tree = Math::Symbolic->parse_from_string('1/2 * m * v^2');
12 # Now do symbolic calculations with $tree.
13 # ... like deriving it...
14
15 my ($sub) = Math::Symbolic::Compiler->compile_to_sub($tree);
16
17 my $kinetic_energy = $sub->($mass, $velocity);
18
20 Math::Symbolic is intended to offer symbolic calculation capabilities
21 to the Perl programmer without using external (and commercial)
22 libraries and/or applications.
23
24 Unless, however, some interested and knowledgable developers turn up to
25 participate in the development, the library will be severely limited by
26 my experience in the area. Symbolic calculations are an active field of
27 research in CS.
28
29 There are several ways to construct Math::Symbolic trees. There are no
30 actual Math::Symbolic objects, but rather trees of objects of
31 subclasses of Math::Symbolic. The most general but unfortunately also
32 the least intuitive way of constructing trees is to use the
33 constructors of the Math::Symbolic::Operator, Math::Symbolic::Variable,
34 and Math::Symbolic::Constant classes to create (nested) objects of the
35 corresponding types.
36
37 Furthermore, you may use the overloaded interface to apply the standard
38 Perl operators (and functions, see "OVERLOADED OPERATORS") to existing
39 Math::Symbolic trees and standard Perl expressions.
40
41 Possibly the most convenient way of constructing Math::Symbolic trees
42 is using the builtin parser to generate trees from expressions such as
43 "2 * x^5". You may use the "Math::Symbolic->parse_from_string()" class
44 method for this.
45
46 Of course, you may combine the overloaded interface with the parser to
47 generate trees with Perl code such as "$term * 5 * 'sin(omega*t+phi)'"
48 which will create a tree of the existing tree $term times 5 times the
49 sine of the vars omega times t plus phi.
50
51 There are several modules in the distribution that contain subroutines
52 related to calculus. These are not loaded by Math::Symbolic by default.
53 Furthermore, there are several extensions to Math::Symbolic available
54 from CPAN as separate distributions. Please refer to "SEE ALSO" for an
55 incomplete list of these.
56
57 For example, Math::Symbolic::MiscCalculus come with "Math::Symbolic"
58 and contains routines to compute Taylor Polynomials and the associated
59 errors.
60
61 Routines related to vector calculus such as grad, div, rot, and Jacobi-
62 and Hesse matrices are available through the
63 Math::Symbolic::VectorCalculus module. This module is also able to
64 compute Taylor Polynomials of functions of two variables, directional
65 derivatives, total differentials, and Wronskian Determinants.
66
67 Some basic support for linear algebra can be found in
68 Math::Symbolic::MiscAlgebra. This includes a routine to compute the
69 determinant of a matrix of "Math::Symbolic" trees.
70
71 EXPORT
72 None by default, but you may choose to have the following constants
73 exported to your namespace using the standard Exporter semantics.
74 There are two export tags: :all and :constants. :all will export all
75 constants and the parse_from_string subroutine.
76
77 Constants for transcendetal numbers:
78 EULER (2.7182...)
79 PI (3.14159...)
80
81 Constants representing operator types: (First letter indicates arity)
82 (These evaluate to the same numbers that are returned by the type()
83 method of Math::Symbolic::Operator objects.)
84 B_SUM
85 B_DIFFERENCE
86 B_PRODUCT
87 B_DIVISION
88 B_LOG
89 B_EXP
90 U_MINUS
91 U_P_DERIVATIVE (partial derivative)
92 U_T_DERIVATIVE (total derivative)
93 U_SINE
94 U_COSINE
95 U_TANGENT
96 U_COTANGENT
97 U_ARCSINE
98 U_ARCCOSINE
99 U_ARCTANGENT
100 U_ARCCOTANGENT
101 U_SINE_H
102 U_COSINE_H
103 U_AREASINE_H
104 U_AREACOSINE_H
105 B_ARCTANGENT_TWO
106
107 Constants representing Math::Symbolic term types:
108 (These evaluate to the same numbers that are returned by the term_type()
109 methods.)
110 T_OPERATOR
111 T_CONSTANT
112 T_VARIABLE
113
114 Subroutines:
115 parse_from_string (returns Math::Symbolic tree)
116
118 The package variable $Parser will contain a Parse::RecDescent object
119 that is used to parse strings at runtime.
120
122 parse_from_string
123 This subroutine takes a string as argument and parses it using a
124 Parse::RecDescent parser taken from the package variable
125 $Math::Symbolic::Parser. It generates a Math::Symbolic tree from the
126 string and returns that tree.
127
128 The string may contain any identifiers matching /[a-zA-Z][a-zA-Z0-9_]*/
129 which will be parsed as variables of the corresponding name.
130
131 Please refer to Math::Symbolic::Parser for more information.
132
134 This example demonstrates variable and operator creation using object
135 prototypes as well as partial derivatives and the various ways of
136 applying derivatives and simplifying terms. Furthermore, it shows how
137 to use the compiler for simple expressions.
138
139 use Math::Symbolic qw/:all/;
140
141 my $energy = parse_from_string(<<'HERE');
142 kinetic(mass, velocity, time) +
143 potential(mass, z, time)
144 HERE
145
146 $energy->implement(kinetic => '(1/2) * mass * velocity(time)^2');
147 $energy->implement(potential => 'mass * g * z(t)');
148
149 $energy->set_value(g => 9.81); # permanently
150
151 print "Energy is: $energy\n";
152
153 # Is how does the energy change with the height?
154 my $derived = $energy->new('partial_derivative', $energy, 'z');
155 $derived = $derived->apply_derivatives()->simplify();
156
157 print "Changes with the heigth as: $derived\n";
158
159 # With whatever values you fancy:
160 print "Putting in some sample values: ",
161 $energy->value(mass => 20, velocity => 10, z => 5),
162 "\n";
163
164 # Too slow?
165 $energy->implement(g => '9.81'); # To get rid of the variable
166
167 my ($sub) = Math::Symbolic::Compiler->compile($energy);
168
169 print "This was much faster: ",
170 $sub->(20, 10, 5), # vars ordered alphabetically
171 "\n";
172
174 Since version 0.102, several arithmetic operators have been overloaded.
175
176 That means you can do most arithmetic with Math::Symbolic trees just as
177 if they were plain Perl scalars.
178
179 The following operators are currently overloaded to produce valid
180 Math::Symbolic trees when applied to an expression involving at least
181 one Math::Symbolic object:
182
183 +, -, *, /, **, sqrt, log, exp, sin, cos
184
185 Furthermore, some contexts have been overloaded with particular
186 behaviour: '""' (stringification context) has been overloaded to
187 produce the string representation of the object. '0+' (numerical
188 context) has been overloaded to produce the value of the object. 'bool'
189 (boolean context) has been overloaded to produce the value of the
190 object.
191
192 If one of the operands of an overloaded operator is a Math::Symbolic
193 tree and the over is undef, the module will throw an error unless the
194 operator is a + or a -. If the operator is an addition, the result will
195 be the original Math::Symbolic tree. If the operator is a subtraction,
196 the result will be the negative of the Math::Symbolic tree. Reason for
197 this inconsistent behaviour is that it makes idioms like the following
198 possible:
199
200 @objects = (... list of Math::Symbolic trees ...);
201 $sum += $_ foreach @objects;
202
203 Without this behaviour, you would have to shift the first object into
204 $sum before using it. This is not a problem in this case, but if you
205 are applying some complex calculation to each object in the loop body
206 before adding it to the sum, you'd have to either split the code into
207 two loops or replicate the code required for the complex calculation
208 when shift()ing the first object into $sum.
209
210 Warning: The operator to use for exponentiation is the normal Perl
211 operator for exponentiation "**", NOT the caret "^" which denotes
212 exponentiation in the notation that is recognized by the Math::Symbolic
213 parsers! The "^" operator will be interpreted as the normal binary xor.
214
216 Due to several design decisions, it is probably rather difficult to
217 extend the Math::Symbolic related modules through subclassing. Instead,
218 we chose to make the module extendable through delegation.
219
220 That means you can introduce your own methods to extend
221 Math::Symbolic's functionality. How this works in detail can be read in
222 Math::Symbolic::Custom.
223
224 Some of the extensions available via CPAN right now are listed in the
225 "SEE ALSO" section.
226
228 Math::Symbolic can become quite slow if you use it wrong. To be honest,
229 it can even be slow if you use it correctly. This section is meant to
230 give you an idea about what you can do to have Math::Symbolic compute
231 as quickly as possible. It has some explanation and a couple of 'red
232 flags' to watch out for. We'll focus on two central points: Creation
233 and evaluation.
234
235 CREATING Math::Symbolic TREES
236 Math::Symbolic provides several means of generating Math::Symbolic
237 trees (which are just trees of Math::Symbolic::Constant,
238 Math::Symbolic::Variable and most importantly Math::Symbolic::Operator
239 objects).
240
241 The most convenient way is to use the builtin parser (for example via
242 the "parse_from_string()" subroutine). Problem is, this darn thing
243 becomes really slow for long input strings. This is a known problem for
244 Parse::RecDescent parsers and the Math::Symbolic grammar isn't the
245 shortest either.
246
247 Try to break the formulas you parse into smallish bits. Test the parser
248 performance to see how small they need to be.
249
250 I'll give a simple example where this first advice is gospel:
251
252 use Math::Symbolic qw/parse_from_string/;
253 my @formulas;
254 foreach my $var (qw/x y z foo bar baz/) {
255 my $formula = parse_from_string("sin(x)*$var+3*y^z-$var*x");
256 push @formulas, $formula;
257 }
258
259 So what's wrong here? I'm parsing the whole formula every time. How
260 about this?
261
262 use Math::Symbolic qw/parse_from_string/;
263 my @formulas;
264 my $sin = parse_from_string('sin(x)');
265 my $term = parse_from_string('3*y^z');
266 my $x = Math::Symbolic::Variable->new('x');
267 foreach my $var (qw/x y z foo bar baz/) {
268 my $v = $x->new($var);
269 my $formula = $sin*$var + $term - $var*$x;
270 push @formulas, $formula;
271 }
272
273 I wouldn't call that more legible, but you notice how I moved all the
274 heavy lifting out of the loop. You'll know and do this for normal code,
275 but it's maybe not as obvious when dealing with such code. Now, since
276 this is still slow and - if anything - ugly, we'll do something really
277 clever now to get the best of both worlds!
278
279 use Math::Symbolic qw/parse_from_string/;
280 my @formulas;
281 my $proto = parse_from_string('sin(x)*var+3*y^z-var*x");
282 foreach my $var (qw/x y z foo bar baz/) {
283 my $formula = $proto->new();
284 $formula->implement(var => Math::Symbolic::Variable->new($var));
285 push @formulas, $formula;
286 }
287
288 Notice how we can combine legibility of a clean formula with removing
289 all parsing work from the loop? The "implement()" method is described
290 in detail in Math::Symbolic::Base.
291
292 On a side note: One thing you could do to bring your computer to its
293 knees is to take a function like sin(a*x)*cos(b*x)/e^(2*x), derive that
294 in respect to x a couple of times (like, erm, 50 times?), call
295 "to_string()" on it and parse that string again.
296
297 Almost as convenient as the parser is the overloaded interface. That
298 means, you create a Math::Symbolic object and use it in algebraic
299 expressions as if it was a variable or number. This way, you can even
300 multiply a Math::Symbolic tree with a string and have the string be
301 parsed as a subtree. Example:
302
303 my $x = Math::Symbolic::Variable->new('x');
304 my $formula = $x - sin(3*$x); # $formula will be a M::S tree
305 # or:
306 my $another = $x - 'sin(3*x)'; # have the string parsed as M::S tree
307
308 This, however, turns out to be rather slow, too. It is only about two
309 to five times faster than parsing the formula all the way.
310
311 Use the overloaded interface to construct trees from existing
312 Math::Symbolic objects, but if you need to create new trees quickly,
313 resort to building them by hand.
314
315 Finally, you can create objects using the "new()" constructors from
316 Math::Symbolic::Operator and friends. These can be called in two forms,
317 a long one that gives you complete control (signature for variables,
318 etc.) and a short hand. Even if it is just to protect your finger tips
319 from burning, you should use the short hand whenever possible. It is
320 also slightly faster.
321
322 Use the constructors to build Math::Symbolic trees if you need speed.
323 Using a prototype object and calling "new()" on that may help with the
324 typing effort and should not result in a slow down.
325
326 CRUNCHING NUMBERS WITH Math::Symbolic
327 As with the generation of Math::Symbolic trees, the evaluation of a
328 formula can be done in distinct ways.
329
330 The simplest is, of course, to call "value()" on the tree and have that
331 calculate the value of the formula. You might have to supply some input
332 values to the formula via "value()", but you can also call
333 "set_value()" before using "value()". But that's not faster. For each
334 call to "value()", the computer walks the complete Math::Symbolic tree
335 and evaluates the nodes. If it reaches a leaf, the resulting value is
336 propagated back up the tree. (It's a depth-first search.)
337
338 Calling value() on a Math::Symbolic tree requires walking the tree for
339 every evaluation of the formula. Use this if you'll evaluate the
340 formula only a few times.
341
342 You may be able to make the formula simpler using the Math::Symbolic
343 simplification routines (like "simplify()" or some stuff in the
344 Math::Symbolic::Custom::* modules). Simpler formula are quicker to
345 evaluate. In particular, the simplification should fold constants.
346
347 If you're going to evaluate a tree many times, try simplifying it
348 first.
349
350 But again, your mileage may vary. Test first.
351
352 If the overhead of calling "value()" is unaccepable, you should use the
353 Math::Symbolic::Compiler to compile the tree to Perl code. (Which
354 usually comes in compiled form as an anonymous subroutine.) Example:
355
356 my $tree = parse_from_string('3*x+sin(y)^(z+1)');
357 my $sub = $tree->to_sub(y => 0, x => 1, z => 2);
358 foreach (1..100) {
359 # define $x, $y, and $z
360 my $res = $sub->($y, $x, $z);
361 # faster than $tree->value(x => $x, y => $y, z => $z) !!!
362 }
363
364 Compile your Math::Symbolic trees to Perl subroutines for evaluation in
365 tight loops. The speedup is in the range of a few thousands.
366
367 On an interesting side note, the subroutines compiled from
368 Math::Symbolic trees are just as fast as hand-crafted, "performance
369 tuned" subroutines.
370
371 If you have extremely long formulas, you can choose to even resort to
372 more extreme measures than generating Perl code. You can have
373 Math::Symbolic generate C code for you, compile that and link it into
374 your application at run time. It will then be available to you as a
375 subroutine.
376
377 This is not the most portable thing to do. (You need Inline::C which in
378 turn needs the C compiler that was used to compile your perl.)
379 Therefore, you need to install an extra module for this. It's called
380 Math::Symbolic::Custom::CCompiler. The speed-up for short formulas is
381 only about factor 2 due to the overhead of calling the Perl subroutine,
382 but with sufficiently complicated formulas, you should be able to get a
383 boost up to factor 100 or even 1000.
384
385 For raw execution speed, compile your trees to C code using
386 Math::Symbolic::Custom::CCompiler.
387
388 PROOF
389 In the last two sections, you were told a lot about the performance of
390 two important aspects of Math::Symbolic handling. But eventhough
391 benchmarks are very system dependent and have limited meaning to the
392 general case, I'll supply some proof for what I claimed. This is Perl
393 5.8.6 on linux-2.6.9, x86_64 (Athlon64 3200+).
394
395 In the following tables, value means evaluation using the "value()"
396 method, eval means evaluation of Perl code as a string, sub is a hand-
397 crafted Perl subroutine, compiled is the compiled Perl code, c is the
398 compiled C code. Evaluation of a very simple function yields:
399
400 f(x) = x*2
401 Rate value eval sub compiled c
402 value 17322/s -- -68% -99% -99% -99%
403 eval 54652/s 215% -- -97% -97% -97%
404 sub 1603578/s 9157% 2834% -- -1% -16%
405 compiled 1616630/s 9233% 2858% 1% -- -15%
406 c 1907541/s 10912% 3390% 19% 18% --
407
408 We see that resorting to C is a waste in such simple cases. Compiling
409 to a Perl sub, however is a good idea.
410
411 f(x,y,z) = x*y*z+sin(x*y*z)-cos(x*y*z)
412 Rate value eval compiled sub c
413 value 1993/s -- -88% -100% -100% -100%
414 eval 16006/s 703% -- -97% -97% -99%
415 compiled 544217/s 27202% 3300% -- -2% -56%
416 sub 556737/s 27830% 3378% 2% -- -55%
417 c 1232362/s 61724% 7599% 126% 121% --
418
419 f(x,y,z,a,b) = x^y^tan(a*z)^(y*sin(x^(z*b)))
420 Rate value eval compiled sub c
421 value 2181/s -- -84% -99% -99% -100%
422 eval 13613/s 524% -- -97% -97% -98%
423 compiled 394945/s 18012% 2801% -- -5% -48%
424 sub 414328/s 18901% 2944% 5% -- -46%
425 c 763985/s 34936% 5512% 93% 84% --
426
427 These more involved examples show that using value() can become
428 unpractical even if you're just doing a 2D plot with just a few
429 thousand points. The C routines aren't that much faster, but they
430 scale much better.
431
432 Now for something different. Let's see whether I lied about the
433 creation of Math::Symbolic trees. parse indicates that the parser was
434 used to create the object tree. long indicates that the long syntax of
435 the constructor was used. short... well. proto means that the objects
436 were created from prototypes of the same class. For ol_long and
437 ol_parse, I used the overloaded interface in conjunction with
438 constructors or parsing (a la "$x * 'y+z'").
439
440 f(x) = x
441 Rate parse long short ol_long ol_parse proto
442 parse 258/s -- -100% -100% -100% -100% -100%
443 long 95813/s 37102% -- -33% -34% -34% -35%
444 short 143359/s 55563% 50% -- -2% -2% -3%
445 ol_long 146022/s 56596% 52% 2% -- -0% -1%
446 ol_parse 146256/s 56687% 53% 2% 0% -- -1%
447 proto 147119/s 57023% 54% 3% 1% 1% --
448
449 Obviously, the parser gets blown to pieces, performance-wise. If you
450 want to use it, but cannot accept its tranquility, you can resort to
451 Math::SymbolicX::Inline and have the formulas parsed at compile time.
452 (Which isn't faster, but means that they are available when the program
453 runs.) All other methods are about the same speed. Note, that the ol_*
454 tests are just the same as short here, because in case of "f(x) = x",
455 you cannot make use of the overloaded interface.
456
457 f(x,y,a,b) = x*y(a,b)
458 Rate parse ol_parse ol_long long proto short
459 parse 125/s -- -41% -41% -100% -100% -100%
460 ol_parse 213/s 70% -- -0% -99% -99% -99%
461 ol_long 213/s 70% 0% -- -99% -99% -99%
462 long 26180/s 20769% 12178% 12171% -- -6% -10%
463 proto 27836/s 22089% 12955% 12947% 6% -- -5%
464 short 29148/s 23135% 13570% 13562% 11% 5% --
465
466 f(x,a) = sin(x+a)*3-5*x
467 Rate parse ol_long ol_parse proto short
468 parse 41.2/s -- -83% -84% -100% -100%
469 ol_long 250/s 505% -- -0% -97% -98%
470 ol_parse 250/s 506% 0% -- -97% -98%
471 proto 9779/s 23611% 3819% 3810% -- -3%
472 short 10060/s 24291% 3932% 3922% 3% --
473
474 The picture changes when we're dealing with slightly longer functions.
475 The performance of the overloaded interface isn't that much better than
476 the parser. (Since it uses the parser to convert non-Math::Symbolic
477 operands.) ol_long should, however, be faster than ol_parse. I'll
478 refine the benchmark somewhen. The three other construction methods are
479 still about the same speed. I omitted the long version in the last
480 benchmark because the typing work involved was unnerving.
481
483 New versions of this module can be found on http://steffen-mueller.net
484 or CPAN. The module development takes place on Sourceforge at
485 http://sourceforge.net/projects/math-symbolic/
486
487 The following modules come with this distribution:
488
489 Math::Symbolic::ExportConstants, Math::Symbolic::AuxFunctions
490
491 Math::Symbolic::Base, Math::Symbolic::Operator,
492 Math::Symbolic::Constant, Math::Symbolic::Variable
493
494 Math::Symbolic::Custom, Math::Symbolic::Custom::Base,
495 Math::Symbolic::Custom::DefaultTests,
496 Math::Symbolic::Custom::DefaultMods
497 Math::Symbolic::Custom::DefaultDumpers
498
499 Math::Symbolic::Derivative, Math::Symbolic::MiscCalculus,
500 Math::Symbolic::VectorCalculus, Math::Symbolic::MiscAlgebra
501
502 Math::Symbolic::Parser, Math::Symbolic::Parser::Precompiled,
503 Math::Symbolic::Compiler
504
505 The following modules are extensions on CPAN that do not come with this
506 distribution in order to keep the distribution size reasonable.
507
508 Math::SymbolicX::Inline - (Inlined Math::Symbolic functions)
509
510 Math::Symbolic::Custom::CCompiler (Compile Math::Symbolic trees to C
511 for speed or for use in C code)
512
513 Math::SymbolicX::BigNum (Big number support for the Math::Symbolic
514 parser)
515
516 Math::SymbolicX::Complex (Complex number support for the Math::Symbolic
517 parser)
518
519 Math::Symbolic::Custom::Contains (Find subtrees in Math::Symbolic
520 expressions)
521
522 Math::SymbolicX::ParserExtensionFactory (Generate parser extensions for
523 the Math::Symbolic parser)
524
525 Math::Symbolic::Custom::ErrorPropagation (Calculate Gaussian Error
526 Propagation)
527
528 Math::SymbolicX::Statistics::Distributions (Statistical Distributions
529 as Math::Symbolic functions)
530
531 Math::SymbolicX::NoSimplification (Turns off Math::Symbolic
532 simplifications)
533
535 Please send feedback, bug reports, and support requests to the
536 Math::Symbolic support mailing list: math-symbolic-support at lists dot
537 sourceforge dot net. Please consider letting us know how you use
538 Math::Symbolic. Thank you.
539
540 If you're interested in helping with the development or extending the
541 module's functionality, please contact the developers' mailing list:
542 math-symbolic-develop at lists dot sourceforge dot net.
543
544 List of contributors:
545
546 Steffen Mueller, smueller at cpan dot org
547 Stray Toaster, mwk at users dot sourceforge dot net
548 Oliver Ebenhoeh
549
551 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
552 2013 by Steffen Mueller
553
554 This library is free software; you can redistribute it and/or modify it
555 under the same terms as Perl itself, either Perl version 5.6.1 or, at
556 your option, any later version of Perl 5 you may have available.
557
558
559
560perl v5.34.0 2021-07-22 Math::Symbolic(3)