Sympy 基础

Sympy是python符号计算库,有着符号求解的特点。

这篇博客内容是利用一个求解方程的例子,简单介绍Sympy符号计算的基本过程。

首先,我们要解决的问题是车流微分方程:

F为流量,为密度,u为车流速度,F=*u。

在某一时刻流量有最大值

F与的关系为:


从物理意义上讲,当密度最大时拥堵最严重,车都不走了,流量为0.

什么时候流量最大呢?就是F()函数取极值时,即得到最大值,此时密度为,速度为

那么总结起来就是:


求解方程组

在引入Sympy的时候,初始化LaTeX语法,这样就能用LaTeX语法写符号了。

import sympy
sympy.init_printing()
u_max, u_star, rho_max, rho_star, A, B = sympy.symbols('u_max u_star rho_max rho_star A B')
下面用这些变量表示上面三个方程:

sympy.Eq()函数将两个表达式分别放在等号两边,组成方程:

eq1 = sympy.Eq( 0, u_max*rho_max*(1 - A*rho_max-B*rho_max**2) )
eq2 = sympy.Eq( 0, u_max*(1 - 2*A*rho_star-3*B*rho_star**2) )
eq3 = sympy.Eq( u_star, u_max*(1 - A*rho_star - B*rho_star**2) )
这时候输入eq1,得到:


eq2:


eq3:


假设u_star已知,那么三个未知量三个变量,方程组可解.

>>>eq2-3*eq3



sympy直接将这个字符串打印出来了,而没有转化为方程。

这时候,应该利用sympy.Eq()函数创建新的方程:

eq4 = sympy.Eq(eq2.lhs - 3*eq3.lhs, eq2.rhs - 3*eq3.rhs)

eq4:



eq2.lhs表示等号左边的代数式(left hand side)

eq2.rhs表示等号右边的代数式(right hand side)

这时候,方程eq4还没有化简。

eq4.simplify()


注意这时候eq4本身并没有化简。

eq4依然为:



我们再看eq4.expand()函数:

eq4.expand()


expand函数将因式全部乘了起来,并且进行了化简,但是此时eq4依然没有改变。

这时候我们可以进行求解方程。

首先,从方程4求解处rho_star:

In[17]:rho_sol = sympy.solve(eq4,rho_star)
In[18]:rho_sol
Out[18]: 


注意:sympy.solve()返回的是一个列表。所以我们不如采用如下代码:

rho_sol = sympy.solve(eq4,rho_star)[0]
rho_sol

B_sol = sympy.solve(eq1,B)[0]
B_sol


将求解的rho_sol B_sol代入方程2中:

quadA = eq2.subs([(rho_star, rho_sol), (B,B_sol)])
quadA

quadA.simplify()


A_sol = sympy.solve(quadA, A)
A_sol[0]



A_sol[1]



假设=10,=1.0,=0.7,那么:

aval = A_sol[0].evalf(subs={u_star: 0.7, u_max:1.0, rho_max:10.0} )
aval


舍去负值。

bval = B_sol.evalf(subs={rho_max:10.0, A:aval} )
bval


同样,也求解得到B。

求微分:

x, nu, t = sympy.symbols('x nu t')
phi = sympy.exp(-(x-4*t)**2/(4*nu*(t+1))) + sympy.exp(-(x-4*t-2*numpy.pi)**2/(4*nu*(t+1)))
phiprime = phi.diff(x)

lambdify:


fromsympy.utilities.lambdifyimport lambdify

u = -2*nu*(phiprime/phi)+4

ufunc = lambdify((t,x, nu),u)
print("The value of u at t=1, x=4, nu=3 is {}.".format(ufunc(1,4,3)))
结果为:
The value of u at t=1, x=4, nu=3 is 3.49170664206.


关闭Latex语法

sympy.init_printing(use_latex=False)