> 技术文档 > 2023年高教杯数学建模2023B题解析(仅从代码角度出发)

2023年高教杯数学建模2023B题解析(仅从代码角度出发)


前言

最近博主正在和队友准备九月的数学建模,在做往年的题目,博主主要是负责数据处理,运算以及可视化,这里分享一下自己部分的工作,相关题目以及下面所涉及的代码后续我会作为资源上传

问题求解

第一题

第一题的思路主要如下:
在这里插入图片描述
在这里插入图片描述
如果我们基于代码实现的话,代码应该是这样的:

# 导入相关第三方包import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport math# 生成测线距离中心点处的距离list1=[]d=200for i in range(-800,1000,200): list1.append(i)df=pd.DataFrame(list1,columns=[\"测线距离中心点处的距离\"])#计算海水深度和覆盖宽度degree1 = 1.5 radian1 = degree1 * (math.pi / 180)df[\"海水深度\"]=(70-df[\"测线距离中心点处的距离\"]*math.tan(radian1))df[\"海水深度\"]=df[\"海水深度\"].round(2)degrees2 = 120/2radian2 = degrees2 * (math.pi / 180)df[\"覆盖宽度\"]=(df[\"海水深度\"]*math.sin(radian2)/math.cos(radian2+radian1))+(df[\"海水深度\"]*math.sin(radian2)/math.cos(radian2-radian1))df[\"覆盖宽度\"]=df[\"覆盖宽度\"].round(2)# 计算重叠率leftlist=df[\"海水深度\"]*math.sin(radian2)*1/math.cos(radian1+radian2)rightlist=df[\"海水深度\"]*math.sin(radian2)*1/math.cos(radian1-radian2)leftlist=leftlist.round(2)rightlist=rightlist.round(2)leftlist=leftlist.tolist()leftlist=leftlist[1:]rightlist=rightlist.tolist()rightlist=rightlist[:8]heights = df[\"覆盖宽度\"].tolist()heights=heights[:8]list2=[0]for i in range(0,8): a=(1-200/((leftlist[i]+rightlist[i])*math.cos(radian1))) list2.append(a*100)df[\"重叠率\"]=list2df.to_excel(\"2023B题1.xlsx\",index=False)

这样我们就基本上完成了对相关数据的求解,然后我们可以实现一下对于它的可视化,代码与相关结果如下:

