实验9 Python在求解数学建模问题中的基础应用¶

1 常微分方程¶

主要使用的函数scipy.integrate.solve_ivp (安装scipy库)

  • 例 $$ \frac{dy}{dt} = -2*y + 1, \quad y(0) = 1 $$ 求解区间$ t\in[0,5]$
In [1]:
import numpy as np
from scipy.integrate import solve_ivp
from matplotlib import pyplot as plt 

def fun(t,y):
    """System of ODEs."""
    return -2*y +1

t_span = (0, 5) # time span
y0 = [0]   # initial condition

sol = solve_ivp(fun, t_span, y0, method='RK45', t_eval=np.linspace(0, 5, 100))
#显示结果
plt.figure(figsize=(8, 4))
plt.plot(sol.t, sol.y[0],'r--', label='y(t)')
plt.title('Solution of ODE using solve_ivp')
plt.xlabel('t')
plt.ylabel('y')
plt.show()
No description has been provided for this image
  • 例2 求解以下常微分方程 $y^{'''} - 3*y^{''} - y^{'}*y = 0$ 其边界值条件为$y^{'}(0)=1,y^{''}(0)=-1$

  • 解:

    • 设$y_{1}=y,y_{2} = y^{'},y_{3}=y^{'''}$那么常微分方程变成以下方程组: $$ \left\{ \begin{aligned} y_{1}^{'} = y_{2} \\ y_{2}^{'} = y_{3} \\ y_{3}^{'} = 3*y_{3}+ y_{2}*y_{1}\\ \end{aligned} \right. $$
In [2]:
import numpy as np
from scipy.integrate import solve_ivp
from matplotlib import pyplot as plt

def fun2(x,Y):
   y1,y2,y3 = Y  # u1,w1分别表示y1,y2
   dy1 = y2
   dy2 = y3
   dy3 = 3*y3 + y2*y1 
   return [dy1, dy2,dy3]

Y0 = [0,1,-1]
# 初始条件
x_span = (0, 1) # 时间区间
x_eval = np.linspace(0, 1, 100) # 计算点
sol = solve_ivp(fun2, x_span, Y0, method='RK45', t_eval=x_eval)
# 显示结果
plt.plot(sol.t, sol.y[0],'r-',label='y(t)')  
plt.plot(sol.t, sol.y[1], 'g--',label="y'(t)")  
plt.plot(sol.t, sol.y[2], 'b-.',label="y''(t)")  
plt.legend()  
plt.xlabel('t')  
plt.show()  
No description has been provided for this image

2 插值与拟合¶

主要scipy.interpolate 和 scipy.optimize.curve_fit

  • 插值
In [4]:
import numpy as np  
from scipy.interpolate import interp1d 
import matplotlib.pyplot as plt  

# 一维插值
x = np.linspace(0, 10, 10)  
y = np.sin(x)  
f_linear = interp1d(x, y)  
f_cubic = interp1d(x, y, kind='cubic')  

xnew = np.linspace(0, 10, 100)  
plt.plot(x, y, 'o', label='data')  
plt.plot(xnew, f_linear(xnew), 'r-', label='linear')  
plt.plot(xnew, f_cubic(xnew), 'b--', label='cubic')  
plt.legend()  
plt.show()  
No description has been provided for this image
  • 曲线拟合
In [5]:
from scipy.optimize import curve_fit  
from matplotlib import pyplot as plt 
import numpy as np

def func(x, a, b, c):  
    return a * np.exp(b * x) + c 

xdata = np.linspace(0, 4, 50)  
y = func(xdata, 2.5, 1.3, 2) + 2 * np.random.normal(size=len(xdata))  
popt, pcov = curve_fit(func, xdata, y)  
# print('Fitted parameters:', popt)  

plt.plot(xdata, y, 'rp', label='benchmark data')  
plt.plot(xdata, func(xdata,popt[0],popt[1],popt[2]), 'b--', label='curve_fit')  
plt.legend()  
plt.show()  
No description has been provided for this image

3 线性规划¶

  • scipy.optimize.linprog 是求解线性规划问题的工具
  • 例: 线性规划 $$ minz = -1*x_{1} - 2*x_{2} \\ s.t. \left\{\begin{aligned} x_{1} +2 *x_{2} \leq 4 \\ 4*x_{1} + 2*x_{2} \leq 12 \\ x_{1},x_{2} \geq 0\\ \end{aligned}\right. $$
In [8]:
from scipy.optimize import linprog  

# 最小化 -x - 2y (即最大化 x + 2y)  
c = [-1, -2]  
# 不等式约束: x + 2y <= 4, 4x + 2y <= 12  
A = [[1, 2],  
     [4, 2]]  
b = [4, 12]  
# 变量 x, y >=0  
res = linprog(c, A_ub=A, b_ub=b, bounds=[(0, None), (0, None)])  
print('Optimal value:', -res.fun)  # 因为linprog默认是minimize  
print('x:', res.x[0])  
print('y:', res.x[1])  
Optimal value: 4.0
x: 0.0
y: 2.0

4 非线性规划¶

  • scipy.optimize.minimize支持多种方法求解非线性优化。 $$ minz = 0.2*(x_1^2+x_2^2+x_3^2)+5*(x_1+x_2+x_3)+4*(2*x_1+x_2-140) \\ \left \{ \begin{array}{ll} x_1\geq 40 \\x_1+x_2 \geq 100 \\ x_1 +x_2+x_3 \geq 180 \\ 0 \leq x_1,x_2,x_3 \leq 100 \end{array} \right. $$
In [12]:
from scipy.optimize import minimize  

def fun(x):  
    return 0.2*(x[0]**2+x[1]**2+x[2]**2)+5*(x[0]+x[1]+x[2])+4*(2*x[0]+x[1]-140) 

x0 = [40, 60,80]  # 初始猜测  
cons= ({'type':'ineq', 'fun': lambda x: -100 + x[0]+ x[1]},  
        {'type':'ineq', 'fun': lambda x:- 180+  x[0]+ x[1]+x[2]})
# 约束条件
bounds = ((40, 100), (0, 100), (0, 100))
res = minimize(fun, x0, constraints=cons,bounds=bounds)
print('Optimal value:{:2.0f}'.format(res.fun) )  
print('Optimal x: {:3.0f},{:3.0f},{:3.0f}'.format(res.x[0],res.x[1],res.x[2]))  
Optimal value:3180
Optimal x:  50, 60, 70