系統學習Sympy
什么是Sympy
Sympy 是一個可以進行符號運算的第三方科學計算庫,數學對象可以被精確的表達,而不是近似值,這也意味着帶有未計算的未知量可以以符號的形式留在數學表達式中。
import sympy
sympy.sqrt(3) #用Sympy表達無理數
sqrt(3)
sympy.init_printing(use_unicode=True) # `use_unicode=True` 是默認值,在程序最前面調用該函數,可以用Unicode將結果打印的更好看。
sympy.sqrt(3) #更好的print 效果
一個更有趣的例子
在Sympy 中,用symbols
來定義變量,也就是說,在使用某個變量前,必須先定義它。
x,y=sympy.symbols('x,y') # symbols('x y') 或者symbols('x,y')
help(sympy.symbols)
Help on function symbols in module sympy.core.symbol:
symbols(names, **args)
Transform strings into instances of :class:`Symbol` class.
:func:`symbols` function returns a sequence of symbols with names taken
from ``names`` argument, which can be a comma or whitespace delimited
string, or a sequence of strings::
>>> from sympy import symbols, Function
>>> x, y, z = symbols('x,y,z')
>>> a, b, c = symbols('a b c')
The type of output is dependent on the properties of input arguments::
>>> symbols('x')
x
>>> symbols('x,')
(x,)
>>> symbols('x,y')
(x, y)
>>> symbols(('a', 'b', 'c'))
(a, b, c)
>>> symbols(['a', 'b', 'c'])
[a, b, c]
>>> symbols(set(['a', 'b', 'c']))
set([a, b, c])
If an iterable container is needed for a single symbol, set the ``seq``
argument to ``True`` or terminate the symbol name with a comma::
>>> symbols('x', seq=True)
(x,)
To reduce typing, range syntax is supported to create indexed symbols.
Ranges are indicated by a colon and the type of range is determined by
the character to the right of the colon. If the character is a digit
then all contiguous digits to the left are taken as the nonnegative
starting value (or 0 if there is no digit left of the colon) and all
contiguous digits to the right are taken as 1 greater than the ending
value::
>>> symbols('x:10')
(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)
>>> symbols('x5:10')
(x5, x6, x7, x8, x9)
>>> symbols('x5(:2)')
(x50, x51)
>>> symbols('x5:10,y:5')
(x5, x6, x7, x8, x9, y0, y1, y2, y3, y4)
>>> symbols(('x5:10', 'y:5'))
((x5, x6, x7, x8, x9), (y0, y1, y2, y3, y4))
If the character to the right of the colon is a letter, then the single
letter to the left (or 'a' if there is none) is taken as the start
and all characters in the lexicographic range *through* the letter to
the right are used as the range::
>>> symbols('x:z')
(x, y, z)
>>> symbols('x:c') # null range
()
>>> symbols('x(:c)')
(xa, xb, xc)
>>> symbols(':c')
(a, b, c)
>>> symbols('a:d, x:z')
(a, b, c, d, x, y, z)
>>> symbols(('a:d', 'x:z'))
((a, b, c, d), (x, y, z))
Multiple ranges are supported; contiguous numerical ranges should be
separated by parentheses to disambiguate the ending number of one
range from the starting number of the next::
>>> symbols('x:2(1:3)')
(x01, x02, x11, x12)
>>> symbols(':3:2') # parsing is from left to right
(00, 01, 10, 11, 20, 21)
Only one pair of parentheses surrounding ranges are removed, so to
include parentheses around ranges, double them. And to include spaces,
commas, or colons, escape them with a backslash::
>>> symbols('x((a:b))')
(x(a), x(b))
>>> symbols('x(:1\,:2)') # or 'x((:1)\,(:2))'
(x(0,0), x(0,1))
All newly created symbols have assumptions set according to ``args``::
>>> a = symbols('a', integer=True)
>>> a.is_integer
True
>>> x, y, z = symbols('x,y,z', real=True)
>>> x.is_real and y.is_real and z.is_real
True
Despite its name, :func:`symbols` can create symbol-like objects like
instances of Function or Wild classes. To achieve this, set ``cls``
keyword argument to the desired type::
>>> symbols('f,g,h', cls=Function)
(f, g, h)
>>> type(_[0])
<class 'sympy.core.function.UndefinedFunction'>
x,y=sympy.symbols('x y')
expr=x+2*y;expr
expr+1
x*expr # 除了 x-x=0,sqr(8)=2*sqrt(2),很多簡化不能自動的進行,這是因為我們有可能希望展開,也有可能希望是多因式的形式,在sympy中,有專門的函數來進行轉化
expanded_expr=sympy.expand(x*expr)
expanded_expr
sympy.factor(expanded_expr)
強大的Sympy
Sympy的強大在於可以進行很多種符號運算,比如簡化表達式,計算導數,積分,極限,解方程,矩陣運算。下面簡單的給幾個例子:
x,y,z,nu=sympy.symbols('x y z nu')
- 對 sin(x)exp(x)求導
sympy.diff(sympy.sin(x)*sympy.exp(x),x)
- 計算exsin(x)+excos(x)的積分
sympy.integrate(sympy.exp(x)*(sympy.sin(x)+sympy.cos(x)),x)
- 計算sin(x2)的無窮積分:
from sympy import *
sympy.integrate(sympy.sin(x**2),(x,-oo,oo))
- sin(x)/x,當x趨近於0時的極限:
sympy.limit(sympy.sin(x)/x,x,0)
- 解方程:x**2-2=0
sympy.solve(x**2-2,x)
- 解微分方程 y''-y=e(t)
y=sympy.Function('y')
t=sympy.symbols('t')
sympy.dsolve(sympy.Eq(y(t).diff(t,t)-y(t),sympy.exp(t)),y(t))
- 找矩陣[[1,2],[2,2]]的特征值:
sympy.Matrix([[1,2],[2,2]]).eigenvals()
- 用LATEX打印cos(x)**2在(0,pi)的積分:
sympy.integrate(sympy.cos(x)**2,(x,0,sympy.pi))
sympy.integrate(sympy.cos(x)**2,x)
sympy.latex(sympy.Integral(sympy.cos(x)**2,(x,0,sympy.pi)))
'\\int_{0}^{\\pi} \\cos^{2}{\\left (x \\right )}\\, dx'
sympy.Integral(sympy.cos(x)**2,(x,0,sympy.pi))
Attention:Integral
is used for the showing purpose,while integrate
is used for evaluating purpose.
下面通過一個小例子來說明在Sympy中的symbols
和Python中的變量的區別:
x=sympy.symbols('x')
expr=x+1
x=2
# expr
type(expr)
sympy.core.add.Add
可以發現expr並不是3,因為x=2只是改變了x的指向,並不影響到expr,如果要想將expr中的x替換為2,可以用expr的subs
方法。
expr.subs(x,2)
等號
在Python中,=
代表賦值,為了不與python沖突,所以等式不能用=
來表示,而==
代表邏輯判斷等於,其返回布爾值,顯然作為表示符號運算中的“等於”,也不合適。在Sympy中,我們用Eq
來表示等式:
sympy.Eq(x+1,4)
為了比較兩個式子是否相等,可以將兩個式子做減法,然后用simplify
方法:
x=sympy.symbols('x')
a=(x+1)**2;a
b=x**2+1+2*x;b
(a-b).simplify()
另外,還有一個equals
方法可以用來判斷,兩個式子是否是相同的:
a.equals(b)
True
^和/
我們用**
來表示指數,而不是^
,這是因為Sympy跟Python保持一致,在Python中,^
表示邏輯運算符‘異或’:
True ^ False
True
True ^ True
False
False ^ False
False
基本操作
這里先簡單介紹下Sympy中的基本操作:
x,y,z=sympy.symbols('x y z')
替換
help(expr.subs)
Help on method subs in module sympy.core.basic:
subs(*args, **kwargs) method of sympy.core.add.Add instance
Substitutes old for new in an expression after sympifying args.
`args` is either:
- two arguments, e.g. foo.subs(old, new)
- one iterable argument, e.g. foo.subs(iterable). The iterable may be
o an iterable container with (old, new) pairs. In this case the
replacements are processed in the order given with successive
patterns possibly affecting replacements already made.
o a dict or set whose key/value items correspond to old/new pairs.
In this case the old/new pairs will be sorted by op count and in
case of a tie, by number of args and the default_sort_key. The
resulting sorted list is then processed as an iterable container
(see previous).
If the keyword ``simultaneous`` is True, the subexpressions will not be
evaluated until all the substitutions have been made.
Examples
========
>>> from sympy import pi, exp, limit, oo
>>> from sympy.abc import x, y
>>> (1 + x*y).subs(x, pi)
pi*y + 1
>>> (1 + x*y).subs({x:pi, y:2})
1 + 2*pi
>>> (1 + x*y).subs([(x, pi), (y, 2)])
1 + 2*pi
>>> reps = [(y, x**2), (x, 2)]
>>> (x + y).subs(reps)
6
>>> (x + y).subs(reversed(reps))
x**2 + 2
>>> (x**2 + x**4).subs(x**2, y)
y**2 + y
To replace only the x**2 but not the x**4, use xreplace:
>>> (x**2 + x**4).xreplace({x**2: y})
x**4 + y
To delay evaluation until all substitutions have been made,
set the keyword ``simultaneous`` to True:
>>> (x/y).subs([(x, 0), (y, 0)])
0
>>> (x/y).subs([(x, 0), (y, 0)], simultaneous=True)
nan
This has the added feature of not allowing subsequent substitutions
to affect those already made:
>>> ((x + y)/y).subs({x + y: y, y: x + y})
1
>>> ((x + y)/y).subs({x + y: y, y: x + y}, simultaneous=True)
y/(x + y)
In order to obtain a canonical result, unordered iterables are
sorted by count_op length, number of arguments and by the
default_sort_key to break any ties. All other iterables are left
unsorted.
>>> from sympy import sqrt, sin, cos
>>> from sympy.abc import a, b, c, d, e
>>> A = (sqrt(sin(2*x)), a)
>>> B = (sin(2*x), b)
>>> C = (cos(2*x), c)
>>> D = (x, d)
>>> E = (exp(x), e)
>>> expr = sqrt(sin(2*x))*sin(exp(x)*x)*cos(2*x) + sin(2*x)
>>> expr.subs(dict([A, B, C, D, E]))
a*c*sin(d*e) + b
The resulting expression represents a literal replacement of the
old arguments with the new arguments. This may not reflect the
limiting behavior of the expression:
>>> (x**3 - 3*x).subs({x: oo})
nan
>>> limit(x**3 - 3*x, x, oo)
oo
If the substitution will be followed by numerical
evaluation, it is better to pass the substitution to
evalf as
>>> (1/x).evalf(subs={x: 3.0}, n=21)
0.333333333333333333333
rather than
>>> (1/x).subs({x: 3.0}).evalf(21)
0.333333333333333314830
as the former will ensure that the desired level of precision is
obtained.
See Also
========
replace: replacement capable of doing wildcard-like matching,
parsing of match, and conditional replacements
xreplace: exact node replacement in expr tree; also capable of
using matching rules
evalf: calculates the given formula to a desired level of precision
expr=sympy.cos(x)+1;expr
expr.subs(x,y)
subs
主要用來做以下兩個事:
- 計算表達式在某個值的結果.
(x+y).subs([(x,1),(y,2)])
- 用子表達式來代替另一個子表達式
expr=x**y;expr
expr=expr.subs(y,x**x);expr
expr=sympy.sin(2*x)+sympy.cos(2*x);expr
sympy.expand_trig(expr)
expr.subs(sympy.sin(2*x),sympy.sin(x)*sympy.cos(x)*2)
有兩點注意事項:(1)subs
返回一個新的表達式,sympy對象都是不可變的,這意味着subs
沒有在原處修改:
expr=sympy.cos(x)
expr.subs(x,0)
(2)傳入list(old1,new1),(old2,new2)來一次性完成多個替換:
(x**3+4*x*y-z).subs([(x,2),(y,4),(z,0)])
將字符串轉化為Sympy表達式
simpify
函數(注意不是simplify
) 用來將字符串轉化為Sympy中的表達式:
str_expr='x**2+3*x-1/2'
sympy.sympify(str_expr)
sympy.sympify(str_expr).subs(x,2)
注意 sympify 用了eval,對於沒初始化的變量,不要用
sympy.sympify('xxx+xyy')
# sympy.sympify('xxx+xyy').subs(xxx,3)
evalf
evalf
主要用來把數值表達式來計算為浮點數
sympy.sqrt(8).evalf()
sympy.sqrt(8).evalf(3) #結果保留3位有效數字
expr=sympy.cos(2*x);expr
expr.subs(x,2)
expr.subs(x,2).evalf()
求解一個數值表達式的某點的具體值,一般是先subs
,然后evalf
,但還有更高效的方法:在evalf
中,傳入subs
=dict(),其中dict是一對symbol:point
.
expr
expr.evalf(subs={x:2})
有時候,由於在計算完成后,存在小於一定程度的精度的四舍五入誤差,可以通過設置chop
為True:
one=sympy.sin(1)**2+sympy.cos(1)**2
one
(one-1).evalf(chop=True)
(one-1).evalf()
lambdify
subs
和evalf
對於計算表達式在一個點的值比較方便,但如果想同時求很多個點,用sympy就會非常慢,這種情況下,使用其他庫,如numpy
,scipy
等就比較方便,而將sympy表達式轉換為函數的就是lambdify
方法,lambdify
就像lambda
,除了它還需要將sympy中的變量轉換為給定庫中的變量:
import numpy as np
a=np.arange(10)
expr=sympy.sin(x)
f=sympy.lambdify(x,expr,'numpy')
f(a)
array([ 0. , 0.84147098, 0.90929743, 0.14112001, -0.7568025 ,
-0.95892427, -0.2794155 , 0.6569866 , 0.98935825, 0.41211849])
help(sympy.lambdify)
Help on function lambdify in module sympy.utilities.lambdify:
lambdify(args, expr, modules=None, printer=None, use_imps=True, dummify=True)
Returns a lambda function for fast calculation of numerical values.
If not specified differently by the user, SymPy functions are replaced as
far as possible by either python-math, numpy (if available) or mpmath
functions - exactly in this order. To change this behavior, the "modules"
argument can be used. It accepts:
- the strings "math", "mpmath", "numpy", "numexpr", "sympy"
- any modules (e.g. math)
- dictionaries that map names of sympy functions to arbitrary functions
- lists that contain a mix of the arguments above, with higher priority
given to entries appearing first.
The default behavior is to substitute all arguments in the provided
expression with dummy symbols. This allows for applied functions (e.g.
f(t)) to be supplied as arguments. Call the function with dummify=False if
dummy substitution is unwanted (and `args` is not a string). If you want
to view the lambdified function or provide "sympy" as the module, you
should probably set dummify=False.
For functions involving large array calculations, numexpr can provide a
significant speedup over numpy. Please note that the available functions
for numexpr are more limited than numpy but can be expanded with
implemented_function and user defined subclasses of Function. If specified,
numexpr may be the only option in modules. The official list of numexpr
functions can be found at:
https://github.com/pydata/numexpr#supported-functions
In previous releases ``lambdify`` replaced ``Matrix`` with ``numpy.matrix``
by default. As of release 1.0 ``numpy.array`` is the default.
To get the old default behavior you must pass in ``[{'ImmutableMatrix':
numpy.matrix}, 'numpy']`` to the ``modules`` kwarg.
>>> from sympy import lambdify, Matrix
>>> from sympy.abc import x, y
>>> import numpy
>>> array2mat = [{'ImmutableMatrix': numpy.matrix}, 'numpy']
>>> f = lambdify((x, y), Matrix([x, y]), modules=array2mat)
>>> f(1, 2)
matrix([[1],
[2]])
Usage
=====
(1) Use one of the provided modules:
>>> from sympy import sin, tan, gamma
>>> from sympy.utilities.lambdify import lambdastr
>>> from sympy.abc import x, y
>>> f = lambdify(x, sin(x), "math")
Attention: Functions that are not in the math module will throw a name
error when the lambda function is evaluated! So this would
be better:
>>> f = lambdify(x, sin(x)*gamma(x), ("math", "mpmath", "sympy"))
(2) Use some other module:
>>> import numpy
>>> f = lambdify((x,y), tan(x*y), numpy)
Attention: There are naming differences between numpy and sympy. So if
you simply take the numpy module, e.g. sympy.atan will not be
translated to numpy.arctan. Use the modified module instead
by passing the string "numpy":
>>> f = lambdify((x,y), tan(x*y), "numpy")
>>> f(1, 2)
-2.18503986326
>>> from numpy import array
>>> f(array([1, 2, 3]), array([2, 3, 5]))
[-2.18503986 -0.29100619 -0.8559934 ]
(3) Use a dictionary defining custom functions:
>>> def my_cool_function(x): return 'sin(%s) is cool' % x
>>> myfuncs = {"sin" : my_cool_function}
>>> f = lambdify(x, sin(x), myfuncs); f(1)
'sin(1) is cool'
Examples
========
>>> from sympy.utilities.lambdify import implemented_function
>>> from sympy import sqrt, sin, Matrix
>>> from sympy import Function
>>> from sympy.abc import w, x, y, z
>>> f = lambdify(x, x**2)
>>> f(2)
4
>>> f = lambdify((x, y, z), [z, y, x])
>>> f(1,2,3)
[3, 2, 1]
>>> f = lambdify(x, sqrt(x))
>>> f(4)
2.0
>>> f = lambdify((x, y), sin(x*y)**2)
>>> f(0, 5)
0.0
>>> row = lambdify((x, y), Matrix((x, x + y)).T, modules='sympy')
>>> row(1, 2)
Matrix([[1, 3]])
Tuple arguments are handled and the lambdified function should
be called with the same type of arguments as were used to create
the function.:
>>> f = lambdify((x, (y, z)), x + y)
>>> f(1, (2, 4))
3
A more robust way of handling this is to always work with flattened
arguments:
>>> from sympy.utilities.iterables import flatten
>>> args = w, (x, (y, z))
>>> vals = 1, (2, (3, 4))
>>> f = lambdify(flatten(args), w + x + y + z)
>>> f(*flatten(vals))
10
Functions present in `expr` can also carry their own numerical
implementations, in a callable attached to the ``_imp_``
attribute. Usually you attach this using the
``implemented_function`` factory:
>>> f = implemented_function(Function('f'), lambda x: x+1)
>>> func = lambdify(x, f(x))
>>> func(4)
5
``lambdify`` always prefers ``_imp_`` implementations to implementations
in other namespaces, unless the ``use_imps`` input parameter is False.
簡化
simplify
sympy有很多方法來進行簡化操作,也有一個通用的方法symplify
,它試圖用各種方法將表達式簡化:
sympy.simplify(sympy.sin(x)**2+sympy.cos(x)**2)
sympy.simplify((x**3+x**2-x-1)/(x**2+2*x+1))
sympy.simplify(sympy.gamma(x)/sympy.gamma(x-2))
simplify
也有一個陷阱,因為它嘗試用各種方法來找到最簡化的結果,而“最簡化的結果”本身就是一個不好定義的術語,比如,我們認為x** 2+2* xy+y** 2的最簡化結果是(x+y)** 2
sympy.simplify(x**2+2*x*y+y**2)
我們並沒有得到我們想得到的(x+y)** 2的結果,針對這種情況,有一個方法factor
,可以進行這樣的簡化。
sympy.factor(x**2+2*x*y+y**2)
simplify
的第二個陷阱是它太慢了,因為它嘗試各種方法來進行簡化,如果我們事先知道最終簡化的方式,最好選擇特定的簡化方法。使用simplify
的最佳時機是交互式使用,來為進一步簡化提供思路。
多項式/有理式函數簡化
expand
expand,顧名思義,是展開:
sympy.expand((x+1)**3)
sympy.expand((x+1)*(x+2)-(x-1)*x)
factor
factor,是因式分解:
sympy.factor(x**2*z+4*x*y*z+4*y**2*z)
對於多項式,factor
是expand
的對立,factor
可以保證每個因子都是不可約的,facor_list
返回更有結構層次的輸出:
sympy.factor_list(x**2+2*x*y+y**2)
help(sympy.factor_list)
Help on function factor_list in module sympy.polys.polytools:
factor_list(f, *gens, **args)
Compute a list of irreducible factors of ``f``.
Examples
========
>>> from sympy import factor_list
>>> from sympy.abc import x, y
>>> factor_list(2*x**5 + 2*x**4*y + 4*x**3 + 4*x**2*y + 2*x + 2*y)
(2, [(x + y, 1), (x**2 + 1, 2)])
sympy.factor(x**2+2*x*y+y**2+y)
sympy.factor_list(x**2+2*x*y*y**2+y)
(2*x**5 + 2*x**4*y + 4*x**3 + 4*x**2*y + 2*x + 2*y)
sympy.factor(2*x**5 + 2*x**4*y + 4*x**3 + 4*x**2*y + 2*x + 2*y)
sympy.factor_list(2*x**5 + 2*x**4*y + 4*x**3 + 4*x**2*y + 2*x + 2*y)
collect
help(sympy.collect)
Help on function collect in module sympy.simplify.radsimp:
collect(expr, syms, func=None, evaluate=None, exact=False, distribute_order_term=True)
Collect additive terms of an expression.
This function collects additive terms of an expression with respect
to a list of expression up to powers with rational exponents. By the
term symbol here are meant arbitrary expressions, which can contain
powers, products, sums etc. In other words symbol is a pattern which
will be searched for in the expression's terms.
The input expression is not expanded by :func:`collect`, so user is
expected to provide an expression is an appropriate form. This makes
:func:`collect` more predictable as there is no magic happening behind the
scenes. However, it is important to note, that powers of products are
converted to products of powers using the :func:`expand_power_base`
function.
There are two possible types of output. First, if ``evaluate`` flag is
set, this function will return an expression with collected terms or
else it will return a dictionary with expressions up to rational powers
as keys and collected coefficients as values.
Examples
========
>>> from sympy import S, collect, expand, factor, Wild
>>> from sympy.abc import a, b, c, x, y, z
This function can collect symbolic coefficients in polynomials or
rational expressions. It will manage to find all integer or rational
powers of collection variable::
>>> collect(a*x**2 + b*x**2 + a*x - b*x + c, x)
c + x**2*(a + b) + x*(a - b)
The same result can be achieved in dictionary form::
>>> d = collect(a*x**2 + b*x**2 + a*x - b*x + c, x, evaluate=False)
>>> d[x**2]
a + b
>>> d[x]
a - b
>>> d[S.One]
c
You can also work with multivariate polynomials. However, remember that
this function is greedy so it will care only about a single symbol at time,
in specification order::
>>> collect(x**2 + y*x**2 + x*y + y + a*y, [x, y])
x**2*(y + 1) + x*y + y*(a + 1)
Also more complicated expressions can be used as patterns::
>>> from sympy import sin, log
>>> collect(a*sin(2*x) + b*sin(2*x), sin(2*x))
(a + b)*sin(2*x)
>>> collect(a*x*log(x) + b*(x*log(x)), x*log(x))
x*(a + b)*log(x)
You can use wildcards in the pattern::
>>> w = Wild('w1')
>>> collect(a*x**y - b*x**y, w**y)
x**y*(a - b)
It is also possible to work with symbolic powers, although it has more
complicated behavior, because in this case power's base and symbolic part
of the exponent are treated as a single symbol::
>>> collect(a*x**c + b*x**c, x)
a*x**c + b*x**c
>>> collect(a*x**c + b*x**c, x**c)
x**c*(a + b)
However if you incorporate rationals to the exponents, then you will get
well known behavior::
>>> collect(a*x**(2*c) + b*x**(2*c), x**c)
x**(2*c)*(a + b)
Note also that all previously stated facts about :func:`collect` function
apply to the exponential function, so you can get::
>>> from sympy import exp
>>> collect(a*exp(2*x) + b*exp(2*x), exp(x))
(a + b)*exp(2*x)
If you are interested only in collecting specific powers of some symbols
then set ``exact`` flag in arguments::
>>> collect(a*x**7 + b*x**7, x, exact=True)
a*x**7 + b*x**7
>>> collect(a*x**7 + b*x**7, x**7, exact=True)
x**7*(a + b)
You can also apply this function to differential equations, where
derivatives of arbitrary order can be collected. Note that if you
collect with respect to a function or a derivative of a function, all
derivatives of that function will also be collected. Use
``exact=True`` to prevent this from happening::
>>> from sympy import Derivative as D, collect, Function
>>> f = Function('f') (x)
>>> collect(a*D(f,x) + b*D(f,x), D(f,x))
(a + b)*Derivative(f(x), x)
>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), f)
(a + b)*Derivative(f(x), x, x)
>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x), exact=True)
a*Derivative(f(x), x, x) + b*Derivative(f(x), x, x)
>>> collect(a*D(f,x) + b*D(f,x) + a*f + b*f, f)
(a + b)*f(x) + (a + b)*Derivative(f(x), x)
Or you can even match both derivative order and exponent at the same time::
>>> collect(a*D(D(f,x),x)**2 + b*D(D(f,x),x)**2, D(f,x))
(a + b)*Derivative(f(x), x, x)**2
Finally, you can apply a function to each of the collected coefficients.
For example you can factorize symbolic coefficients of polynomial::
>>> f = expand((x + a + 1)**3)
>>> collect(f, x, factor)
x**3 + 3*x**2*(a + 1) + 3*x*(a + 1)**2 + (a + 1)**3
.. note:: Arguments are expected to be in expanded form, so you might have
to call :func:`expand` prior to calling this function.
See Also
========
collect_const, collect_sqrt, rcollect
expr=x*y+x-3+2*x**2-z*x**2+x**3;expr
sympy.collect(expr,x)
collect
經常與coeff
一起使用,來給出第n次冪的系數:
sympy.collect(expr,x).coeff(x,2)
cancle
通分及約分:
sympy.cancel((x**2+2*x+1)/(x**2+x))
expr=1/x+(3*x/2-2)/(x-4);expr
sympy.cancel(expr)
apart
expr = (4*x**3 + 21*x**2 + 10*x + 12)/(x**4 + 5*x**3 + 5*x**2 + 4*x);expr
sympy.apart(expr)
help(sympy.apart)
Help on function apart in module sympy.polys.partfrac:
apart(f, x=None, full=False, **options)
Compute partial fraction decomposition of a rational function.
Given a rational function ``f``, computes the partial fraction
decomposition of ``f``. Two algorithms are available: One is based on the
undertermined coefficients method, the other is Bronstein's full partial
fraction decomposition algorithm.
The undetermined coefficients method (selected by ``full=False``) uses
polynomial factorization (and therefore accepts the same options as
factor) for the denominator. Per default it works over the rational
numbers, therefore decomposition of denominators with non-rational roots
(e.g. irrational, complex roots) is not supported by default (see options
of factor).
Bronstein's algorithm can be selected by using ``full=True`` and allows a
decomposition of denominators with non-rational roots. A human-readable
result can be obtained via ``doit()`` (see examples below).
Examples
========
>>> from sympy.polys.partfrac import apart
>>> from sympy.abc import x, y
By default, using the undetermined coefficients method:
>>> apart(y/(x + 2)/(x + 1), x)
-y/(x + 2) + y/(x + 1)
The undetermined coefficients method does not provide a result when the
denominators roots are not rational:
>>> apart(y/(x**2 + x + 1), x)
y/(x**2 + x + 1)
You can choose Bronstein's algorithm by setting ``full=True``:
>>> apart(y/(x**2 + x + 1), x, full=True)
RootSum(_w**2 + _w + 1, Lambda(_a, (-2*_a*y/3 - y/3)/(-_a + x)))
Calling ``doit()`` yields a human-readable result:
>>> apart(y/(x**2 + x + 1), x, full=True).doit()
(-y/3 - 2*y*(-1/2 - sqrt(3)*I/2)/3)/(x + 1/2 + sqrt(3)*I/2) + (-y/3 -
2*y*(-1/2 + sqrt(3)*I/2)/3)/(x + 1/2 - sqrt(3)*I/2)
See Also
========
apart_list, assemble_partfrac_list
三角幾何簡化
sympy與Python保持一致,在三角函數名前加a
,就是相應的反三角函數
sympy.acos(x)
sympy.cos(sympy.acos(x))
sympy.asin(1)
trigsimp
sympy.trigsimp(sympy.sin(x)**2+sympy.cos(x)**2)
sympy.trigsimp(sympy.sin(x)**4-2*sympy.cos(x)**2*sympy.sin(x)**2+sympy.cos(x)**4)
sympy.trigsimp(sympy.cosh(x)**2+sympy.sinh(x)**2)
sympy.trigsimp(sympy.sinh(x)/sympy.cosh(x))
expand_trig
sympy.expand_trig(sympy.sin(2*x))
sympy.expand_trig(sympy.tan(2*x))
expand_trig
是試圖把三角函數表達式變大,trigsimp
是試圖將三角函數表達式變小。
Powers
先看3個等式:
-
- xa*xb=x^(a+b)
- 2.xa*ya=(xy)^a
- 3.(xa)b=x^(ab)
等式1總是成立的;
等式2並不是總是成立的,比如,x=y=-1,a=1/2,左邊為-1,右邊為1
等式3也並不是總成立的,比如,x=-1,a=2,b=1/2,左邊為-1,右邊為1
如果冪表達式並不總是正確的,Sympy就不會進行簡化,我們需要對符號進行做一些假定。
- Sympy符號默認是復數,這意味着不會對一些給定的表達式進行簡化,除非它適合所有的復數。
- 符號可以通過傳入
symbols
的參數來完成一些假定,對於本部分剩余的地方,我們假定x,y是正數,a,b是實數,z,t,c是任意的復數,來看看能得到什么結果。
x,y=sympy.symbols('x y',positive=True)
a,b=sympy.symbols('a b',real=True)
z,t,c=sympy.symbols('z t c')
需要注意的是,sqrt(x)
是x**Rational(1,2)
的快捷方式:
sympy.sqrt(x)==x**sympy.Rational(1,2)
True
powsimp
該方法施加等式1,等式2
sympy.powsimp(x**a*x**b)
sympy.powsimp(x**a*y**a)
注意,powsimp不會對不合法的結果做簡化,如
sympy.powsimp(t**c*z**c)
如果要強行進行簡化,設置force=True
:
sympy.powsimp(t**c*z**c,force=True)
sympy.powsimp(z**2*t**2)
expand_power_exp/expand_power_base
sympy.expand_power_exp(x**(a+b)) # 簡化指數
help(sympy.expand_power_exp)
Help on function expand_power_exp in module sympy.core.function:
expand_power_exp(expr, deep=True)
Wrapper around expand that only uses the power_exp hint.
See the expand docstring for more information.
Examples
========
>>> from sympy import expand_power_exp
>>> from sympy.abc import x, y
>>> expand_power_exp(x**(y + 2))
x**2*x**y
sympy.expand_power_exp((x*y)**a) # 簡化指數
sympy.expand_power_base((x*y)**a) # 簡化底
就像powsimp
,一樣,如果非法,expand_power_base不會進行簡化:
sympy.expand_power_base((z*t)**c)
但它也有force=True
:
sympy.expand_power_base((z*t)**c,force=True)
powdenest
help(sympy.powdenest)
Help on function powdenest in module sympy.simplify.powsimp:
powdenest(eq, force=False, polar=False)
Collect exponents on powers as assumptions allow.
Given ``(bb**be)**e``, this can be simplified as follows:
* if ``bb`` is positive, or
* ``e`` is an integer, or
* ``|be| < 1`` then this simplifies to ``bb**(be*e)``
Given a product of powers raised to a power, ``(bb1**be1 *
bb2**be2...)**e``, simplification can be done as follows:
- if e is positive, the gcd of all bei can be joined with e;
- all non-negative bb can be separated from those that are negative
and their gcd can be joined with e; autosimplification already
handles this separation.
- integer factors from powers that have integers in the denominator
of the exponent can be removed from any term and the gcd of such
integers can be joined with e
Setting ``force`` to True will make symbols that are not explicitly
negative behave as though they are positive, resulting in more
denesting.
Setting ``polar`` to True will do simplifications on the Riemann surface of
the logarithm, also resulting in more denestings.
When there are sums of logs in exp() then a product of powers may be
obtained e.g. ``exp(3*(log(a) + 2*log(b)))`` - > ``a**3*b**6``.
Examples
========
>>> from sympy.abc import a, b, x, y, z
>>> from sympy import Symbol, exp, log, sqrt, symbols, powdenest
>>> powdenest((x**(2*a/3))**(3*x))
(x**(2*a/3))**(3*x)
>>> powdenest(exp(3*x*log(2)))
2**(3*x)
Assumptions may prevent expansion:
>>> powdenest(sqrt(x**2))
sqrt(x**2)
>>> p = symbols('p', positive=True)
>>> powdenest(sqrt(p**2))
p
No other expansion is done.
>>> i, j = symbols('i,j', integer=True)
>>> powdenest((x**x)**(i + j)) # -X-> (x**x)**i*(x**x)**j
x**(x*(i + j))
But exp() will be denested by moving all non-log terms outside of
the function; this may result in the collapsing of the exp to a power
with a different base:
>>> powdenest(exp(3*y*log(x)))
x**(3*y)
>>> powdenest(exp(y*(log(a) + log(b))))
(a*b)**y
>>> powdenest(exp(3*(log(a) + log(b))))
a**3*b**3
If assumptions allow, symbols can also be moved to the outermost exponent:
>>> i = Symbol('i', integer=True)
>>> powdenest(((x**(2*i))**(3*y))**x)
((x**(2*i))**(3*y))**x
>>> powdenest(((x**(2*i))**(3*y))**x, force=True)
x**(6*i*x*y)
>>> powdenest(((x**(2*a/3))**(3*y/i))**x)
((x**(2*a/3))**(3*y/i))**x
>>> powdenest((x**(2*i)*y**(4*i))**z, force=True)
(x*y**2)**(2*i*z)
>>> n = Symbol('n', negative=True)
>>> powdenest((x**i)**y, force=True)
x**(i*y)
>>> powdenest((n**i)**x, force=True)
(n**i)**x
sympy.powdenest((x**a)**b)
sympy.powdenest((z*a)**b)
sympy
<module 'sympy' from 'E:\\software\\Anaconda\\lib\\site-packages\\sympy\\__init__.py'>
指數和對數
先看2個等式:
- log(xy)=lob(x)+log(y)
- log(x^n)=nlog(x)
兩個等式都不是總成立的,然而,如果x,y是正數,且n為實數,則等式成立。
在sympy中,log
是自然對數,也就是ln
,為了防止忘了,sympy自動提供log
=ln
.
sympy.log(x)
sympy.ln(x)
x,y=sympy.symbols('x y',positive=True)
n=sympy.symbols('n',real=True)
像之前的t,z,沒有任何假定。
expand_log
用expand_log
來對兩個等式,從左到右的計算:
sympy.expand_log(sympy.log(x*y))
sympy.expand_log(sympy.log(x/y))
sympy.log(x/y)
sympy.expand_log(sympy.log(x**2))
sympy.expand_log(sympy.log(x**n))
sympy.expand_log(sympy.log(t*z))
當然,expand_log也有個force=True設置,可以強制的進行log 展開:
sympy.expand_log(sympy.log(t*z),force=True)
logcombine
對這兩個等式,從右往左計算:
sympy.logcombine(sympy.log(x)+sympy.log(y))
sympy.logcombine(sympy.log(x)-sympy.log(y))
同樣,logcombine
也有force=True的設置
特殊函數
sympy有很多個特殊函數,從組合數學到數學物理方程,詳盡的描述見https://docs.sympy.org/latest/modules/functions/index.html#functions-contents
首先定義x,y,z,k,m,l,對它們不做任何假定。
x,y,z,k,m,l=sympy.symbols('x y z k m l')
n的階乘用fatorial(n)
:
sympy.factorial(n)
二項式系數方程,binominal(n,k)
sympy.binomial(n,k)
gamma函數,gamma(z)
sympy.gamma(z)
重寫rewrite
對於特殊函數的常規操作是重寫,這實際上對於sympy中所有函數都成立,並不僅僅局限於特殊函數,用expr.rewrite(function)
來完成重寫。
sympy.tan(x).rewrite(sympy.sin)
sympy.factorial(x).rewrite(sympy.gamma)
expand_func
sympy.expand_func(sympy.gamma(3+x))
combsimp
n,k=sympy.symbols('n k',integer=True)
sympy.combsimp(sympy.factorial(n)/sympy.factorial(n-3))
sympy.combsimp(sympy.binomial(n+1,k+1)/sympy.binomial(n,k))
例子(連續分式)
def list_to_fac(l):
expr=sympy.Integer(0)
for i in reversed(l[1:]):
expr+=i
expr=1/expr
return l[0]+expr
list_to_fac([x,y,z])
我們在list_to_fac
中用了sympy.Integer(0),所以就算傳入list_to_fac的列表中都是Python int,最后返回結果還是sympy 對象。
list_to_fac([1,2,3,4])
sysm=sympy.symbols('a0:5')
a0, a1, a2, a3, a4 = sysm
fac=list_to_fac(sysm);fac
sympy.cancel(fac)
fac=sympy.cancel(fac)
fac
l=[]
fac=sympy.apart(fac,a1);fac
l.append(a0)
fac = 1/(fac - a0);fac
fac=sympy.apart(fac,a1);fac
l.append(a1)
微積分
導數
sympy.diff(x**2,x)
diff
可以一次性求解多階導數,比如求解n階導數,可以將n個x傳入diff中或者將x,n傳入diff中:
sympy.diff(sympy.exp(x**2),x,2)
sympy.diff(sympy.exp(x**2),x,x,)
diff
也可以同時對多個變量求導,將需要求導的變量及次數依次輸入:
expr=sympy.exp(x*y*z)
expr
expr.diff(x,y,y,z,z,z,z)
用類Derivative
來表示沒有計算的導數,偏導數,與diff有相同的語法:
sympy.Derivative(expr,x,y,2,z,4)
計算用類Derivative
表示的導數,偏導數,用方法doit()
:
sympy.Derivative(expr,x,y,2,z,4).doit()
不確定是幾階導數的可以用(x,n)元組傳入diff:
m,n,a,b=sympy.symbols('m n a b')
expr=(a*x+b)**m;expr
# sympy.diff(expr,(x,n)) # go wrong?!
積分
用integrate
來進行積分計算,包括定積分,不定積分,計算不定積分,只要把自變量傳入進去就可以了。
sympy.integrate(sympy.cos(x),x)
如果要求定積分,傳入(integration_variable, lower_limit, upper_limit):
from sympy import *
sympy.integrate(sympy.exp(-x),(x,0,oo))
sympy.integrate(sympy.exp(-x**2-y**2),(x,-oo,+oo),(y,-oo,oo))
如果integrate
不能計算出一個積分值,會返回一個沒有被計算的Integrate
對象。
expr=sympy.integrate(x**x,x)
expr
像Derivative
一樣,Integraral
返回一個沒被計算的積分對象,然后可以用doit
來計算。
expr=sympy.Integral(sympy.log(x)**2,x)
expr
expr.doit()
integ = Integral((x**4 + x**2*exp(x) - x**2 - 2*x*exp(x) - 2*x -
exp(x))*exp(x)/((x - 1)**2*(x + 1)**2*(exp(x) + 1)), x)
integ
integ.doit()
integ = Integral(sin(x**2), x);integ
integ.doit()
integ = Integral(x**y*exp(-x), (x, 0, oo));integ
integ.doit()
最后一個返回了一個Piecewise
(分段函數)對象
求極限
求極限的基本語法:
limit(f(x), x, x0)
limit(sin(x)/x, x, 0)
當表達式在某點出奇異點時候,應該用limit
,而不是subs
expr=x**2/exp(x);expr
expr.subs(x,oo)
limit(expr,x,oo)
limit(expr,x,-oo)
極限也有自己的對象,Limit
,可以用doit
來對該對象進行計算:
expr=Limit((cos(x)-1)/x,x,0);expr
expr.doit()
如果僅僅要計算某一邊的極限,最后再傳入'+',或者'-'即可:
limit(1/x,x,0,'+')
limit(1/x,x,0,'-')
級數展開
sympy可以在某點對一個函數進行非對稱級數展開。如,為了計算f(x)在x=x0處,x^n階的展開,用f(x).series(x,x0,n)
,x0和n可以省略,這種情況,默認x0=0,n=6.
expr=exp(sin(x));expr
expr.series(x,0,4)
如果不保留高階項,用removeO
(Big O):
expr.series(x,0,4).removeO()
有限差分
用differentiate_finite
來求有限差分:
f,g=sympy.symbols('f g',cls=Function)
differentiate_finite(f(x)*g(x))
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-210-faa797f23aa1> in <module>()
----> 1 differentiate_finite(f(x)*g(x))
NameError: name 'differentiate_finite' is not defined
設置參數evaluate=True
來展開中間導數:
differentiate_finite(f(x)*g(x),evaluate=True)
如果已經有了Derivative
對象,可以用as_finite_difference
方法,來得到任意階的近似的導數。
f=Function('f')
dfdx=f(x).diff(x)
dfdx
dfdx.as_finite_difference()
這里,用最少的點(對於1階導數是2個點),在x處近似的得到f(x)的導數;
f(x)
dfdx=f(x).diff(x,2);dfdx
h=symbols('h')
pp=dfdx.as_finite_difference([-3*h,h,2*h]);pp
help(dfdx.as_finite_difference)
finite_diff_weights(2, [-3, -1, 2], 0)[-1][-1]
解方程
在sympy中,等號用Eq
表示:
Eq(x,y)
然而,還有更簡單的方法表示等式,在sympy中,凡是不是用Eq的表達式,自動的都認為是等於0:
solveset(Eq(x**2,1),x)
solveset(Eq(x**2-1),x)
solveset(Eq(x**2-1,0),x)
solveset(x**2-1,x)
解代數方程
解代數方程的主要方法是solveset
,語法為:solveset(equation, variable=None, domain=S.Complexes)
,其中equation可以是Eq對象,或者默認為0的表達式。
注意還有個solve
方程,語法為:solve(equations, variables) ,還是建議先用solveset
。
solveset
返回值是 FiniteSet
, Interval
或者 ImageSet
對象:
solveset(x**2 - x, x)
solveset(x - x, x, domain=S.Reals)
solveset(sin(x) - 1, x, domain=S.Reals)
solveset(exp(x), x)
solveset(cos(x) - x, x)
在代數方程中,如果是線性方程,現在用linsolve
,以后的版本可能會直接用solveset
:
help(linsolve)
- 方程形式的列表:
linsolve([x + y + z - 1, x + y + 2*z - 3 ], (x, y, z))
- 增廣矩陣形式:
linsolve(Matrix(([1, 1, 1, 1], [1, 1, 2, 3])), (x, y, z))
- A * x = b形式
M = Matrix(((1, 1, 1, 1), (1, 1, 2, 3)))
M
system = A, b = M[:, :-1], M[:, -1]
system
linsolve(system, x, y, z)
在模塊solveset
中,用nonlinsolve
來求解非線性方程組:
- 僅有實數解
a, b, c, d = symbols('a, b, c, d', real=True)
nonlinsolve([a**2 + a, a - b], [a, b]) # that means,a**2+a=0;a-b=0
- 僅有復數解
nonlinsolve([x**2 + 1, y**2 + 1], [x, y])
help(nonlinsolve)
- 既有實根也有復數根
system = [x**2 - 2*y**2 -2, x*y - 2]
vars = [x, y]
nonlinsolve(system, vars)
- 無限個解
nonlinsolve([x*y, x*y - x], [x, y])
注意:
(1):解的順序對應了symbols的順序
(2)當前,nonlinsolve
不返回以LambertW形式的解
solve([x**2 - y**2/exp(x)], [x, y], dict=True)
solve([sin(x + y), cos(x - y)], [x, y]) #可用於這種情況,但不會給出全部解
solveset
只返回零點一次,用roots
可以得到零點及相應出現的次數。
solveset(x**2,x)
roots(x**2,x)
解微分方程
用dsolve
解微分方程。
f, g = symbols('f g', cls=Function)
f(x).diff(x,2)
diffeq=Eq(f(x).diff(x,2)-2*f(x).diff(x)+f(x),sin(x));diffeq
dsolve(diffeq,f(x))
小總結
關於各種solve的傳入參數,第一個是方程(組),第二個是相應的未知量(有必要寫出來,它的順序決定了求解值的順序)
矩陣
用Matrix
對象來表示矩陣。
M=Matrix([[1,2,3],[2,3,4]]);M
為了簡便,只傳入一個列表,M即代表是列向量。
Matrix([1,2,3])
N = Matrix([0, 1, 1])
M*N
關於sympy中的矩陣一個比較重要的點是:不像sympy中其他對象,Matrix是可變的。這意味着,它們可以原地改變。這樣的一個缺點是,它不能用在需要是不可變對象的地方,比如在sympy表達式中,如果需要一個Matrix的不變的版本,用ImmutableMatrix
.
基本操作
- shape
M
M.shape
- 查詢行列
M.row(0)
M.col(1)
- 增刪行列
刪除一行或者一列,用row_del
,column_del
,這些操作都發生在原地。
M
M.col_del(0)
M
M.row_del(1)
M
增加行列,用row_insert
,col_insert
,這些操作不會在原地進行。
M.row_insert(1,Matrix([[0,1]]))
---------------------------------------------------------------------------
ShapeError Traceback (most recent call last)
<ipython-input-270-8ea1d073fb8d> in <module>()
----> 1 M.row_insert(1,Matrix([[0,1]]))
E:\software\Anaconda\lib\site-packages\sympy\matrices\matrices.py in row_insert(self, pos, mti)
4039 if self.cols != mti.cols:
4040 raise ShapeError(
-> 4041 "`self` and `mti` must have the same number of columns.")
4042
4043 newmat = self.zeros(self.rows + mti.rows, self.cols)
ShapeError: `self` and `mti` must have the same number of columns.
M
M=M.row_insert(1,Matrix([[0,1]]))
M = M.col_insert(0, Matrix([1, -2])) # 這里,列向量,只需要一個list,不用嵌套。
---------------------------------------------------------------------------
ShapeError Traceback (most recent call last)
<ipython-input-280-3d900b7dc745> in <module>()
----> 1 M = M.col_insert(0, Matrix([1, -2])) # 這里,列向量,只需要一個list,不用嵌套。
E:\software\Anaconda\lib\site-packages\sympy\matrices\matrices.py in col_insert(self, pos, mti)
4070 """
4071 if pos == 0:
-> 4072 return mti.row_join(self)
4073 elif pos < 0:
4074 pos = self.cols + pos
E:\software\Anaconda\lib\site-packages\sympy\matrices\matrices.py in row_join(self, rhs)
3966 if self.rows != rhs.rows:
3967 raise ShapeError(
-> 3968 "`self` and `rhs` must have the same number of rows.")
3969
3970 from sympy.matrices import MutableMatrix
ShapeError: `self` and `rhs` must have the same number of rows.
M
除非有特殊聲明,否則下面的操作都不會在原地進行,通常,不在原地進行的操作會返回一個新的對象,在原地操作會返回None.
基本操作
M = Matrix([[1, 3], [-2, 3]])
N = Matrix([[0, 3], [0, 7]])
M
N
M+N
M*2
M**2
M*M # 與上式一樣
M**-1
M**-1*M
M.T
Matrix constructor
eye(3)
eye(4)
zeros(2,3)
ones(2,3)
對角陣用diag
,其參數既可以是數字也可以是矩陣,剩下的是0.
diag(1,2,3)
diag(-1,ones(2,3),Matrix([2,3,4]))
高級方法
- 行列式,用
det
M = Matrix([[1, 0, 1], [2, -1, 3], [4, 3, 2]])
M
M.det()
- RREF
help(M.rref)
Help on method rref in module sympy.matrices.matrices:
rref(iszerofunc=<function _iszero at 0x000001AAC40281E0>, simplify=False) method of sympy.matrices.dense.MutableDenseMatrix instance
Return reduced row-echelon form of matrix and indices of pivot vars.
To simplify elements before finding nonzero pivots set simplify=True
(to use the default SymPy simplify function) or pass a custom
simplify function.
Examples
========
>>> from sympy import Matrix
>>> from sympy.abc import x
>>> m = Matrix([[1, 2], [x, 1 - 1/x]])
>>> m.rref()
(Matrix([
[1, 0],
[0, 1]]), [0, 1])
rref 就是reduced row echelon form,即簡化列梯形矩陣,返回值第一個是經過線性變換后的矩陣,第二個元組,包含了對角的列編號。
M = Matrix([[1, 0, 1, 3], [2, 3, 4, 7], [-1, -3, -3, -4]])
M
M.rref()
- Nullspace
對於線性方程:Ax=b。如果有唯一解的化,那么沒有任何向量乘以A后能夠等於0向量:Ab=0。這個時候叫做full rank。也就是rank =n。
如果如果Ax=b沒有唯一解,那么就會有很多向量使Ab=0。這些向量b本身組成了一個空間(可以哦嗯一組基表示所有滿足要求的向量)。
如果rank=n-1,那么這個nullspace由一個基向量就可以表示,如果rank=n-2,那么這個nullspace由兩個基向量才能表示。
所以求一個矩陣的nullspace也就是求這個space的基。
如果A是方陣,那么A的rank就等於不為零的特征值的個數。
M = Matrix([[1, 2, 3, 0, 0], [4, 10, 0, 0, 1]])
M
M.rref()
M.nullspace()
Columnspace
M = Matrix([[1, 1, 2], [2 ,1 , 3], [3 , 1, 4]])
特征值,特征向量,對角化
M = Matrix([[3, -2, 4, -2], [5, 3, -3, -2], [5, -2, 2, -2], [5, -2, -3, 3]])
M
M.eigenvals()
M.eigenvects()
P, D = M.diagonalize()
P
D
P*D*P**-1
如果想要的特征多項式,直接用charpoly
,這比engenvals
更高效,有時候符號表示的根求解非常麻煩。
lamda = symbols('lamda') # lambda 是python中的關鍵字,所以sympy中用lamda
p = M.charpoly(lamda)
p
factor(p)
高級表達式操作
理解表達式樹
首先來看表達式在sympy中是怎么表達的,比如2^x+xy,可以用srepr
來內在的看表達式是什么樣子。
expr=2**x+x*y
expr
srepr(expr)
"Add(Pow(Integer(2), Symbol('x')), Mul(Symbol('x'), Symbol('y')))"