2024数模国赛D题完整论文
一、问题一模型建立与求解
1.1问题描述
• 潜艇中心位置的深度定位没有误差,即潜艇的深度是一个已知的固定值 。
• 潜艇的水平位置 具有定位误差,均服从正态分布 ,其中 表示水平定位标准差。
• 潜艇的几何尺寸为 (长、宽、高)。
• 深弹的引爆深度为 ,杀伤半径为 。
• 目标是分析投弹最大命中概率与投弹落点平面坐标 及定深引信引爆深度 之间的关系,并找到使得投弹命中概率最大的方案。
1.2坐标系定义
- 潜艇的中心在海平面上的投影为坐标原点 (0,0)。
- 潜艇的水平位置(X,Y) 服从正态分布 。
- 潜艇的上表面深度为。
1.3模型构建
1.3.1 命中判定条件和概率计算
(1)水平位置的概率密度函数
水平坐标 (X,Y)的联合概率密度函数为:
由于潜艇的水平位置有误差,需要对潜艇的所有可能位置进行加权求和。
(2)计算水平命中概率
潜艇的实际位置在水平面上随机分布,水平命中概率 Pin 表示投弹落点在潜艇平面范围内的概率,其计算公式为:
(3)计算垂直命中概率
垂直方向命中概率的计算条件如下:
如果Zd<Ztop,则垂直命中概率Pz1=1,因为引爆深度在潜艇上表面之下。
如果Ztop<Zd<Ztop+R,则垂直命中概率Pz2=1,因为引爆深度在潜艇上表面与杀伤半径之间。
因此,垂直和水平的综合命中概率Phit1为
(4)计算落点在潜艇范围外的命中概率
对于落点在潜艇范围外但在杀伤范围内的概率计算:水平落点在潜艇范围外的概率为Pout=1-Pin。
如果引爆时,深弹与潜艇中心的距离
则概率为:
1.3.2 总命中概率
将所有条件综合,得到总命中概率
1.3.3 最大化命中概率的优化问题
为了找到最佳的投弹方案,需要最大化总命中概率,即
(1)水平落点(x,y)的最优选择:
投弹点应尽可能接近潜艇中心的投影点(0,0),以最大化水平命中概率Pin。
(2)引爆深度Zd的最优选择:
引爆深度应尽可能靠近潜艇上表面或在潜艇的杀伤范围内,以确保垂直命中概率最大化。
1.3.4数值求解
由于积分和优化过程较为复杂,实际应用中可以使用数值方法(如蒙特卡洛模拟或数值积分)进行求解,以确保计算的精确性。
- 通过随机采样潜艇的位置和投弹位置,模拟多个投弹场景。
- 使用优化算法(如梯度下降法、遗传算法等)来最大化命中概率。
1.4参考代码
import numpy as np
from scipy.stats import norm
from scipy.optimize import minimize
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 设置中文字体为 SimHei(黑体)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置字体为SimHei显示中文
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 定义参数
sigma_xy = 120 # 水平定位标准差
h0 = 150 # 潜艇的估计深度
L = 100 # 潜艇的长度
W = 20 # 潜艇的宽度
R = 20 # 杀伤半径
Z_top = h0 - 12.5 # 潜艇上表面
Z_bottom = h0 + 12.5 # 潜艇下表面
beta = np.deg2rad(90) # 航向角
# 生成潜艇的中心位置
def generate_submarine_position(sigma_xy):
X_center = np.random.normal(0, sigma_xy)
Y_center = np.random.normal(0, sigma_xy)
return X_center, Y_center
# 坐标系旋转
def rotate_coordinates(X_d, Y_d, X_center, Y_center, beta):
X_shifted = X_d - X_center
Y_shifted = Y_d - Y_center
X_rotated = X_shifted * np.cos(beta) + Y_shifted * np.sin(beta)
Y_rotated = -X_shifted * np.sin(beta) + Y_shifted * np.cos(beta)
return X_rotated, Y_rotated
# 水平命中判断函数
def is_in_horizontal_range(X_rotated, Y_rotated, L, W):
return (-L / 2 <= X_rotated <= L / 2) and (-W / 2 <= Y_rotated <= W / 2)
# 杀伤半径判断
def is_in_kill_range(X_rotated, Y_rotated, Z_trigger, Z_top, Z_bottom, L, W, R):
dx = max(0, abs(X_rotated) - L / 2)
dy = max(0, abs(Y_rotated) - W / 2)
horizontal_distance = np.sqrt(dx ** 2 + dy ** 2)
if Z_trigger > Z_bottom:
vertical_distance = Z_trigger - Z_bottom
elif Z_trigger < Z_top:
vertical_distance = Z_top - Z_trigger
else:
vertical_distance = 0
total_distance = np.sqrt(horizontal_distance ** 2 + verti-cal_distance ** 2)
return total_distance <= R
# 垂直命中概率
def vertical_hit_probability(Z_trigger, Z_top, Z_bottom, R, X_rotated, Y_rotated, L, W):
if Z_trigger >= Z_top and is_in_horizontal_range(X_rotated, Y_rotated, L, W):
return 1
elif Z_top > Z_trigger >= (Z_top - R) and is_in_horizontal_range(X_rotated, Y_rotated, L, W):
return 1
elif not is_in_horizontal_range(X_rotated, Y_rotated, L, W) and is_in_kill_range(X_rotated, Y_rotated, Z_trigger,
Z_top, Z_bottom, L, W, R):
return 1
else:
return 0
# 水平命中概率计算
def horizontal_hit_probability(X_d, Y_d, sigma_xy, L, W):
P_x = norm.cdf((X_d + L / 2) / sigma_xy) - norm.cdf((X_d - L / 2) / sigma_xy)
P_y = norm.cdf((Y_d + W / 2) / sigma_xy) - norm.cdf((Y_d - W / 2) / sigma_xy)
return P_x * P_y
# 总命中概率
def total_hit_probability(params, sigma_xy, Z_top, Z_bottom, L, W, R):
X_d, Y_d, Z_trigger = params
P_horizontal = horizontal_hit_probability(X_d, Y_d, sigma_xy, L, W)
P_vertical = vertical_hit_probability(Z_trigger, Z_top, Z_bottom, R, X_d, Y_d, L, W)
return -(P_horizontal * P_vertical) # 因为我们使用的是最小化算法,所以要取负值
# 优化函数
def optimize_hit_probability():
initial_guess = [0, 0, Z_top - R] # 初始猜测值
bounds = [(-L, L), (-W, W), (Z_top - R, Z_bottom + R)] # X_d, Y_d, Z_trigger的范围
result = minimize(total_hit_probability, initial_guess, args=(sigma_xy, Z_top, Z_bottom, L, W, R), bounds=bounds)
return result.x, -result.fun
# 可视化命中概率的三维图
def plot_3d_hit_probability():
fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection='3d')
# 生成不同的 X_d, Y_d, Z_trigger 组合
X_d_vals = np.linspace(-L, L, 30)
Y_d_vals = np.linspace(-W, W, 30)
Z_trigger_vals = np.linspace(Z_top - R, Z_bottom + R, 30)
X_d_grid, Y_d_grid, Z_trigger_grid = np.meshgrid(X_d_vals, Y_d_vals, Z_trigger_vals)
hit_prob_grid = np.zeros_like(X_d_grid)
...
二、问题二模型建立与求解
2.1问题描述和建模目标
在问题 2 中,潜艇中心位置的定位在所有方向上都有误差:
潜艇的水平坐标X 和Y 服从正态分布 。
深度坐标Z 服从单边截尾正态分布 ,其中h0 是潜艇中心位置的深度定位值, 是深度误差的标准差,l 是潜艇中心位置的实际深度的最小值。
目标是建立数学模型,给出投弹命中概率的表达式,并针对给定参数设计定深引信引爆深度,使得投弹命中概率最大。
2.2坐标系和变量定义
原点O 位于潜艇中心在海平面上的投影点。
X轴为正东方向,Y 轴为正南方向,Z 轴为垂直向下。
潜艇的几何尺寸为100*20*25m3。
潜艇中心位置的水平坐标误差:。
潜艇中心位置的深度坐标误差:。
2.3命中概率的建模
需要综合考虑水平和深度的定位误差来建立命中概率模型。
2.3.1水平误差的概率密度函数
水平坐标X和Y服从独立的正太分布,其联合概率密度函数为:
2.3.2深度误差的概率密度函数
深度坐标 Z 服从单边截尾正态分布,密度函数为:
2.3.3综合命中概率
根据题目,深弹满足以下条件之一即视为命中潜艇:
- 深弹落点在潜艇平面范围内,且引爆深度位于潜艇上表面的下方,由触发引信引爆。
- 深弹落点在潜艇平面范围内,且引爆深度位于潜艇上表面的上方,同时潜艇在深弹的杀伤范围内,由定深引信引爆。
- 深弹落点在潜艇平面范围外,但引爆深度时潜艇在深弹的杀伤范围内,由定深引信引爆。
假设潜艇的上表面位于处
为了将潜艇的水平范围计算得更加准确,需要考虑以下几个关键点:
a 潜艇中心位置的误差:
潜艇的中心位置服从二维正态分布,意味着潜艇在Z 和Y 方向上具有位置误差。
b 潜艇航向角β
潜艇的水平范围并非固定在X和Y轴上,而是根据β旋转。
我们需要通过如下公式来求旋转潜艇的水平范围,并将潜艇中心位置的误差纳入考虑。
2.3.4潜艇水平位置分布
a 潜艇中心的水平位置服从正态分布,即潜艇的实际中心位置有误差:
其中,σxy是潜艇水平位置的标准差。
b 潜艇的航向角β
潜艇的航向角β 是从正北方向顺时针旋转到潜艇航向的角度。即潜艇的长度轴线与X 轴之间形成角度**β,**因此潜艇的水平范围需要相对于原来的坐标系旋转。
2.3.5投弹坐标的旋转变换
为了计算投弹点是否落在潜艇的水平范围内,我们需要将投弹的坐标转换到潜艇的旋转坐标系中。
2.3.6水平命中判断
2.3.7判断条件
旋转后的潜艇水平范围保持不变,因此可以使用潜艇的长度L 和宽度W 进行命中判断:
即
2.3.8水平命中条件
投弹点与潜艇中心的水平距离决定了水平命中概率。我们假设投弹点与潜艇的水平距离服从正态分布,水平命中概率使用累积分布函数(CDF)来计算:
最终水平命中概率为:
2.3.9垂直命中条件
垂直命中由引爆深度决定。根据引爆深度与潜艇上表面和下表面的关系,我们可以定义以下几种命中条件:
a 触发引信命中
b 定深引信命中
c 杀伤半径命中
如果投弹点位于潜艇水平范围外,但引爆深度距离潜艇较近,且其距离在杀伤半径 以内,则潜艇仍会被定深引信杀伤。
垂直命中概率通过对投弹点与潜艇在垂直方向和水平方向的综合距离进行判断。
2.3.10总命中概率
总命中概率是水平命中概率和垂直命中概率的乘积:
2.3.11引爆深度优化
为了找到最优引爆深度,我们需要在一定的深度范围内搜索,使得命中概率最大化。
搜索的范围为
优化目标:
通过数值优化算法,我们可以找到一个使命中概率最大的引爆深度。
2.3.12多次采样优化
由于潜艇水平位置具有不确定性,我们不能依赖单一的潜艇位置进行优化。因此,使用多次采样来模拟潜艇的不同可能位置,并在每个水平下优化引爆深度。具体步骤为:
2.4参考代码
import numpy as np
from scipy.stats import norm
from scipy.optimize import minimize_scalar
import matplotlib.pyplot as plt
# 定义参数
sigma_xy = 120 # 水平定位标准差
sigma_z = 40 # 垂直方向定位标准差
h0 = 150 # 潜艇的估计深度
R = 20 # 深弹杀伤半径
L = 100 # 潜艇的长度
W = 20 # 潜艇的宽度
Z_top = h0 - 12.5 # 潜艇上表面
Z_bottom = h0 + 12.5 # 潜艇下表面
# 生成潜艇的中心位置
def generate_submarine_position(sigma_xy):
X_center = np.random.normal(0, sigma_xy)
Y_center = np.random.normal(0, sigma_xy)
return X_center, Y_center
# 投弹坐标旋转函数
def rotate_coordinates(X_d, Y_d, X_center, Y_center, beta):
X_shifted = X_d - X_center
Y_shifted = Y_d - Y_center
X_rotated = X_shifted * np.cos(beta) + Y_shifted * np.sin(beta)
Y_rotated = -X_shifted * np.sin(beta) + Y_shifted * np.cos(beta)
return X_rotated, Y_rotated
# 水平命中判断函数
def is_in_horizontal_range(X_rotated, Y_rotated, L, W):
return (-L / 2 <= X_rotated <= L / 2) and (-W / 2 <= Y_rotated <= W / 2)
def is_in_kill_range(X_rotated, Y_rotated, Z_trigger, Z_top, Z_bottom, L, W, R):
dx = max(0, abs(X_rotated) - L / 2)
dy = max(0, abs(Y_rotated) - W / 2)
horizontal_distance = np.sqrt(dx ** 2 + dy ** 2)
if Z_trigger > Z_bottom:
vertical_distance = Z_trigger - Z_bottom
elif Z_trigger < Z_top:
vertical_distance = Z_top - Z_trigger
else:
vertical_distance = 0
total_distance = np.sqrt(horizontal_distance ** 2 + verti-cal_distance ** 2)
return total_distance <= R
# 垂直命中概率的计算
def vertical_hit_probability(Z_trigger, Z_top, Z_bottom, R, X_rotated, Y_rotated, L, W):
if Z_trigger >= Z_top and is_in_horizontal_range(X_rotated, Y_rotated, L, W):
return 1
elif Z_top > Z_trigger >= (Z_top - R) and is_in_horizontal_range(X_rotated, Y_rotated, L, W):
return 1
elif not is_in_horizontal_range(X_rotated, Y_rotated, L, W) and is_in_kill_range(X_rotated, Y_rotated, Z_trigger,
Z_top, Z_bottom, L, W, R):
return 1
else:
return 0
# 水平命中概率计算函数
def horizontal_hit_probability(Xd, Yd, sigma_xy):
P_x = norm.cdf((Xd + L / 2) / sigma_xy) - norm.cdf((Xd - L / 2) / sigma_xy)
P_y = norm.cdf((Yd + W / 2) / sigma_xy) - norm.cdf((Yd - W / 2) / sigma_xy)
return P_x * P_y
# 总命中概率的计算
def total_hit_probability(Z_trigger, Xd, Yd, sigma_xy, sigma_z, Z_top, Z_bottom, L, W, R, beta):
X_center, Y_center = generate_submarine_position(sigma_xy)
X_rotated, Y_rotated = rotate_coordinates(Xd, Yd, X_center, Y_center, beta)
P_horizontal = horizontal_hit_probability(X_rotated, Y_rotated, sigma_xy)
P_vertical = vertical_hit_probability(Z_trigger, Z_top, Z_bottom, R, X_rotated, Y_rotated, L, W)
return P_horizontal * P_vertical
# 优化函数
def optimize_depth_for_position(beta):
result = minimize_scalar(
lambda Z: -total_hit_probability(Z, 0, 0, sigma_xy, sigma_z, Z_top, Z_bottom, L, W, R, beta),
bounds=(Z_top - R, Z_bottom), method='bounded')
return result.x, -result.fun
# 多次采样优化的函数
def optimize_depth_across_samples(beta, num_samples=1000):
optimal_depths = []
hit_probs = []
for _ in range(num_samples):
Z_trigger_optimal, max_hit_prob = opti-mize_depth_for_position(beta)
optimal_depths.append(Z_trigger_optimal)
hit_probs.append(max_hit_prob)
return np.mean(optimal_depths), np.mean(hit_probs)
# 计算最佳定深引信引爆深度和最大命中概率
beta = np.deg2rad(90)
Z_trigger_optimal_avg, max_hit_prob_avg = opti-mize_depth_across_samples(beta)
# 输出通过多次采样计算出的最佳引爆深度和平均最大命中概率
print(f"通过多次采样的最佳定深引信引爆深度: {Z_trigger_optimal_avg:.2f} 米")
print(f"平均最大命中概率: {max_hit_prob_avg:.4f}")
# 生成三维图的可视化
from mpl_toolkits.mplot3d import Axes3D
# 设置投弹坐标范围,用于生成三维命中概率图
X_vals = np.linspace(-L, L, 50)
Y_vals = np.linspace(-W, W, 50)
Z_vals = np.linspace(Z_top - R, Z_bottom + R, 50)
# 创建三维网格
X_grid, Y_grid, Z_grid = np.meshgrid(X_vals, Y_vals, Z_vals)
# 计算命中概率
hit_probs_3D = np.zeros_like(X_grid)
for i in range(len(X_vals)):
for j in range(len(Y_vals)):
for k in range(len(Z_vals)):
hit_probs_3D[i, j, k] = total_hit_probability(Z_grid[i, j, k], X_grid[i, j, k], Y_grid[i, j, k],
sigma_xy, sigma_z, Z_top, Z_bottom, L, W, R, beta)
# 绘制三维图
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 绘制散点图,命中概率用颜色表示
sc = ax.scatter(X_grid.flatten(), Y_grid.flatten(), Z_grid.flatten(), c=hit_probs_3D.flatten(), cmap='viridis',
alpha=0.8)
# 设置标签和标题
ax.set_xlabel('X 轴 (米)', fontsize=12)
ax.set_ylabel('Y 轴 (米)', fontsize=12)
ax.set_zlabel('Z 轴 (米)', fontsize=12)
ax.set_title('三维命中概率分布图', fontsize=14)
# 添加颜色条
cbar = fig.colorbar(sc, ax=ax, shrink=0.5, aspect=5)
cbar.set_label('命中概率', fontsize=12)
# 调整视角
ax.view_init(elev=30, azim=45)
# 显示图像
plt.tight_layout()
plt.show()