plt.rcParams[\'font.sans-serif\'] = [\'SimHei\'] # 指定默认字体plt.rcParams[\'axes.unicode_minus\'] = False # 解决保存图像是负号\'-\'显示为方块的问题# Plotting sea depthplt.figure(figsize=(10, 6))plt.plot(df[\"测线距离中心点处的距离\"], df[\"海水深度\"], marker=\'o\', linestyle=\'-\', color=\'b\', label=\'海水深度\')# Plotting coverage widthplt.plot(df[\"测线距离中心点处的距离\"], df[\"覆盖宽度\"], marker=\'o\', linestyle=\'-\', color=\'g\', label=\'覆盖宽度\')# Plotting overlap rateplt.plot(df[\"测线距离中心点处的距离\"], df[\"重叠率\"], marker=\'o\', linestyle=\'-\', color=\'r\', label=\'重叠率\')# Adding labels and titleplt.xlabel(\'测线距离中心点处的距离\')plt.ylabel(\'海水深度 / 覆盖宽度 / 重叠率\')plt.title(\'海水深度、覆盖宽度和重叠率随距离变化的折线图\')plt.legend()# Display plotplt.grid(True)plt.tight_layout()plt.show()

2023年高教杯数学建模2023B题解析(仅从代码角度出发)

第二题

第二题的思路主要是下面的式子:
在这里插入图片描述
博主的求解代码基本如下:

import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport math# 生成相关数据list1=[]list2=[]a=0for i in range(8): ans=a*math.pi/180 list1.append(ans) a+=45a=0for i in range(8): list2.append(a) a+=0.3b=1.5c=60randian11=b*math.pi/180randian12=c*math.pi/180# 求解覆盖宽度:list3=[]for i in range(8): list4=[] for j in range(8): randian21=math.tan(randian11)*-1*math.cos(list1[i]) randian31=math.tan(randian11)*math.sin(list1[i]) randian22=math.atan(randian21) randian32=math.atan(randian31) Da=120-list2[j]*randian21*1852 W=(Da*math.sin(randian12)/math.cos(randian12+randian32))+(Da*math.sin(randian12)/math.cos(randian12-randian32)) list4.append(W) list3.append(list4)

最后我们的工作就是数据的可视化了,首先是我们的代码部分:

#对结果的可视化plt.rcParams[\'font.sans-serif\'] = [\'SimHei\'] # 指定默认字体plt.rcParams[\'axes.unicode_minus\'] = False # 解决保存图像是负号\'-\'显示为方块的问题df=pd.DataFrame()df[\"β=0°\"]=list3[0]df[\"β=45°\"]=list3[1]df[\"β=90°\"]=list3[2]df[\"β=135°\"]=list3[3]df[\"测量船距海域中心点的距离\"]=list2plt.figure(figsize=(10, 6))plt.plot(df[\"测量船距海域中心点的距离\"], df[\"β=0°\"], label=\"β=0°\")plt.scatter(df[\"测量船距海域中心点的距离\"], df[\"β=0°\"]) plt.plot(df[\"测量船距海域中心点的距离\"], df[\"β=45°\"], label=\"β=45°\")plt.scatter(df[\"测量船距海域中心点的距离\"], df[\"β=45°\"]) plt.plot(df[\"测量船距海域中心点的距离\"], df[\"β=90°\"], label=\"β=90°\")plt.scatter(df[\"测量船距海域中心点的距离\"], df[\"β=90°\"]) plt.plot(df[\"测量船距海域中心点的距离\"], df[\"β=135°\"], label=\"β=135°\")plt.scatter(df[\"测量船距海域中心点的距离\"], df[\"β=135°\"]) plt.xlabel(\'测量船距海域中心点的距离\')plt.ylabel(\'list3 values\')plt.legend()plt.grid(True)plt.show() 

2023年高教杯数学建模2023B题解析(仅从代码角度出发)

第三题

前言

这题与上面的题目仅仅需要我们求解不同,这题的工作主要分为两份:

  1. 求解
  2. 灵敏度分析

求解

这题求解的主要思路如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(PS:浅浅吐槽一下,公式真的多,理顺花了我好一会…)
博主的求解代码如下:

import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport math# 设置相关参数a=1.5b=60radian1=a*math.pi/180radian2=b* math.pi/180D0=110Les=4*1852 #待测海域东西宽度D=D0+Les/2*math.tan(radian1) #此处Dmaxx=D*math.tan(radian2)D=D-x*math.tan(radian1)W1=0W2=0res_list=[x] # 存储xleft_list=[] # 存储左线坐标right_list=[] # 存储右线坐标while x+W2*math.cos(radian1)<=Les: W2=D*math.sin(radian2)/math.cos(radian2-radian1) W1=D*math.sin(radian2)/math.cos(radian2+radian1) d=(W1+W2)*0.9*math.cos(radian1)/(1+math.sin(radian1)*math.sin(radian2)/math.cos(radian2+radian1)*0.9) left_list.append(x-W1*math.cos(radian1)) right_list.append(x+W2*math.cos(radian1)) D=D-d*math.tan(radian1) x=x+d res_list.append(x)W2=D*math.sin(radian2)/math.cos(radian2-radian1)W1=D*math.sin(radian2)/math.cos(radian2+radian1)d=(W1+W2)*0.9*math.cos(radian1)/(1+math.sin(radian1)*math.sin(radian2)/math.cos(radian2+radian1)*0.9)left_list.append(x-W1*math.cos(radian1))right_list.append(x+W2*math.cos(radian1))print(\"总条数:%d\"%(len(res_list))) #总条数print(\"最大长度:%f\"%(res_list[-1])) #最大长度for i in range(len(res_list)): res_list[i]=res_list[i]/1852 left_list[i]=left_list[i]/1852 right_list[i]=right_list[i]/1852

然后就是我们对相关结果的可视化:

# 可视化plt.rcParams[\'font.sans-serif\'] = [\'SimHei\'] # 指定默认字体plt.rcParams[\'axes.unicode_minus\'] = False # 解决保存图像是负号\'-\'显示为方块的问题plt.axvline(res_list[0], color=\'red\',label=\'Red Line (测线)\')plt.axvline(left_list[0], color=\'green\',label=\'Green Line (条线左侧)\')plt.axvline(right_list[0], color=\'blue\',label=\'Blue Line (条线右侧)\')for i in range(1, len(res_list)): plt.axvline(res_list[i], color=\'red\') plt.axvline(left_list[i], color=\'green\') plt.axvline(right_list[i], color=\'blue\')# 设置图形属性plt.title(\'问题三结果\')plt.ylabel(\'由南向北/海里\')plt.legend()# 显示图形plt.grid(True)plt.show()

2023年高教杯数学建模2023B题解析(仅从代码角度出发)

灵敏度分析

灵敏度的分析思路其实还是很简单,主要是我们要改变开角和坡角的大小来看一下
看一下对结果的影响:

  • 基于开角变化实现的灵敏度分析及其可视化
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport math# 设置相关参数for b in range(100,150,10): a=1.5 radian1=a*math.pi/180 radian2=b/2* math.pi/180 D0=110 Les=4*1852 #待测海域东西宽度 D=D0+Les/2*math.tan(radian1) #此处Dmax x=D*math.tan(radian2) D=D-x*math.tan(radian1) W1=0 W2=0 res_list=[x] left_list=[] right_list=[] while x+W2*math.cos(radian1)<=Les: W2=D*math.sin(radian2)/math.cos(radian2-radian1) W1=D*math.sin(radian2)/math.cos(radian2+radian1) d=(W1+W2)*0.9*math.cos(radian1)/(1+math.sin(radian1)*math.sin(radian2)/math.cos(radian2+radian1)*0.9) left_list.append(x-W1*math.cos(radian1)) right_list.append(x+W2*math.cos(radian1)) D=D-d*math.tan(radian1) x=x+d res_list.append(x) W2=D*math.sin(radian2)/math.cos(radian2-radian1) W1=D*math.sin(radian2)/math.cos(radian2+radian1) d=(W1+W2)*0.9*math.cos(radian1)/(1+math.sin(radian1)*math.sin(radian2)/math.cos(radian2+radian1)*0.9) plt.plot(range(len(res_list)), res_list, linestyle=\'-\', label=f\'开角为{b}°\')plt.rcParams[\'font.sans-serif\'] = [\'SimHei\'] # 指定默认字体plt.rcParams[\'axes.unicode_minus\'] = False # 解决保存图像是负号\'-\'显示为方块的问题# 设置标签和标题plt.xlabel(\'i\')plt.ylabel(\'res_list[i]\')plt.title(\'基于开角变化实现的灵敏度分析及其可视化\')# 添加网格线和图例(可选)plt.grid(True)plt.legend()# 显示图形plt.show() 

结果如下:
2023年高教杯数学建模2023B题解析(仅从代码角度出发)

  • 基于开角变化实现的灵敏度分析及其可视化:
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport math# 设置相关参数a_list=[1.3,1.4,1.5]for i in range(len(a_list)): a=a_list[i] b=120 radian1=a*math.pi/180 radian2=b/2* math.pi/180 D0=110 Les=4*1852 #待测海域东西宽度 D=D0+Les/2*math.tan(radian1) #此处Dmax x=D*math.tan(radian2) D=D-x*math.tan(radian1) W1=0 W2=0 res_list=[x] left_list=[] right_list=[] while x+W2*math.cos(radian1)<=Les: W2=D*math.sin(radian2)/math.cos(radian2-radian1) W1=D*math.sin(radian2)/math.cos(radian2+radian1) d=(W1+W2)*0.9*math.cos(radian1)/(1+math.sin(radian1)*math.sin(radian2)/math.cos(radian2+radian1)*0.9) left_list.append(x-W1*math.cos(radian1)) right_list.append(x+W2*math.cos(radian1)) D=D-d*math.tan(radian1) x=x+d res_list.append(x) W2=D*math.sin(radian2)/math.cos(radian2-radian1) W1=D*math.sin(radian2)/math.cos(radian2+radian1) d=(W1+W2)*0.9*math.cos(radian1)/(1+math.sin(radian1)*math.sin(radian2)/math.cos(radian2+radian1)*0.9) plt.plot(range(len(res_list)), res_list, linestyle=\'-\', label=f\'坡角为{a}°\')plt.rcParams[\'font.sans-serif\'] = [\'SimHei\'] # 指定默认字体plt.rcParams[\'axes.unicode_minus\'] = False # 解决保存图像是负号\'-\'显示为方块的问题# 设置标签和标题plt.xlabel(\'i\')plt.ylabel(\'res_list[i]\')plt.title(\'基于坡角变化实现的灵敏度分析及其可视化\')# 添加网格线和图例(可选)plt.grid(True)plt.legend()# 显示图形plt.show()

2023年高教杯数学建模2023B题解析(仅从代码角度出发)

第四题

这题的主要工作就不是我做了,我主要是负责海水深度与横纵坐标数据的可视化,代码如下:

import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport math# 导入相关数据filepath=\"../resource/data.xlsx\"df=pd.read_excel(filepath)# 数据预处理df = df.iloc[1:, 2:]list1=df.values.tolist()list2=[]for i in range(251): list3=[] for j in range(201): list3.append(list1[i][j]*-1) list2.append(list3)list4 = np.arange(0,4.02,0.02) list3 = np.arange(0, 5.02, 0.02)# 数据可视化plt.rcParams[\'font.sans-serif\'] = [\'SimHei\'] # 指定默认字体plt.rcParams[\'axes.unicode_minus\'] = False # 解决保存图像是负号\'-\'显示为方块的问题x, y = np.meshgrid(list4, list3)z = np.array(list2)fig = plt.figure(figsize=(10, 8))ax = fig.add_subplot(111, projection=\'3d\')surf = ax.plot_surface(x, y, z, cmap=\'viridis\')ax.set_xlabel(\'横向坐标(由西向东)/海里\')ax.set_ylabel(\'纵向坐标(由南向北)/海里\')ax.view_init(elev=30, azim=-45) fig.colorbar(surf, aspect=5) # 显示图形plt.show()

三维图如下:
2023年高教杯数学建模2023B题解析(仅从代码角度出发)

结语

以上就是我所做的所有相关工作了,从这个学期有人找我打一下这个比赛,在此之前我从来都没有写过多少python,前一段时间打数维杯才开始看,没几天就上战场了,所幸最后也水了一个一等奖(感谢我的队友们),之前我的好几个学弟也问过怎么学语言之类,我还是觉得除了我们的第一门语言外,其他的就不要找几十小时的视频看了,你看我没看不也是硬逼出来了吗,事情往往不会在你有充分准备时到来,我们更应该学会边做边学,而不是等到学完再做,种一棵树最好的时间是十年前,其次是现在,写给可能有一些纠结的大家,也写给自己,那我们下篇见!over!

龙川教育网