24国赛全解全析:
(文中前面的几张图片是我往期作品中的部分内容和可视化图片哦,可视化内容非常精美!)
以下为开赛后更新的回答
2024全国大学生数学建模竞赛(国赛)A题 碰撞检测模型+最优螺距 机理建模
题目分析
- 板凳结构和连接方式:
- 每节板凳有固定的长度和宽度,龙头和龙身、龙尾的长度不同。
- 每节板凳通过孔和把手相连接。
- 需要考虑孔的位置和连接方式对整体结构的影响。
- 目标:
- 优化板凳龙的排列方式,使其在最小面积内盘旋。
- 提高板凳龙的行进速度和观赏性。
建模思路
- 几何建模:
- 计算每节板凳的占用面积,并考虑到它们之间的连接角度和重叠区域。
- 根据给定的连接方式,模拟板凳龙在不同角度下的布局,找到最小面积的排列方式。
- 优化算法:
- 可以使用启发式算法如模拟退火算法或遗传算法,寻找最优的板凳排列顺序和连接角度。
- 对于每种排列方式,计算所需的总面积和连接的紧密程度,选择最优解。
- 动力学分析:
- 如果考虑板凳龙的行进速度,还需要分析每节板凳在运动中的动态变化和阻力,可能需要引入物理建模。
根据你提供的文件内容,我们可以对这个数学建模问题进行更深入的分析。以下是针对各个问题的详细分析和可能的建模思路:
问题 1 分析
问题描述:舞龙队沿螺距为 55 cm 的等距螺线顺时针盘入,龙头前把手的速度为 1 m/s。要求计算从初始时刻到 300 秒的每秒整个舞龙队的位置和速度,并在特定时刻记录龙头、龙身和龙尾的特定位置和速度。
建模思路:
1. 参数化螺旋曲线:使用极坐标方程 r=a+bθ 描述螺线,其中 和a和b 为常数,螺距 p=2πbθ=55cm 。
2. 速度和位置计算:根据龙头的速度 ()(1m/s) 计算每秒龙头沿螺线前进的距离,再根据每节板凳的长度和间距计算龙身和龙尾的位置和速度。
3. 数值模拟:编写一个程序模拟每秒舞龙队各个部分的位置和速度,并输出结果到文件 result1.xlsx。
问题 2 分析
问题描述:确定舞龙队在盘入过程中,板凳之间不发生碰撞的终止时刻。
建模思路:
1. 碰撞检测:考虑到板凳的宽度和相邻板凳的最小间距,建立一个几何模型检测各节板凳是否发生碰撞。
2. 迭代模拟:在问题 1 的基础上,逐步增加时间,检测每一步的位置,如果发生碰撞,则记录时间并停止计算。 3. 优化算法:可以使用事件驱动的方法来优化检测过程,只在可能发生碰撞时进行计算。
问题 3 分析
问题描述:确定最小螺距,使得龙头前把手能够沿着相应的螺线盘入到直径为 9 m 的调头空间的边界。
建模思路:
1. 几何优化:使用几何分析计算从初始位置到调头空间边界所需的最小螺距。需要考虑到整个舞龙队的长度和转弯半径。
2. 数值求解:可以使用优化算法(如二分法或梯度下降)求解最小螺距。
问题 4 分析
问题描述:调整调头曲线,使得龙头前把手能够沿S形曲线调头,并保持与盘入、盘出螺线相切,目标是使调头曲线最短。
建模思路:
1. 曲线拟合与优化:利用曲线拟合技术(如贝塞尔曲线或样条曲线)拟合出最短的调头路径,保持与螺线的相切条件。
2. 优化问题建模:将调头曲线的长度作为目标函数,以曲线形状参数作为优化变量,使用优化算法(如遗传算法或模拟退火)找到最优解。
问题 5 分析
问题描述:确定龙头的最大行进速度,使得舞龙队各把手的速度均不超过 2 m/s。
建模思路:
1. 速度限制分析:根据龙头速度和各节板凳之间的关系,分析不同速度下各部分的速度变化,确保不超过2 m/s。 2. 数值模拟与优化:编写一个程序模拟不同龙头速度下的情况,使用优化算法找到使得所有板凳速度均在限制范围内的最大龙头速度。
变量定义和符号说明
我们使用了多个变量和符号来描述数学模型和解题过程。以下是主要变量和符号的定义和说明:
符号 | 定义与说明 |
---|---|
r | 极坐标下的半径,表示从螺线中心到舞龙队某把手的距离(单位:米)。 |
\theta | 极坐标下的角度,表示绕螺线中心的旋转角度(单位:弧度)。 |
p | 螺线的螺距,表示螺线每旋转一圈的径向变化量(单位:米)。 |
v_{\text{head}} | 龙头的行进速度,表示龙头前把手的线速度(单位:米/秒)。 |
v_i | 第 i 节龙身前把手或龙尾后把手的速度,表示舞龙队中某节板凳的速度(单位:米/秒)。 |
\omega_i | 第 i 节龙身前把手或龙尾后把手的角速度,表示舞龙队中某节板凳绕圆心的角速度(单位:弧度/秒)。 |
R_1 | 第一段圆弧的半径,表示调头路径第一段圆弧的半径(单位:米)。 |
R_2 | 第二段圆弧的半径,表示调头路径第二段圆弧的半径(单位:米)。 |
L | 调头路径的总长度,表示两段圆弧的总弧长(单位:米)。 |
t | 时间,表示龙头从开始到当前时间的经过时间(单位:秒)。 |
s | 沿螺旋线的累计行进距离,表示龙头在螺旋线上的累积距离(单位:米)。 |
x(t), y(t) | 直角坐标下的坐标位置,表示龙头或其他把手在直角坐标系下的坐标(单位:米)。 |
¥\theta_1 , \theta_2 | 调头路径中第一段和第二段圆弧的圆心角,表示每段圆弧绕其圆心的旋转角度(单位:弧度)。 |
\text{turn\_radius} | 调头空间的半径,表示调头空间的圆形区域的半径(单位:米)。 |
v_{\text{max}} | 龙头的最大行进速度,表示在所有把手速度不超过2 m/s条件下的最大龙头速度(单位:米/秒)。 |
d_{ij} | 两个把手之间的距离,表示舞龙队中相邻板凳之间的距离(单位:米)。 |
a | 螺距系数,定义为 a = \frac{p}{2\pi},用于极坐标下描述螺旋线(单位:米/弧度)。 |
问题 2:解题过程及数学建模
问题描述: 在舞龙队沿螺距为 55 cm 的等距螺线顺时针盘入的过程中,确定舞龙队盘入的终止时刻,即使得板凳之间不发生碰撞的最后时刻。输出此时舞龙队的位置和速度,并存放在 result2.xlsx 中。
数学模型
螺线盘入模型: 和问题1一样,我们使用极坐标来描述螺旋线路径,舞龙队沿着螺旋线前进。
碰撞检测模型:
每节板凳有固定长度 220 cm(龙头长度为 341 cm),宽度为 30 cm。相邻板凳通过把手连接。为避免碰撞,板凳之间的间距至少要大于或等于板凳宽度。
两节相邻的板凳的中心距可以通过极坐标下的两点之间的距离公式计算: dij=(ricos(θi)−rjcos(θj))2+(risin(θi)−rjsin(θj))2 其中 i, j 为两节相邻板凳的索引。
终止条件:
当 dij<0.3 米时(即 30 cm),表示两节板凳发生碰撞,此时舞龙队盘入应终止。
数值模拟:
和问题1类似,我们采用数值方法模拟龙头沿螺旋线的运动。对于每一个时间步,计算每节板凳的位置并检测是否发生碰撞。
求解步骤
- 初始化参数:
- 设定初始位置、速度及板凳间距。
- 设置螺线方程参数、板凳长度、宽度等。
- 时间迭代:
- 对于每一个时间步,计算所有板凳的坐标位置。
- 计算相邻板凳之间的距离,检测是否发生碰撞。
- 碰撞检测:
- 对所有相邻板凳计算距离,若任意两个板凳之间的距离小于 0.3 m,则停止迭代,记录时间、位置和速度。
- 输出结果:
- 将终止时刻的舞龙队各部分的位置和速度保存到 Excel 文件 result2.xlsx 中。
- 给出关键时间点(例如0 s、60 s、120 s等)的位置和速度数据。
问题 1:解题过程及数学建模
问题描述: 舞龙队沿螺距为 ()55cm(0.55m) 的等距螺线顺时针盘入,各把手中心均位于螺线上。龙头前把手的行进速度为 1m/s 。初始时,龙头位于螺线第 16 圈 A 点处。需要计算从初始时刻到 300s 的每秒舞龙队的各部分位置和速度,并将结果保存到 Excel 文件中。
数学模型
螺线方程: 等距螺线的方程在极坐标系中可以表示为: r(θ)=r0+aθ
其中:
r 是半径。
θ 是极角。
r0 是起始半径(16圈处的半径)。
a 是螺距系数,可以由螺距 p 表示为 a=p2π=0.552πm/rad 。
- 位置计算: 对于每个时间点 t ,龙头前把手沿螺线移动的距离 s = v \cdot t ,其中 v = 1 m/s。我们可以计算出对应的角度变化: θ(t)=sr(θ)
根据螺线的性质,可以通过数值方法计算每个时间点对应的 r(t) 和 \theta(t) 。
- 坐标转换: 将极坐标转换为直角坐标,得到每个时间点的 x(t) 和 y(t) : x(t)=r(t)⋅cos(θ(t))y(t)=r(t)⋅sin(θ(t))
- 速度计算: 速度可以分解为径向速度和角速度。因为龙头前把手的行进速度是恒定的,所以我们需要计算每个位置的速度矢量。
Python 代码实现
以下是一个用于计算舞龙队位置和速度的 Python 示例代码,并使用 Matplotlib 进行可视化。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 螺旋线参数
p = 0.55 # 螺距 (m)
v = 1.0 # 龙头前把手速度 (m/s)
a = p / (2 * np.pi) # 螺旋系数
# 时间设置
t_end = 300 # 结束时间 (s)
dt = 1 # 时间步长 (s)
time_points = np.arange(0, t_end + dt, dt)
# 初始半径 (假设第16圈的半径为某个r0)
r0 = 16 * p / (2 * np.pi)
# 计算位置和速度
positions = []
velocities = []
for t in time_points:
s = v * t # 沿螺旋线的距离
# 咕咕咕
# 计算速度
# 咕咕咕
# 咕咕咕
# 将数据保存到 Excel
df_positions = pd.DataFrame(positions, columns=['x (m)', 'y (m)'])
df_velocities = pd.DataFrame(velocities, columns=['v (m/s)', 'omega (rad/s)'])
df_positions.to_excel('result1_positions.xlsx', index=False)
df_velocities.to_excel('result1_velocities.xlsx', index=False)
# 可视化
plt.figure(figsize=(8, 8))
x_coords, y_coords = zip(*positions)
plt.plot(x_coords, y_coords, marker='o', markersize=2, linestyle='-')
plt.xlabel('x (m)')
plt.ylabel('y (m)')
plt.title('Dragon Dance Path')
plt.grid(True)
plt.show()
代码说明
- 螺旋线参数设置:设定螺距 p 和速度 v ,计算出螺旋线系数 a 。
- 时间步进计算:每秒计算一次位置和速度,记录每个时间点的 (x, y) 坐标和速度矢量。
- 保存结果:将计算结果保存到 Excel 文件中,方便后续分析和展示。
- 可视化:使用 Matplotlib 生成螺旋线的路径图,展示舞龙队的行进路线。
结果输出
- result1_positions.xlsx:包含从 0 到 300 秒每秒的龙头、龙身、龙尾的 x 和 y 坐标。
- result1_velocities.xlsx:包含从 0 到 300 秒每秒的龙头、龙身、龙尾的速度矢量信息。
- 可视化图表:展示舞龙队沿螺旋线行进的路径。
Python 代码实现
以下是用于问题2的 Python 代码示例,它检测舞龙队盘入时的碰撞并输出结果:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 螺旋线参数
p = 0.55 # 螺距 (m)
v = 1.0 # 龙头前把手速度 (m/s)
a = p / (2 * np.pi) # 螺旋系数
# 板凳参数
bench_length = 2.2 # 板凳长度 (m)
bench_width = 0.3 # 板凳宽度 (m)
num_benches = 223 # 总板凳数
# 时间设置
dt = 1 # 时间步长 (s)
time_points = [0] # 存储时间点
positions = [[(0, 0)]] # 存储每个时间点的所有板凳位置
# 初始半径
r0 = 16 * p / (2 * np.pi)
# 碰撞检测函数
def check_collision(positions, bench_width):
for i in range(len(positions) - 1):
# 咕咕咕
return True
return False
# 计算板凳位置
def calculate_positions(t):
s = v * t # 沿螺旋线的距离
# 咕咕咕
return x, y
# 模拟过程
collision_detected = False
t = 0
while not collision_detected:
t += dt
time_points.append(t)
# 计算每个板凳的新位置
new_positions = []
for i in range(num_benches):
x, y = calculate_positions(t - i * bench_length / v)
new_positions.append((x, y))
# 检查是否发生碰撞
collision_detected = check_collision(new_positions, bench_width)
positions.append(new_positions)
# 找到发生碰撞的时间点
collision_time = time_points[-1]
collision_positions = positions[-1]
# 提取关键板凳位置
key_positions = [collision_positions[0]] # 龙头位置
indices = [1, 51, 101, 151, 201, -1] # 关键板凳索引
for idx in indices:
key_positions.append(collision_positions[idx])
# 保存结果到Excel
df_positions = pd.DataFrame(key_positions, columns=['x (m)', 'y (m)'])
df_positions.to_excel('result2.xlsx', index=False)
# 可视化
plt.figure(figsize=(10, 10))
x_coords, y_coords = zip(*collision_positions)
plt.plot(x_coords, y_coords, marker='o', markersize=2, linestyle='-')
plt.xlabel('x (m)')
plt.ylabel('y (m)')
plt.title('Dragon Dance Path at Collision Time')
plt.grid(True)
plt.show()
代码说明
- 碰撞检测:通过计算相邻板凳之间的距离,如果距离小于板凳宽度(0.3 m),则认为发生碰撞。
- 位置计算:每个时间步都计算所有板凳的位置,模拟板凳的移动路径。
- 结果输出:碰撞发生时,停止计算并保存关键板凳的位置信息到 Excel 文件中。
- 可视化:使用 Matplotlib 可视化舞龙队的路径和碰撞时的位置。
结果输出
- result2.xlsx:包含发生碰撞时舞龙队的龙头、龙身和龙尾的关键位置和速度。
- 可视化图表:展示舞龙队在发生碰撞时的路径。
问题 3:解题过程及数学建模
问题描述: 舞龙队从顺时针盘入调头切换为逆时针盘出,需要一定的调头空间。调头空间为以螺线中心为圆心、直径为 9 m 的圆形区域。目标是确定最小螺距,使得龙头前把手能够沿着相应的螺线盘入到调头空间的边界。
数学模型
调头空间:
调头空间是以螺线中心为圆心,直径为 9m 的圆形区域。半径 R=4.5m 。
需要计算龙头前把手沿螺线轨迹从外圈进入到半径为 4.5m 的区域边界。
螺线方程:
等距螺线的极坐标方程为: r(θ)=r0+aθ 其中:
r 是半径, θ 是极角。
r0 是起始半径, a 是螺距系数,且 a=p2π 。
目标是找到最小的 p 使得螺线轨迹能达到调头空间的边界 R=4.5m 。
最小螺距计算:
咕咕咕~
数值方法:
咕咕咕~
解题步骤
初始化参数:
设定调头空间半径 R=4.5m 。
设置螺线方程参数,初始半径 r0 根据题目设定。
优化螺距:
使用数值优化方法(如二分法)寻找满足螺线到达调头空间边界的最小螺距 p 。
位置计算与验证:
在找到最小螺距 p 后,计算对应的螺线轨迹,验证其是否满足条件。
输出结果:
将结果输出到文件,并可视化调头路径和螺线轨迹。
Python 代码实现
以下是用于问题3的 Python 代码示例,它使用数值方法优化螺距并计算螺线轨迹。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import minimize_scalar
# 参数设置
R = 4.5 # 调头空间半径 (m)
r0 = 16 * 0.55 / (2 * np.pi) # 初始半径,假设在第16圈处
theta_max = 2 * np.pi * 16 # 最大角度假设为16圈
# 定义螺线函数
def spiral_radius(theta, p):
# 咕咕咕
# 目标函数:找到最小的p,使得螺线半径<=R
def objective_function(p):
# 咕咕咕
# 使用优化算法寻找最小螺距p
result = minimize_scalar(objective_function, bounds=(0.1, 1), method='bounded')
# 计算最优螺距p下的螺线轨迹
# 咕咕咕
# 转换为直角坐标
x_coords = radii * np.cos(theta_values)
y_coords = radii * np.sin(theta_values)
# 保存结果到Excel
df_results = pd.DataFrame({'theta': theta_values, 'r (m)': radii, 'x (m)': x_coords, 'y (m)': y_coords})
df_results.to_excel('result3.xlsx', index=False)
# 可视化
plt.figure(figsize=(10, 10))
plt.plot(x_coords, y_coords, label='Spiral Path')
circle = plt.Circle((0, 0), R, color='yellow', alpha=0.3, label='Turn Area')
plt.gca().add_artist(circle)
plt.xlabel('x (m)')
plt.ylabel('y (m)')
plt.title('Minimum Spiral Path to Turn Area')
plt.legend()
plt.grid(True)
plt.axis('equal')
plt.show()
代码说明
- 目标函数:定义一个目标函数,寻找最小的螺距 p 使得螺线轨迹的最大半径等于或刚好达到调头区域的边界。
- 优化过程:使用 scipy.optimize.minimize_scalar 来寻找最优的螺距 p 。
- 位置计算:计算螺线的 x 和 y 坐标,用于可视化和结果输出。
- 可视化:使用 Matplotlib 绘制螺线轨迹和调头区域。
结果输出
- result3.xlsx:包含优化后的螺线轨迹数据,包括每个角度的半径和坐标。
- 可视化图表:展示螺线轨迹和调头区域,验证螺线刚好到达调头区域边界。
问题 4:解题过程及数学建模
问题描述: 舞龙队盘入螺线的螺距为 1.7 m,盘出螺线与盘入螺线关于螺线中心对称。舞龙队在调头空间内完成调头,调头路径由两段相切的圆弧组成,前一段圆弧的半径是后一段的2倍。圆弧与盘入、盘出螺线均相切。问题要求确定是否可以调整圆弧使调头曲线变短,同时保持相切的条件。
目标: 1. 找到使得调头曲线最短的圆弧半径和连接点。
2. 计算从 到−100s到100s 时间内,舞龙队的位置和速度,并输出到 result4.xlsx 文件中。 3. 在论文中给出关键时刻 (、、、、)(−100s、−50s、0s、50s、100s) 龙头前把手和龙身指定位置的速度和位置。
数学模型
螺旋线方程:
盘入螺线和盘出螺线的极坐标方程: rin(θ)=r0+1.7θ2π rout(θ)=r0−1.7θ2π 其中,盘出螺线关于中心对称,且与盘入螺线具有相同的螺距(1.7 m)。
调头路径建模:
调头路径由两段相切的圆弧组成,分别记为弧1和弧2,半径分别为 R_1 和 R_2 = \frac{R_1}{2}。
调头路径要求与盘入螺线和盘出螺线相切,且两段圆弧之间也要相切。相切条件要求几何上相邻曲线具有相同的切线斜率。
优化目标:
咕咕咕~
相切条件:
圆弧与螺线相切的几何约束条件可通过微分求解其斜率相等: drin(θ)dθ=drcircle1(θ)dθ,drout(θ)dθ=drcircle2(θ)dθ
解题步骤
初始化参数:
咕咕咕~
调头路径优化:
咕咕咕~
数值模拟:
从 开始到−100s开始到100s ,使用数值方法模拟龙头和龙身各部分的位置和速度变化。
输出结果:
记录每个时间步的舞龙队各部分位置和速度,将结果保存到 Excel 文件中。
关键时刻的速度和位置结果整理输出。
Python 代码实现
以下是用于问题4的 Python 代码示例,结合了调头路径优化和可视化展示:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import minimize
# 螺旋线和调头参数
p_in = 1.7 # 盘入螺距 (m)
p_out = 1.7 # 盘出螺距 (m)
v = 1.0 # 龙头速度 (m/s)
turn_radius = 4.5 # 调头空间半径 (m)
# 时间设置
t_start = -100
t_end = 100
dt = 1
time_points = np.arange(t_start, t_end + dt, dt)
# 圆弧参数优化目标函数
def objective(R):
# 咕咕咕
# 相切条件的约束
def constraint(R):
R1, R2 = R
return R1 - 2 * R2
# 初始猜测的圆弧半径
initial_guess = [2.5, 1.25]
# 优化问题设置
constraints = {'type': 'eq', 'fun': constraint}
result = minimize(objective, initial_guess, constraints=constraints, bounds=((1, 10), (0.5, 5)))
R1_optimal, R2_optimal = result.x
print(f"优化结果: R1 = {R1_optimal:.4f}, R2 = {R2_optimal:.4f}")
# 模拟舞龙队在调头区域内的运动
def simulate_dragon_motion(R1, R2, time_points):
positions = []
for t in time_points:
if t < 0:
# 咕咕咕
else:
# 咕咕咕
positions.append((x, y))
return positions
positions = simulate_dragon_motion(R1_optimal, R2_optimal, time_points)
# 保存结果到Excel
df_positions = pd.DataFrame(positions, columns=['x (m)', 'y (m)'])
df_positions.to_excel('result4.xlsx', index=False)
# 可视化调头路径
x_coords, y_coords = zip(*positions)
plt.figure(figsize=(10, 10))
plt.plot(x_coords, y_coords, marker='o', markersize=2, linestyle='-', label='Turning Path')
plt.xlabel('x (m)')
plt.ylabel('y (m)')
plt.title('Dragon Dance Turning Path within Turn Area')
plt.grid(True)
plt.legend()
plt.show()
代码说明
- 优化目标:我们使用 scipy.optimize.minimize 函数来最小化调头路径的弧长。
- 相切条件约束:保持两段圆弧相切的条件,即 R1 = 2 \times R2。
- 模拟舞龙队运动:根据优化后的圆弧半径,模拟龙头和龙身的运动路径。
- 结果输出:将结果保存到 Excel 文件 result4.xlsx 中,并生成路径可视化图。
结果输出
- 最优圆弧半径:输出优化后的圆弧半径 R1 和 R2。
- 关键时间点的位置和速度:模拟从 -100 s 到 100 s 的舞龙队运动,并输出对应位置和速度。
- 可视化图表:展示了舞龙队在调头区域内的最优路径。
这种方法结合了优化算法和几何建模,提供了舞龙队调头路径的最优解。通过数值模拟和可视化,展示了不同路径条件下的舞龙队运动,具有重要的学术价值和实际应用潜力。
问题 5:解题过程及数学建模
问题描述: 在舞龙队沿问题 4 设定的路径行进的过程中,龙头的行进速度保持不变。需要确定龙头的最大行进速度,使得舞龙队中所有把手的速度均不超过 2 m/s。
目标: 1. 确定龙头的最大行进速度 vmax ,保证整个舞龙队各把手的速度不超过 2m/s 。
2. 计算每个把手的速度,并调整龙头速度使得其符合速度限制条件。
数学模型
路径描述:
问题4中设定的路径包括盘入螺线、两段相切的圆弧(S形曲线),以及盘出螺线。
路径上任何点的运动速度需要根据龙头的速度来调整,以确保不超过最大速度限制。
速度计算:
假设龙头的行进速度为 v_{\text{head}} ,龙身和龙尾各部分在路径上的速度会因为曲率和旋转而变化。
咕咕咕~
速度约束:
每个把手的速度必须满足 vi≤2m/ s。
这意味着,对于路径上每一点上的每个把手:
Ri⋅ωi≤2 需要调整龙头的速度 vhead 使得上述条件对所有把手都成立。
最大速度的求解:
咕咕咕~
解题步骤
初始化路径和参数:
使用问题4的路径模型,包括盘入螺线、 S 形曲线和盘出螺线。
设定初始龙头速度 vhead=1m/s ,并逐步增加。
计算各把手速度:
对于每一个时间步,计算各把手在路径上的速度。
使用最小二乘法或其他数值方法调整龙头速度 vhead ,保证各把手的速度不超过 2m/s 。
咕咕咕~
输出结果:
记录每个时间步的舞龙队各部分的位置和速度,将结果保存到 Excel 文件 result5.xlsx 中。
Python 代码实现
以下是用于问题5的 Python 代码示例,结合了最大速度求解和可视化展示:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import minimize_scalar
# 调头路径和螺旋线参数
p_in = 1.7 # 盘入螺距 (m)
p_out = 1.7 # 盘出螺距 (m)
turn_radius_1 = 2.5 # 调头路径第一段圆弧半径 (m)
turn_radius_2 = 1.25 # 调头路径第二段圆弧半径 (m)
# 时间设置
t_start = -100
t_end = 100
dt = 1
time_points = np.arange(t_start, t_end + dt, dt)
# 最大速度约束
max_hand_speed = 2.0 # m/s
# 模拟路径计算
def simulate_path(v_head, turn_radius_1, turn_radius_2, time_points):
speeds = []
for t in time_points:
if t < 0:
# 在第一段圆弧
# 咕咕咕
# 在第二段圆弧
omega = v_head / turn_radius_2
speed = turn_radius_2 * omega
else:
# 在直线
speed = v_head
speeds.append(speed)
return speeds
# 目标函数:返回所有把手的最大速度,目标是使其不超过 max_hand_speed
def objective(v_head):
speeds = simulate_path(v_head, turn_radius_1, turn_radius_2, time_points)
max_speed = max(speeds)
return max_speed
# 二分法寻找最大速度
result = minimize_scalar(objective, bounds=(0, 2), method='bounded')
v_max = result.x
print(f"最大龙头速度: {v_max:.4f} m/s")
# 计算最终速度分布
final_speeds = simulate_path(v_max, turn_radius_1, turn_radius_2, time_points)
# 保存结果到Excel
df_speeds = pd.DataFrame({'Time (s)': time_points, 'Speed (m/s)': final_speeds})
df_speeds.to_excel('result5.xlsx', index=False)
# 可视化速度分布
plt.figure(figsize=(10, 6))
plt.plot(time_points, final_speeds, label='Hand Speed')
plt.axhline(max_hand_speed, color='r', linestyle='--', label='Max Allowed Speed')
plt.xlabel('Time (s)')
plt.ylabel('Speed (m/s)')
plt.title('Dragon Dance Hand Speeds Over Time')
plt.legend()
plt.grid(True)
plt.show()
代码说明
- 路径模拟函数 simulate_path:计算舞龙队在每个时间点上的各把手速度。
- 目标函数 objective:返回模拟路径上各把手的最大速度,目的是保持其在允许范围内。
- 最大速度求解:使用 scipy.optimize.minimize_scalar 寻找使各把手速度不超过 2 m/s 的最大龙头速度 v_{\text{max}} 。
- 结果保存与可视化:将计算结果保存到 Excel 文件中,并可视化各把手速度随时间的变化情况。
结果输出
- 最大龙头速度:代码将输出满足条件的最大龙头速度 v_{\text{max}} 。
- 速度分布图:展示舞龙队各把手在调头路径上的速度随时间的变化情况。
- Excel 文件 result5.xlsx:保存每个时间步的各把手速度,便于进一步分析。
24国赛赛前准备:
论文中好的可视化内容至关重要 这里先分享一些国赛数学建模中的常用的可视化内容
数学建模中的可视化分析是一个重要的环节,它帮助研究者和观众更好地理解数据和模型的结果。以下是一些进阶的可视化分析方法和算法,以及相应的Python代码示例:
蒙特卡罗算法
算法介绍:蒙特卡罗算法是一种基于概率和随机性的方法,通过生成大量随机样本来模拟复杂系统的行为或计算数值解。它不依赖于严格的解析解,而是通过随机采样来估计问题的结果。例如,在估计圆周率π的值时,可以在一个正方形内随机生成点,然后计算落在内切圆内的点的比例,利用这个比例估计π的值。蒙特卡罗算法广泛应用于金融风险分析、物理学中的粒子行为模拟、复杂系统的概率分析等领域.
算法示例:
我们可以使用蒙特卡罗算法来估计三维图形的体积。下面是一个简单的Python程序,它使用蒙特卡罗算法来估计一个球体的体积,并使用Matplotlib库进行三维可视化。
import random
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def monte_carlo_volume(n):
count = 0
for i in range(n):
x = random.uniform(-1, 1)
y = random.uniform(-1, 1)
z = random.uniform(-1, 1)
if x**2 + y**2 + z**2 <= 1:
count += 1
return (count / n) * 8
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 10000
volume = monte_carlo_volume(n)
print(f"Estimated volume of the sphere: {volume:.4f}")
xs = []
ys = []
zs = []
colors = []
for i in range(n):
x = random.uniform(-1, 1)
y = random.uniform(-1, 1)
z = random.uniform(-1, 1)
if x**2 + y**2 + z**2 <= 1:
xs.append(x)
ys.append(y)
zs.append(z)
colors.append(z)
ax.scatter(xs, ys, zs, c=colors, cmap='coolwarm', marker='o')
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
- 程序首先定义了一个名为monte_carlo_volume的函数,该函数使用蒙特卡罗算法来估计球体的体积。
- 然后,程序使用monte_carlo_volume函数来估计球体的体积,并将结果打印到控制台上。
- 接下来,程序使用Matplotlib库创建一个3D散点图,该图显示了球体的随机采样点,并根据每个点的z坐标值进行颜色渐变。
可视化效果如下:
部分依赖分析图(Partial Dependence Plot)
部分依赖分析图(Partial Dependence Plot,简称PDP)是一种用于解释复杂机器学习模型的可视化工具。PDP可以帮助我们理解一个或两个特征对模型预测结果的影响,而忽略掉其他特征的影响。这种分析对于提高模型的透明度和可解释性非常有价值。
主要特点和用途
1. 展示特征影响:PDP显示了在保持模型中所有其他特征固定的情况下,一个特征(或两个特征的交互)对预测结果的平均影响。
2. 可解释性:对于复杂的模型(如随机森林、梯度提升机等),PDP帮助解释单个特征如何影响模型的预测,提高了模型的可解释性。
3. 非线性关系和交互效应:PDP特别适合揭示特征与预测目标之间的非线性关系,以及不同特征之间的交互效应。
工作原理
PDP通过对数据集中的特定特征进行多次采样,并保持其他特征不变,然后计算模型对这些样本的预测平均值来生成。
PDP是机器学习领域中一个非常有用的工具,尤其是在需要解释复杂模型的决策过程时。通过使用PDP,数据科学家和分析师可以更好地理解和信任他们的模型预测。图像: 部分依赖分析图的生成需要一个训练好的模型和特定的数据集,这里使用一个简单的合成数据集和一个基本的分类模型来演示。
这是一个部分依赖分析图的示例,它展示了在一个简单的合成数据集上训练的梯度提升分类器中,特征0、特征1以及它们的组合(特征0和1)对模型预测的影响。这种类型的图表非常有用于解释机器学习模型的行为,特别是在识别哪些特征对模型预测最有影响时。
生成这个图表的Python代码如下:
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.inspection import plot_partial_dependence
from sklearn.datasets import make_classification
# 创建合成数据集
X, y = make_classification(n_samples=100, n_features=5, random_state=42)
# 训练梯度提升分类器
clf = GradientBoostingClassifier(n_estimators=50, random_state=42).fit(X, y)
# 绘制部分依赖图
features = [0, 1, (0, 1)]
plot_partial_dependence(clf, X, features, grid_resolution=20)
# 显示图形
plt.suptitle('Partial Dependence Plots')
plt.show()
国赛的进阶可视化图表:成对关系图
成对关系图是一种可视化技术,用于显示数据集中每个变量之间的关系。它通常用于探索数据集中的相关性和分布情况。成对关系图可以用于许多不同的应用程序,例如数据分析、生物学、金融等领域。
下面是一个简单的Python程序,它使用Seaborn库创建一个成对关系图,该图显示了Iris数据集中每个变量之间的关系: iris数据集是一个经典的机器学习数据集,用于分类和聚类等任务。它包含了150个样本,每个样本有四个特征和一个标签。特征是鸢尾花的萼片和花瓣的长度和宽度,单位是厘米。标签是鸢尾花的三个品种之一:山鸢尾、变色鸢尾和维吉尼亚鸢尾。这个数据集是由英国统计学家和生物学家Fisher在1936年发表的论文中提出的,是最早用于评估分类方法的数据集之一。iris数据集在统计学和机器学习领域都有广泛的应用和影响,被认为是一个简单而优美的数据集。
这个程序使用Seaborn库创建一个成对关系图,该图显示了Iris数据集中每个变量之间的关系。程序使用sns.load_dataset函数加载Iris数据集,并使用sns.pairplot函数创建一个成对关系图。
import seaborn as sns
import matplotlib.pyplot as plt
iris = sns.load_dataset("iris")
sns.pairplot(iris, hue="species", markers=["o", "s", "D"])
plt.show()
成对关系图的应用场景包括但不限于以下几个方面:
- 数据分析:成对关系图可以用于显示数据集中每个变量之间的关系,帮助数据分析人员更好地理解数据。
- 生物学:成对关系图可以用于显示基因表达数据的密度和分布情况,帮助生物学家更好地理解基因表达数据。
- 金融:成对关系图可以用于显示股票价格的密度和分布情况,帮助投资者更好地理解股票市场。
其他常用可视化图表
1. 折线图(Line Plot)
用途:展示数据随时间或有序类别变化的趋势。
Python 示例:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]
plt.plot(x, y)
plt.title('Line Plot Example')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
```
2. 柱状图(Bar Chart)
用途:比较不同类别间的数值大小。 Python 示例:
categories = ['Category A', 'Category B', 'Category C']
values = [10, 20, 15]
plt.bar(categories, values)
plt.title('Bar Chart Example')
plt.xlabel('Categories')
plt.ylabel('Values')
plt.show()
3. 散点图(Scatter Plot)
用途:展示两个变量之间的关系。 Python 示例:
x = [5, 7, 8, 7, 2, 17, 2, 9, 4, 11, 12, 9, 6]
y = [99, 86, 87, 88, 100, 86, 103, 87, 94, 78, 77, 85, 86]
plt.scatter(x, y)
plt.title('Scatter Plot Example')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
4. 直方图(Histogram)
用途:展示数据的分布情况。
Python 示例:
data = np.random.normal(0, 1, 1000)
plt.hist(data, bins=30)
plt.title('Histogram Example')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()
5. 饼图(Pie Chart)
用途:显示各部分占整体的比例。
Python 示例:
sizes = [15, 30, 45, 10]
labels = ['Frogs', 'Hogs', 'Dogs', 'Logs']
plt.pie(sizes, labels=labels, autopct='%1.1f%%')
plt.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
plt.title('Pie Chart Example')
plt.show()
6. 热力图(Heatmap)
用途:展示变量间的相关程度或数据的密度。
Python 示例:
data = np.random.rand(10, 10)
sns.heatmap(data, annot=True)
plt.title('Heatmap Example')
plt.show()
7. 箱形图(Box Plot)
用于展示数据的分布和异常值。
Python 示例:
data = np.random.rand(10, 5)
plt.boxplot(data)
plt.title('Box Plot Example')
plt.show()
8. 三维散点图(3D Scatter Plot)
用于在三维空间中展示数据点。
Python 示例:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.random.standard_normal(100)
y = np.random.standard_normal(100)
z = np.random.standard
9.三维曲面图
这种图表非常适合于展示有关两个自变量和一个因变量间复杂关系的数据。
Python 示例: 这是一个三维曲面图的示例,展示了一个由函数 z=sin(x2+y2) 生成的曲面。使用了matplotlib的plot_surface方法来绘制曲面,并通过viridis色彩映射来增强视觉效果。以下是生成这个图形的Python代码:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
# 创建一个图形对象
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
# 生成数据
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
x, y = np.meshgrid(x, y)
z = np.sin(np.sqrt(x**2 + y**2))
# 绘制三维曲面图
surf = ax.plot_surface(x, y, z, cmap=cm.viridis)
# 添加颜色条
fig.colorbar(surf)
# 设置标题
ax.set_title('3D Surface Plot')
# 显示图形
plt.show()
三维曲面的二维投影图
介绍:将三维曲面沿一个或多个轴投影到二维平面上,以查看曲面的不同视角。
示例代码:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.contourf(x, y, z, cmap=cm.viridis)
plt.show()