导数的定义
导数就是增量比的极限,也就是函数的某点到某点的变化率。
导数公式与基本求导法则
常数和基本初等函数的导数公式
函数的和、差、积、商的求导法则
from sympy import pprint,diff from sympy.abc import x f = 2*x**3 - 5*x**2 + 3*x - 7 df = diff(f,x) pprint(f) print() pprint(df)
from sympy import pprint,diff,cos,sin,pi,ln,E from sympy.abc import x f = x**3 + 4*cos(x) - sin(pi/2) df = diff(f,x) pprint(f) print() pprint(df) print() pprint(df.subs(x,pi/2)) print() f2 = ln(x**3+2*x+1) pprint(diff(f2,x))
from sympy import pprint,diff,cos,sin,pi,ln,exp,sqrt from sympy.abc import x f = sqrt(x)*ln(x) df = diff(f,x) pprint(f) print() print(df) print(df.simplify()) #表达式化简 print() print() f2 = exp(x)*(sin(x)+cos(x)) df2 = diff(f2,x) print(df2) print(df2.simplify()) #表达式化简
高阶导数
导数的应用
函数的单调性
from sympy import pprint,diff,cos,sin,pi,ln,exp,sqrt,plot,solve,Piecewise,Eq from sympy.abc import x f = 2*x**3 - 9*x**2 + 12*x - 3 df = diff(f) print(solve(df,x)) from mpl_toolkits.axisartist.axislines import SubplotZero import matplotlib.pyplot as plt import matplotlib as mpl import math import numpy as np # 设置中文显示 mpl.rcParams[\'font.sans-serif\'] = [\'SimHei\'] mpl.rcParams[\'axes.unicode_minus\'] = False fig = plt.figure() ax = SubplotZero(fig, 111) fig.add_subplot(ax) for direction in ["xzero", "yzero"]: # adds arrows at the ends of each axis ax.axis[direction].set_axisline_style("-|>") # adds X and Y-axis from the origin ax.axis[direction].set_visible(True) for direction in ["left", "right", "bottom", "top"]: # hides borders ax.axis[direction].set_visible(False) X = np.array([i/100 for i in range(-50,300)]) y = np.array([f.subs(x,i) for i in X]) dy = np.array([df.subs(x,i) for i in X]) plt.plot(X,y,\'-b\',label=\'f(x) = 2*x^3 - 9*x^2 + 12*x - 3\') plt.plot(X,dy,\'-r\',label="f\'(x) = f(x) = 6*x^2 - 18*x + 12") ax.axis[\'yzero\'].set_label(\'y轴\') ax.axis[\'xzero\'].set_label(\'x轴\') tk = [1,2] plt.xticks(tk) plt.xlim(-3,3) plt.legend(loc=\'lower right\') #生成网格 # plt.grid(True) plt.show()
曲线的凹凸性
from sympy import pprint,diff,cos,sin,pi,ln,exp,sqrt,plot,solve,Piecewise,Eq from sympy.abc import x f = 3*x**4 - 4*x**3 + 1 df = diff(f,x,x) print(df) print(solve(df,x)) from mpl_toolkits.axisartist.axislines import SubplotZero import matplotlib.pyplot as plt import matplotlib as mpl import math import numpy as np # 设置中文显示 mpl.rcParams[\'font.sans-serif\'] = [\'SimHei\'] mpl.rcParams[\'axes.unicode_minus\'] = False fig = plt.figure() ax = SubplotZero(fig, 111) fig.add_subplot(ax) for direction in ["xzero", "yzero"]: # adds arrows at the ends of each axis ax.axis[direction].set_axisline_style("-|>") # adds X and Y-axis from the origin ax.axis[direction].set_visible(True) for direction in ["left", "right", "bottom", "top"]: # hides borders ax.axis[direction].set_visible(False) X = np.array([i/100 for i in range(-200,200)]) y = np.array([f.subs(x,i) for i in X]) dy = np.array([df.subs(x,i) for i in X]) plt.plot(X,y,\'-b\',label=\'f(x) = 2*x^3 - 9*x^2 + 12*x - 3\') plt.plot(X,dy,\'-r\',label=\'f(x) = f"(x) = 12*x*(3*x - 2)\') ax.axis[\'yzero\'].set_label(\'y轴\') ax.axis[\'xzero\'].set_label(\'x轴\') tk = [0, 2/3] plt.xticks(tk) plt.xlim(-1,3) plt.legend(loc=\'upper left\') #生成网格 # plt.grid(True) plt.show()
以上例子说明:
from sympy import pprint,diff,cos,sin,pi,ln,exp,sqrt,plot,solve,Piecewise,Eq from sympy.abc import x f = x**3 - 6*x**2 + 9*x + 1 df = diff(f,x,x) print(df) print(solve(df,x)) from mpl_toolkits.axisartist.axislines import SubplotZero import matplotlib.pyplot as plt import matplotlib as mpl import math import numpy as np # 设置中文显示 mpl.rcParams[\'font.sans-serif\'] = [\'SimHei\'] mpl.rcParams[\'axes.unicode_minus\'] = False fig = plt.figure() ax = SubplotZero(fig, 111) fig.add_subplot(ax) for direction in ["xzero", "yzero"]: # adds arrows at the ends of each axis ax.axis[direction].set_axisline_style("-|>") # adds X and Y-axis from the origin ax.axis[direction].set_visible(True) for direction in ["left", "right", "bottom", "top"]: # hides borders ax.axis[direction].set_visible(False) X = np.array([i/100 for i in range(-200,500)]) y = np.array([f.subs(x,i) for i in X]) dy = np.array([df.subs(x,i) for i in X]) plt.plot(X,y,\'-b\',label=\'f(x) = 2*x^3 - 9*x^2 + 12*x - 3\') plt.plot(X,dy,\'-r\',label=\'f"(x) = 6*(x - 2)\') ax.axis[\'yzero\'].set_label(\'y轴\') ax.axis[\'xzero\'].set_label(\'x轴\') tk = [2] plt.xticks(tk) plt.xlim(-1,5) plt.legend(loc=\'upper left\') #生成网格 # plt.grid(True) plt.show()
小结:
通过函数的导数的值,可以判断出函数的单调性、曲线的凹凸性: 若导数大于0,则单调递增;若导数小于0,则单调递减;导数等于 零的点为函数的驻点。 若二阶导数大于0,则曲线是凹的;若二阶导数小于0,则曲线是凸 的;曲线上凹凸性改变的点为曲线的拐点。 如果函数的导函数在某一个区间内恒大于零(或恒小于零),那么函 数在这个区间单调递增(或单调递减),这种区间就叫做单调区间;如果 函数的二阶导函数在某一个区间内恒大于零(或恒小于零),那么曲线在 这个区间是凹的(或凸的),这种区间就叫做凹凸区间。
穿根法
函数的极值及其求法
极值存在的第一充分条件
from sympy import pprint,diff,cos,I,sin,pi,ln,exp,sqrt,plot,solve,Piecewise,Eq,Rational,re from sympy.abc import x f = (x-1)*x**(2/3) df = diff(f,x) print(df.simplify()) print(solve(Eq(df,0),x)) from mpl_toolkits.axisartist.axislines import SubplotZero import matplotlib.pyplot as plt import matplotlib as mpl import math import numpy as np # 设置中文显示 mpl.rcParams[\'font.sans-serif\'] = [\'SimHei\'] mpl.rcParams[\'axes.unicode_minus\'] = False fig = plt.figure() ax = SubplotZero(fig, 111) fig.add_subplot(ax) for direction in ["xzero", "yzero"]: # adds arrows at the ends of each axis ax.axis[direction].set_axisline_style("-|>") # adds X and Y-axis from the origin ax.axis[direction].set_visible(True) for direction in ["left", "right", "bottom", "top"]: # hides borders ax.axis[direction].set_visible(False) X = np.array([i/100 for i in range(-500,500)]) y = np.array([f.subs(x,i).subs(I,1) for i in X]) #re(f.subs(x,i))用浮点数计算,变取实数。 dy = np.array([df.subs(x,i).subs(I,1) for i in X if i != 0]) print(y) plt.plot(X,y,\'-b\',label=\'f(x) = (x-1)*x**(2/3)\') X = np.delete(X,[200]) plt.plot(X,dy,\'-r\',label="f\'(x) = (5*x - 2)/(3*x**(1/3))") ax.axis[\'yzero\'].set_label(\'y轴\') ax.axis[\'xzero\'].set_label(\'x轴\') tk = [0,2/5] plt.xticks(tk) plt.xlim(-5,5) plt.legend(loc=\'upper left\') #生成网格 # plt.grid(True) plt.show() print(df.subs(x,-1))
极值存在的第二充分条件
from sympy import pprint,diff,cos,I,sin,pi,ln,exp,sqrt,plot,solve,Piecewise,Eq,Rational,re from sympy.abc import x f = x**3 + 3*x**2 - 24*x - 20 df = diff(f,x) ddf = diff(df,x) print(ddf.simplify()) print(solve(Eq(df,0),x)) from mpl_toolkits.axisartist.axislines import SubplotZero import matplotlib.pyplot as plt import matplotlib as mpl import math import numpy as np # 设置中文显示 mpl.rcParams[\'font.sans-serif\'] = [\'SimHei\'] mpl.rcParams[\'axes.unicode_minus\'] = False fig = plt.figure() ax = SubplotZero(fig, 111) fig.add_subplot(ax) for direction in ["xzero", "yzero"]: # adds arrows at the ends of each axis ax.axis[direction].set_axisline_style("-|>") # adds X and Y-axis from the origin ax.axis[direction].set_visible(True) for direction in ["left", "right", "bottom", "top"]: # hides borders ax.axis[direction].set_visible(False) X = np.array([i/100 for i in range(-500,500)]) y = np.array([f.subs(x,i) for i in X]) #re(f.subs(x,i))用浮点数计算,变取实数。 dy = np.array([df.subs(x,i) for i in X]) ddy = np.array([ddf.subs(x,i) for i in X]) plt.plot(X,y,\'-b\',label=\'f(x) = x**3 + 3*x**2 - 24*x - 20\') plt.plot(X,dy,\'-r\',label="f\'(x) = 3*x**2 + 6*x - 24") plt.plot(X,ddy,\'-g\',label=\'f"(x) = 6*x + 6\') plt.plot(np.array([-4,-4]),np.array([-50,65]),linestyle=\'--\',color=\'gray\') plt.plot(np.array([2,2]),np.array([-50,65]),linestyle=\'--\',color=\'gray\') ax.axis[\'yzero\'].set_label(\'y轴\') ax.axis[\'xzero\'].set_label(\'x轴\') tk = [-4, 2] plt.xticks(tk) plt.xlim(-5,5) plt.legend(loc=\'upper left\') #生成网格 # plt.grid(True) plt.show()
求极值的步骤:
函数的最大值、最小值问题
from sympy import diff,plot,solve,Eq,cos,sin from sympy.abc import x,u from sympy.plotting import plot_parametric y = 2*x**3 + 3*x**2 - 12*x + 14 dy = diff(y,x) pointList = [-3,4]+solve(Eq(dy,0),x) results = [y.subs(x,i) for i in pointList] plot(y,(x,-3,4),axis_center=(0.0,0.0),line_color=(1.0,0.0,0.0),title=\'y = 2*x^3 + 3*x^2 - 12*x + 14\') print(\'最大值是:{}\'.format(max(results))) print(\'最小值是:{}\'.format(min(results))) print(solve(dy,x))
说明:
练习一
from sympy import diff,plot,solve,Eq,cos,sin,pi,pprint from sympy.abc import x,V,r from sympy.plotting import plot_parametric S = 2*pi*r**2 + 2*V/r dS = diff(S,r) print(dS.simplify()) print(solve(dS,r)[0])
from sympy import diff,plot,solve,Eq,cos,sin,pi,pprint,Symbol a = Symbol(\'a\',positive=True) x = Symbol(\'x\',positive=True) V = x*(a-2*x)**2 dV = diff(V,x) d2V = diff(dV,x) print(dV.simplify()) print(d2V.simplify()) sol = solve(dV,x) for i in sol: if 0 < i < a/2: res = d2V.subs(x,i) if res < 0: print(\'当x = {}时,V有最大值:{}\'.format(i,V.subs(x,i))) break else: print(\'无解\')
Taylor公式
Taylor(泰勒)公式是用一个函数在某点的信息描述其附近取值的公式。 如果函数足够平滑,在已知函数在某一点的各阶导数值的情况下, Taylor公式可以利用这些导数值来做系数构建一个多项式近似函数在这 一点的邻域中的值。
多项式是最简单的一类初等函数. 所以在数值计算方面,多项式是人们乐于 使用的工具. 加减法和乘法, 因此我们经常用多项式来近似表达函数.
以 f(x) = cos(x) 的近似计算为例.
一次(线性)逼近
二次逼近
八次逼近
找的多项式应满足什么条件,误差是什么?
综上所述
泰勒(Taylor)公式
Taylor公式-余项
from sympy import series,exp,pprint,Symbol,re,sin,pi,O,Order x = Symbol(\'x\',real=True) f = exp(x).series(x,0,10) #令x = 1 i = Order(x**10) print(f) print(f.subs([(O(x**10),0),(x,1)]).evalf())
几个常见的初等函数的带有佩亚诺余项的麦克劳林公式
from sympy import I,exp,E,pi,S,Symbol,expand,Function,Eq,pprint,re,im,cos,sin,series print(E**(I*pi)+1) #欧拉的宇宙公式 print((exp(I*pi)+1).equals(0)) \'\'\'求证:exp(I*pi)=cos(x) + I*sin(x)\'\'\' x = Symbol(\'x\',real=True) #指定x是实数 f = exp(I*x) print(f.expand(complex=True)) print() #泰勒展开 fs = f.series(x,x0=0,n=10) print(\'exp(I*x)泰勒展开:{}\'.format(fs)) print(\'I*sin(x) + cos(x)泰勒展开:{}\'.format(series(I*sin(x) + cos(x),x,x0=0,n=10))) print() #取实部 print(re(fs)) print(cos(x).series(x,x0=0,n=10)) print() #取虚部 print(im(fs)) print((sin(x).series(x,x0=0,n=10)))
from sympy import I,exp,E,pi,S,Symbol,expand,Function,Eq,pprint,re,im,cos,sin,series x = Symbol(\'x\',real=True) m = Symbol(\'m\',real=True) print(series(1/(1-x),x,x0=0,n=10)) print() print(series((1+x)**m,x,x0=0,n=6).simplify())
多元函数
二元函数的定义
from sympy import I,exp,E,pi,S,Symbol,cos,sin,series,plot,sqrt from sympy.plotting import plot3d x = Symbol(\'x\',real=True) y = Symbol(\'m\',real=True) r = Symbol(\'r\') plot3d(sqrt(1-x**2-y**2),(x,-1,1),(y,-1,1)) plot3d(sin(x*y),(x,-2.5,2.5),(y,-2.5,2.5))
多元函数的极限
多元函数偏导数
对于三元函数 u = f (x, y, z)可类似
from sympy import I,diff,Symbol from sympy.plotting import plot3d x = Symbol(\'x\',real=True) y = Symbol(\'y\',real=True) f = x**2 + 3*x*y + y**2 dx = diff(f,x) dy = diff(f,y) print(dx) print(dy) print(dx.subs([(x,1),(y,2)])) print(dy.subs([(x,1),(y,2)])) print(diff(f,x,y))
高阶偏导数
类似可以定义更高阶的偏导数
多元函数的极值和最值
必要条件
充分条件
求二元函数z = f (x, y)极值的一般步骤
求二元函数最值的一般方法
拉格朗日乘数法
from sympy import linsolve,symbols,diff,solve,E,Wild r,x,y,z,V = symbols(\'r,x,y,z,V\',real=True) f = 2*(x*y+y*z+z*x) + r*(x*y*z-V) f2 = V/(x*y) dx = diff(f,x) rs = solve([dx],r) dz = diff(f,z).subs([(r,rs[r]),(z,f2)]) ys = solve(dz,y) dy = diff(f,y).subs([(r,rs[r]),(z,f2),(y,ys[0])]) print(solve(dy,x)[0])
方向导数与梯度
向量的运算
from sympy.vector import CoordSys3D,matrix_to_vector from sympy import Matrix,acos,asin,rad,pi,deg,sin,plot,sin,cos from sympy.abc import x C = CoordSys3D(\'C\') #表示向量只能用坐标系对象的i,j,k表示,不能用它的x,y,z表示,它们代表是x轴,y轴,z轴。 #i代表是x轴方向的坐标向量,j表示y轴方向的,k表示z轴方向的。 a = C.i + 2*C.j #在一个坐标系上一个向量的表示,一般按照i,j,k的顺序xie b = -6*C.i + C.j print(\'a向量的向量坐标:{}\'.format(tuple(a.components.values()))) print(\'a向量的模:{}\'.format(a.magnitude())) print(\'把a向量转为单位向量:{},转化后的大小:{}\'.format(a.normalize(),a.normalize().magnitude())) print(\'把向量a转为矩阵:{}\'.format(a.to_matrix(C))) print() #向量的运算 c = a+b #向量的加法 d = a-b #向量的减法 f = a&b #向量的数量积(点积、内积),用函数表示:a.dot(b) j = a^b #叉积,a.cross(b) k = a.outer(b) #外积 print(\'a-b = {};坐标:{}\'.format(a-b,(a-b).components.values())) print(\'a+b = {};坐标:{}\'.format(a+b,(a+b).components.values())) print(\'a.b = {}\'.format(f)) print(\'向量a与向量b的夹角(角度)是:{}\'.format(deg(acos(f/(a.magnitude()*b.magnitude()))).evalf())) print(\'a*b = {}\'.format(j)) print() #矩阵转为向量。 m = Matrix([1,2]) v = matrix_to_vector(m,C) print(\'矩阵m转为向量:{}\'.format(v)) print(\'向量的模:{}\'.format(m.norm())) print(\'标准化矩阵:{}\'.format(m.normalized())) print(v.to_matrix(C))
正交向量
方向角与方向余弦
from sympy.vector import CoordSys3D,matrix_to_vector from sympy import Matrix,acos,rad,pi,deg,vector,sqrt,solve,Eq,pprint # init_printing(pretty_print=True)d C = CoordSys3D(\'C\') #表示向量只能用坐标系对象的i,j,k表示,不能用它的x,y,z表示,它们代表是x轴,y轴,z轴。 #i代表是x轴方向的坐标向量,j表示y轴方向的,k表示z轴方向的。 l = (1-2)*C.i + (3-2)*C.j + (0-sqrt(2))*C.k #在一个坐标系上一个向量的表示,一般按照i,j,k的顺序xie print(\'与向量l同方向的单位向量:{}\'.format(l/l.magnitude())) lc = (l/l.magnitude()).components print(\'与向量l同方向的单位向量的坐标:{}\'.format(lc)) print(\'方向余弦:cos(alpha) = {};cos(beta) = {};cos(gamma) = {}\'.format(lc[C.i],lc[C.j],lc[C.k])) print(\'方向角:alpha = {};beta = {};gamma = {}\'.format(acos(lc[C.i]),acos(lc[C.j]),acos(lc[C.k])))
方向导数
from sympy.vector import CoordSys3D,matrix_to_vector from sympy import Matrix,acos,rad,pi,deg,vector,sqrt,solve,Eq,pprint,E,diff from sympy.abc import x,y C = CoordSys3D(\'C\') #表示向量只能用坐标系对象的i,j,k表示,不能用它的x,y,z表示,它们代表是x轴,y轴,z轴。 #i代表是x轴方向的坐标向量,j表示y轴方向的,k表示z轴方向的。 z = x*E**(2*y) #在一个坐标系上一个向量的表示,一般按照i,j,k的顺序xie dx = diff(z,x) dy = diff(z,y) l = (2-1)*C.i+(-1-0)*C.j e = (l/l.magnitude()).components dl = dx*e[C.i] + dy*e[C.j] pprint(dl.subs([(x,1),(y,0)]))
from sympy.vector import CoordSys3D,matrix_to_vector from sympy import Matrix,acos,rad,pi,deg,vector,sqrt,solve,Eq,pprint,E,diff from sympy.abc import x,y,z C = CoordSys3D(\'C\') #表示向量只能用坐标系对象的i,j,k表示,不能用它的x,y,z表示,它们代表是x轴,y轴,z轴。 #i代表是x轴方向的坐标向量,j表示y轴方向的,k表示z轴方向的。 u = x**2*y*z #在一个坐标系上一个向量的表示,一般按照i,j,k的顺序xie dx = diff(u,x) dy = diff(u,y) dz = diff(u,z) l = 2*C.i+(-1)*C.j+3*C.k e = (l/l.magnitude()).components dl = dx*e[C.i] + dy*e[C.j] + dz*e[C.k] pprint(dl.subs([(x,1),(y,1),(z,1)]))
from sympy.vector import CoordSys3D,matrix_to_vector,directional_derivative from sympy import Matrix,cos,rad,pi,deg,vector,sqrt,solve,Eq,pprint,E,diff,factor from sympy.abc import x,y,z C = CoordSys3D(\'C\') #表示向量只能用坐标系对象的i,j,k表示,不能用它的x,y,z表示,它们代表是x轴,y轴,z轴。 #i代表是x轴方向的坐标向量,j表示y轴方向的,k表示z轴方向的。 u = x*y + y*z + z*x #在一个坐标系上一个向量的表示,一般按照i,j,k的顺序xie dx = diff(u,x) dy = diff(u,y) dz = diff(u,z) e = (cos(rad(60))*C.i + cos(rad(45))*C.j + cos(rad(60))*C.k).components dl = dx*e[C.i] + dy*e[C.j] + dz*e[C.k] print(dl) pprint(factor(dl.subs([(x,1),(y,1),(z,2)]))) #直接调用sympy的directional_derivative e2 = cos(rad(60))*C.i + cos(rad(45))*C.j + cos(rad(60))*C.k u2 = C.x*C.y + C.y*C.z +C.z*C.x dl = directional_derivative(u2,e2) print(dl.simplify()) pprint(factor(dl.subs([(C.x,1),(C.y,1),(C.z,2)])))
梯度(gradient)的概念及计算
在空间的每一个点都可以确定无限多个方向, 因此, 导数. 在这无限多个方向导数中, 最大的一个(它直接 反映了函数在这个点的变化率的数量级)等于多少? 一个多元函数在某个点也必然有无限多个方向 它是沿什么方向达到的? 描述这个最大方向导数及其 所沿方向的矢量, 就是我们下面讨论的梯度. 梯度是 场论里的一个基本概念. 所谓“场” , 它表示空间区域 上某种物理量的一种分布. 从数学上看, 这种分布常常 表示为 上的一种数值函数或向量函数. 能表示为数 值函数u = u(x, y, z) 的场, 称为数量场,如温度场、密度场等.
方向导数公式
梯度定义
from sympy.vector import CoordSys3D,matrix_to_vector,directional_derivative,gradient,Del from sympy import Matrix,cos,rad,pi,deg,vector,sqrt,solve,Eq,pprint,E,diff,factor from sympy.abc import x,y,z C = CoordSys3D(\'C\') #表示向量只能用坐标系对象的i,j,k表示,不能用它的x,y,z表示,它们代表是x轴,y轴,z轴。 #i代表是x轴方向的坐标向量,j表示y轴方向的,k表示z轴方向的。 u = 1/(C.x**2+C.y**2) #在一个坐标系上一个向量的表示,一般按照i,j,k的顺序xie delop = Del() print(delop.gradient(u).doit()) print(gradient(u))
from sympy.vector import CoordSys3D,matrix_to_vector,directional_derivative,gradient,Del from sympy import Matrix,cos,rad,pi,deg,vector,sqrt,solve,Eq,pprint,E,diff,factor from sympy.abc import x,y,z C = CoordSys3D(\'C\') #表示向量只能用坐标系对象的i,j,k表示,不能用它的x,y,z表示,它们代表是x轴,y轴,z轴。 #i代表是x轴方向的坐标向量,j表示y轴方向的,k表示z轴方向的。 u = C.x**3 - C.x*C.y**2 - C.z #在一个坐标系上一个向量的表示,一般按照i,j,k的顺序xie df = gradient(u) du = df.subs([(C.x,1),(C.y,1),(C.z,0)]) print(\'在向量:{} 方向;增加最快,变化率:{}\'.format(du,du.magnitude())) print(\'在向量:{} 方向;减小最快,变化率:{}\'.format(-du,-du.magnitude()))