Symbolic Computing Using Python: Part 1-Basics
Symbolic Computing Using Python: Part 1-Basics
The implementation of algorithms in the Python language using symbolic calculations and an interpreted language is very convenient when solving problems of mathematical modeling of processes and objects.
Based on SymPy library, Python successfully copes with solving equations and systems, integrating and differentiating, calculating limits, expanding in series and summing up the series, simplifying expressions, and solving differential equations and systems.
When using symbolic calculations, the user is given the opportunity to control the operation of the program during its execution by entering any valid functions with a specified number of variables.
I want to immediately warn that these articles do not pretend to be absolutely unique, as they are collected on the basis of materials from various sources, their goal is to show the basics of symbolic calculations.
The very first step to symbol computing is to import the functions of the SymPy module using pip, the Python package management system. If you have coped with this, we will immediately proceed to the declaration of variables.
Notes: To shorten the record in all the following examples, the first line is not listed: from sympy import *
Explicit declaration of character variables
For symbolic calculations using the SymPy module, character variables and functions must be declared as such. In programs for mathematical calculations, such as Mathematica or Maple, variables are immediately treated as symbolic. In Python, they must be declared symbolic, and this can be done in several ways. The easiest way is to use the symbols () or var () functions. The first function returns a reference to a character object in the form of a variable. The second, without assignment, create a character variable.
Code Sample
>>> x, y, a, b = symbols ('x y a b') # four character variables are created, the previous values of the variables are overwritten>>> f = a ** 3 * x + 3 * a ** 2 * x ** 2/2 + a * x ** 3 + x ** 4/4 # the variable f becomes automatically a character>>> type (f)<class 'sympy.core.add.Add'>>>> var ('u, v')(u, v)>>> f = sin (u) ** 2 + tan (v) # the variable f automatically becomes a character>>> type (f)<class 'sympy.core.add.Add'>
The main difference between the symbols () and var () functions is that the first function returns a reference to a character object. For use in the future, it must be assigned a variable. The second, without assignment, create a character variable.In the functions symbols () and var (), you can declare character variables with an index:
Code Sample
>>> x = symbols ('x: 9'); x # range of indices from 0 to 9(x0, x1, x2, x3, x4, x5, x6, x7, x8)>>> x = symbols ('x5: 10'); x # range of indices from 5 to 9(x5, x6, x7, x8, x9)>>> x = var ('x: 9'); x # range of indices from 0 to 9(x0, x1, x2, x3, x4, x5, x6, x7, x8)>>> x = var ('x5: 10'); x # range of indices from 5 to 9(x5, x6, x7, x8, x9)
You can also assign a type and impose restrictions on the character variables directly in the symbols () and var () functions. Sometimes, without such limitations, obvious transformations do not work, for example, compare:
Code Sample
>>> x = symbols ('x', integer = True) # assign an integer type>>> sqrt (x ** 2)Abs (x)>>> x = symbols ('x', positive = True, integer = True)>>> sqrt (x ** 2)x>>> x = symbols ('x')>>> sqrt (x ** 2) # is x if x≥0sqrt (x ** 2)
>>> x = var ('x', integer = True)>>> sqrt (x ** 2)Abs (x)>>> x = var ('x', positive = True, integer = True)>>> sqrt (x ** 2)x>>> x = var ('x')>>> sqrt (x ** 2) # is x if x≥0sqrt (x ** 2)
To create a container for a single character, use the argument seq = True:
>>> symbols('x',seq=True)(x,)
Determination of real values for character variables:
>>> x, y, z = symbols('x,y,z', real=True)>>> x.is_real and y.is_real and z.is_realTrue
S() function
Sometimes, character expressions can be interpreted as numeric Python constants, not SymPy. Therefore, to declare character variables, and also to convert numerical constants to symbolic ones, use the function S (), for example, compare:
>>> expr = x ** 2 + sin (y) + S (10) / 2; exprx ** 2 + sin (y) + 5>>> type (10)<class 'int'>>>> type (S (10)) # character constant ten<class 'sympy.core.numbers.Integer'>
The difference between the Python constant and the symbolic constant is that the symbolic constant can be calculated with a given degree of accuracy, as shown in the following example in comparison with the standard round () function:
z = 1/7; z # calculates the variable z with processor precision0.14285714285714285z1 = S (1) / 7; z11/7z2 = z1.n (30); z2 # calculates the variable z2 with an accuracy of up to 30 significant digits0.142857142857142857142857142857z3 = round (z1.30); z30.14285714285714285
Character names
If you need to use symbolic mathematics all the time in the current session, you can import common symbolic names from the sympy.abc module:
Sample Code
>>> import sympy.abc >>> dir(sympy.abc) ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_clash', '_clash1', '_clash2', 'a', 'alpha', 'b', 'beta', 'c', 'chi', 'd', 'delta', 'division', 'e', 'epsilon', 'eta', 'exec_', 'f', 'g', 'gamma', 'greeks', 'h', 'i', 'iota', 'j', 'k', 'kappa', 'l', 'lamda', 'm', 'mu', 'n', 'nu', 'o', 'omega', 'omicron', 'p', 'phi', 'pi', 'print_function', 'psi', 'q', 'r', 'rho', 's', 'sigma', 'string', 'symbols', 't', 'tau', 'theta', 'u', 'upsilon', 'v', 'w', 'x', 'xi', 'y', 'z', 'zeta']
The variable name from the namespace can be removed with the command del name1, name2, ..:
>>> type(x)<class 'sympy.core.symbol.Symbol'>>>> del x,y >>> xNameError: name 'x' is not defined
To restore the values of standard constants, as well as the names of some functions, you need to reload the sympy module.
>>> from sympy import *
The subs (…) method
It should be remembered that when writing a symbolic expression, it can be automatically simplified, for example:
>>> a,b,c,d,x,y,z,u,v,w = symbols('a b c d x y z u v w') >>> x - z + 20 -z- 15 + 3*sin(pi/2)+2*zx + 8
The subs (…) method is used to calculate a character expression for the given values of variables, for example:
>>> a, x = symbols ('a x')>>> f = a ** 3 * x + 3 * a ** 2 * x ** 2/2 + a * x ** 3 + x ** 4/4>>> f.subs (a, 1) # in the expression f instead of the variable a was substituted onex ** 4/4 + x ** 3 + 3 * x ** 2/2 + x
If you use two arguments in the subs method, they are interpreted as subs (old, new), that is, the old identifier old is replaced with the new one. The argument of the subs () method can be a sequence that must contain pairs (old, new), or it can be a character expression, for example:
>>> a, b, c, d, x, y, z = symbols ('a b c d x y z')>>> f = a * x ** 3 + b * y ** 2 + c * z + d>>> f.subs ([(a, 1), (b, 2), (c, 3), (d, 4)]) # the substitution is made a = 1, b = 2, c = 3, d = 4x ** 3 + 2 * y ** 2 + 3 * z + 4>>> pr = x ** 3 + 4 * x ** 2 + 6 * x + 10>>> pr.subs (x, 1 / x) # substitution of the symbolic expression10 + 6 / x + 4 / x ** 2 + x ** (- 3)
I’m drawing your attention to the following peculiarity of working with variables (symbolic and ordinary Python variables). Let’s execute the following code:
>>> x = 'Hello'>>> pr = x + 'world'>>> pr'Helloworld'>>> x = 'AAA' # assign a new value to the character variable x>>> pr'Helloworld'
Here the rule operates: if the variable has changed, then the expression created earlier containing this variable is not recalculated automatically. This rule also works for regular Python variables.
Operations with fractions
The SymPy module can perform calculations with fractions and bring them to a common denominator, for example, compare:
>>> S(1)/3+S(2)/511/15 >>> 1/3+2/50.7333333333333334
The functions Rational (numerator, denominator) and Integer (…) are used to create rational fractions without decimal rounding:
>>> z=Rational(1, 7)+Rational(2, 5); z 19/35>>> Integer(1)/Integer(5)1/5>>> 1/50.2>>> z=Integer(1)/Integer(5)+Rational(2, 7); z17/35
Rounding Computing
In symbolic calculations, the rule works — if nothing is said, do not make any roundings. See how in the first case Python converts the expression, but leaves the square root in the response record and does not perform any rounding, and in the second, since one of the numbers is given with a decimal point, the result will be approximate:
>>> sqrt (20)2 * sqrt (5)>>> sqrt (20.0) # the expression uses a number with a decimal point4.47213595499958
For any character object, there is an evalf (…) method (evaluate float), which returns its decimal representation:
>>> sqrt (20) .evalf () # The sqrt () function of the sympy4.47213595499958>>> E.evalf ()2.71828182845905
In the evalf ([n, …]) method, you can use the argument that specifies the precision of the result (n = the number of significant digits)
>>> sqrt(20).evalf(30)4.47213595499957939281834733746>>> pi.evalf(20)3.1415926535897932385
You should also always remember that real arithmetic does not return an exact result, compare:
>>> from sympy import *>>> one = S ('one')>>> one = cos (1) ** 2 + sin (1) ** 2>>> one.evalf () # equals 11.00000000000000>>> (one-1) .evalf () # must be 0-0.e-124
If it is known that the result contains an error of calculation, then using the chop = True option of the evalf () method, it can be removed. The very small value of the real or imaginary part of the result, in this case, is replaced by zero. Take the previous example:
>>> (one-1) .evalf () # must be 0-0.e-124>>> (one-1) .evalf (chop = True)0
Infinity
After the first line from sympy import * is executed, the infinity symbol — oo (two letters „o) becomes available, with which you can also perform certain operations:
>>> oo+1oo>>> 1000000<ooTrue>>> 1/oo0
The infinity symbol is mainly used by the functions limit () and integrate () when defining the limits of integration, which we will discuss in one of the following articles.
Conclusion
The symbolic calculations considered in the article differ from numerical methods in that the results can be further investigated, for example, to determine the extrema of functions, solve equations with embedded variables, and so on.