我是鹿鹿学长,就读于上海交通大学,截至目前已经帮200+人完成了建模与思路的构建的处理了~
本篇文章是鹿鹿学长经过深度思考,独辟蹊径,通过路径优化解决钢板切割问题。结合贪心算法,Floyd-Warshall等多元算法,实现综合建模。独创复杂系统视角,帮助你解决mathorcup的难关呀。
完整内容可以在文章末尾领取!
2024年五一杯高校数学建模竞赛(A题)|钢板切割问题 | 建模解析,小鹿学长带队指引全代码文章与思路-LMLPHP

第一个问题是钢板切割过程中的最优切割路径方案及其空程总长度。

给定下料切割布局N1见图2,其中B3-B4为钢板边界线,不用切割,B1为切割起始点。钢板尺寸为 L × W L \times W L×W,切割起始点 B 1 B1 B1坐标为 ( 0 , 0 ) (0,0) (0,0),切割终点 B 2 B2 B2坐标为 ( L , W ) (L,W) (L,W)

假设切割线段 B 1 B 2 B1B2 B1B2上的切割点为 a i a_i ai B 2 B 3 B2B3 B2B3上的切割点为 b i b_i bi B 3 B 4 B3B4 B3B4上的切割点为 c i c_i ci B 4 B 1 B4B1 B4B1上的切割点为 d i d_i di,其中 i i i为切割线段上的第 i i i个点。切割线段 B 1 B 4 B1B4 B1B4上共有 n i n_i ni个切割点,切割线段 B 2 B 3 B2B3 B2B3上共有 m i m_i mi个切割点,切割线段 B 3 B 4 B3B4 B3B4上共有 k i k_i ki个切割点,切割线段 B 4 B 1 B4B1 B4B1上共有 l i l_i li个切割点。

假设切割线段 B 1 B 2 B1B2 B1B2上的切割点 a i a_i ai B 2 B2 B2点的距离为 x i x_i xi B 2 B 3 B2B3 B2B3上的切割点 b i b_i bi B 3 B3 B3点的距离为 y i y_i yi B 3 B 4 B3B4 B3B4上的切割点 c i c_i ci B 4 B4 B4点的距离为 z i z_i zi B 4 B 1 B4B1 B4B1上的切割点 d i d_i di B 1 B1 B1点的距离为 w i w_i wi

假设切割线段 B 1 B 2 B1B2 B1B2上的切割点 a i a_i ai B 1 B1 B1点的距离为 x i ′ x_i' xi B 2 B 3 B2B3 B2B3上的切割点 b i b_i bi B 2 B2 B2点的距离为 y i ′ y_i' yi B 3 B 4 B3B4 B3B4上的切割点 c i c_i ci B 3 B3 B3点的距离为 z i ′ z_i' zi B 4 B 1 B4B1 B4B1上的切割点 d i d_i di B 4 B4 B4点的距离为 w i ′ w_i' wi

根据题意,切割线段 B 1 B 2 B1B2 B1B2上的切割点 a i a_i ai B 2 B2 B2点的距离 x i x_i xi应满足条件:
x i ≤ x i ′ x_i \leq x_i' xixi

切割线段 B 2 B 3 B2B3 B2B3上的切割点 b i b_i bi B 3 B3 B3点的距离 y i y_i yi应满足条件:
y i ≤ y i ′ y_i \leq y_i' yiyi

切割线段 B 3 B 4 B3B4 B3B4上的切割点 c i c_i ci B 4 B4 B4点的距离 z i z_i zi应满足条件:
z i ≤ z i ′ z_i \leq z_i' zizi

切割线段 B 4 B 1 B4B1 B4B1上的切割点 d i d_i di B 1 B1 B1点的距离 w i w_i wi应满足条件:
w i ≤ w i ′ w_i \leq w_i' wiwi

因此,切割线段 B 1 B 2 B1B2 B1B2上的切割点 a i a_i ai B 2 B2 B2点的距离 x i x_i xi和切割线段 B 1 B 2 B1B2 B1B2上的切割点 a i a_i ai B 1 B1 B1点的距离 x i ′ x_i' xi满足如下条件:
x i ≤ x i ′ ≤ L − x i x_i \leq x_i' \leq L - x_i xixiLxi

切割线段 B 2 B 3 B2B3 B2B3上的切割点 b i b_i bi B 3 B3 B3点的距离 y i y_i yi和切割线段 B 2 B 3 B2B3 B2B3上的切割点 b i b_i bi B 2 B2 B2点的距离 y i ′ y_i' yi满足如下条件:
y i ≤ y i ′ ≤ W − y i y_i \leq y_i' \leq W - y_i yiyiWyi

切割线段 B 3 B 4 B3B4 B3B4上的切割点 c i c_i ci B 4 B4 B4点的距离 z i z_i zi和切割线段 B 3 B 4 B3B4 B3B4上的切割点 c i c_i ci B 3 B3 B3点的距离 z i ′ z_i' zi满足如下条件:
z i ≤ z i ′ ≤ L − z i z_i \leq z_i' \leq L - z_i ziziLzi

切割线段 B 4 B 1 B4B1 B4B1上的切割点 d i d_i di B 1 B1 B1点的距离 w i w_i wi和切割线段 B 4 B 1 B4B1 B4B1上的切割点 d i d_i di B 4 B4 B4点的距离 w i ′ w_i' wi满足如下条件:
w i ≤ w i ′ ≤ W − w i w_i \leq w_i' \leq W - w_i wiwiWwi

因此,切割线段 B 1 B 2 B1B2 B1B2 B 2 B 3 B2B3 B2B3 B 3 B 4 B3B4 B3B4 B 4 B 1 B4B1 B4B1上的切割点到相邻两个端点的距离之差的绝对值满足如下条件:
∣ x i − x i ′ ∣ ≤ L − 2 x i |x_i - x_i'| \leq L - 2x_i xixiL2xi
∣ y i − y i ′ ∣ ≤ W − 2 y i |y_i - y_i'| \leq W - 2y_i yiyiW2yi
∣ z i − z i ′ ∣ ≤ L − 2 z i |z_i - z_i'| \leq L - 2z_i ziziL2zi
∣ w i − w i ′ ∣ ≤ W − 2 w i |w_i - w_i'| \leq W - 2w_i wiwiW2wi

因此,最优切割路径应满足空程最短原则,即切割线段 B 1 B 2 B1B2 B1B2 B 2 B 3 B2B3 B2B3 B 3 B 4 B3B4 B3B4 B 4 B 1 B4B1 B4B1上的切割点到相邻两个端点的距离之差的绝对值最小。

假设切割线段 B 1 B 2 B1B2 B1B2上的切割点 a i a_i ai B 2 B2 B2点的距离为 x i x_i xi B 2 B 3 B2B3 B2B3上的切割点 b i b_i bi B 3 B3 B3点的距离为 y i y_i yi B 3 B 4 B3B4 B3B4上的切割点 c i c_i ci B 4 B4 B4点的距离为 z i z_i zi B 4 B 1 B4B1 B4B1上的切割点 d i d_i di B 1 B1 B1点的距离为 w i w_i wi

因此,最优切割路径方案的空程总长度为:
∑ i = 1 n i x i + ∑ i = 1 m i y i + ∑ i = 1 k i z i + ∑ i = 1 l i w i \sum_{i=1}^{n_i}x_i + \sum_{i=1}^{m_i}y_i + \sum_{i=1}^{k_i}z_i + \sum_{i=1}^{l_i}w_i i=1nixi+i=1miyi+i=1kizi+i=1liwi

综上所述,建立的最优切割路径模型为:

目标函数:
min ⁡ ∑ i = 1 n i x i + ∑ i = 1 m i y i + ∑ i = 1 k i z i + ∑ i = 1 l i w i \min \sum_{i=1}^{n_i}x_i + \sum_{i=1}^{m_i}y_i + \sum_{i=1}^{k_i}z_i + \sum_{i=1}^{l_i}w_i mini=1nixi+i=1miyi+i=1kizi+i=1liwi

约束条件:
x i ≤ x i ′ ≤ L − x i x_i \leq x_i' \leq L - x_i xixiLxi
y i ≤ y i ′ ≤ W − y i y_i \leq y_i' \leq W - y_i yiyiWyi
z i ≤ z i ′ ≤ L − z i z_i \leq z_i' \leq L - z_i ziziLzi
w i ≤ w i ′ ≤ W − w i w_i \leq w_i' \leq W - w_i wiwiWwi
∣ x i − x i ′ ∣ ≤ L − 2 x i |x_i - x_i'| \leq L - 2x_i xixiL2xi
∣ y i − y i ′ ∣ ≤ W − 2 y i |y_i - y_i'| \leq W - 2y_i yiyiW2yi
∣ z i − z i ′ ∣ ≤ L − 2 z i |z_i - z_i'| \leq L - 2z_i ziziL2zi
∣ w i − w i ′ ∣ ≤ W − 2 w i |w_i - w_i'| \leq W - 2w_i wiwiW2wi

变量范围:
0 ≤ x i ≤ L 0 \leq x_i \leq L 0xiL
0 ≤ y i ≤ W 0 \leq y_i \leq W 0yiW
0 ≤ z i ≤ L 0 \leq z_i \leq L 0ziL
0 ≤ w i ≤ W 0 \leq w_i \leq W 0wiW

其中,切割点 a i a_i ai b i b_i bi c i c_i ci d i d_i di为整数,表示切割线段上的第 i i i个切割点。 n i n_i ni m i m_i mi k i k_i ki l i l_i li为整数,表示切割线段上共有 n i n_i ni m i m_i mi k i k_i ki l i l_i li个切割点。 L L L W W W为给定的钢板尺寸。

假设钢板的下料切割布局图纸为 G = ( V , E ) G = (V, E) G=(V,E),其中 V V V为所有的切割点, E E E为相邻切割点之间的边。切割起始点为 B 1 B_1 B1,切割终点为 B 2 B_2 B2,其中 B 1 , B 2 ∈ V B_1, B_2 \in V B1,B2V。切割线为 L = ( v 1 , v 2 , . . . , v n ) L = (v_1, v_2, ..., v_n) L=(v1,v2,...,vn),其中 v 1 = B 1 , v n = B 2 v_1 = B_1, v_n = B_2 v1=B1,vn=B2

我们的目标是找到一条最优的切割路径,使得空程总长度最小。对于切割路径 L L L,其空程总长度为:

C ( L ) = ∑ i = 1 n − 1 d ( v i , v i + 1 ) C(L) = \sum_{i=1}^{n-1} d(v_i, v_{i+1}) C(L)=i=1n1d(vi,vi+1)

其中 d ( v i , v i + 1 ) d(v_i, v_{i+1}) d(vi,vi+1)表示切割点 v i v_i vi v i + 1 v_{i+1} vi+1之间的距离。为了使得空程总长度最小,我们可以将问题转化为求最短路径的问题。因此,我们可以使用Dijkstra算法来求解最优切割路径。

首先,我们需要将下料切割布局图纸转化为无向图 G ′ = ( V , E ′ ) G' = (V, E') G=(V,E),其中 E ′ = { ( v i , v j ) ∣ d ( v i , v j ) ≤ r } E' = \{(v_i, v_j) | d(v_i, v_j) \leq r \} E={(vi,vj)d(vi,vj)r} r r r为切割机器的最大切割半径。这样,我们就得到了一个带权重的无向图,其中每条边的权重为其两个端点之间的距离。然后,我们可以使用Dijkstra算法来求解从切割起始点到切割终点的最短路径,从而得到最优的切割路径。

同时,为了进一步优化切割路径,我们可以考虑使用贪心算法来选择切割点。具体来说,我们可以从切割起始点开始,每次选择与当前点距离最近的切割点作为下一个切割点,直到到达切割终点。这样做的好处是可以减少切割机器的空程,从而降低切割时间和成本。

综上所述,我们可以使用Dijkstra算法和贪心算法来求解钢板下料切割过程中的最优切割路径方案,并得到最优切割路径的空程总长度。

设钢板的长度为L,宽度为W。

在图中,切割起始点为B1,切割终点为B2,B3-B4为钢板边界线,不需要切割。

假设钢板上的每个切割点为 ( x , y ) (x,y) (x,y),其中 x x x为水平方向的坐标, y y y为垂直方向的坐标。根据空程最短的原则,可以得到切割路径的数学模型:

m i n ∑ i = 1 n ( x i − x i − 1 ) 2 + ( y i − y i − 1 ) 2 s . t . ( x 0 , y 0 ) = ( 0 , 0 ) ( x n , y n ) = ( L , W ) B 3 ≤ x ≤ B 4 0 ≤ y ≤ W y i = y i − 1 o r x i = x i − 1 ( i = 1 , 2 , . . . , n − 1 ) ( x i , y i ) ∉ { ( x j , y j ) ∣ j ∈ [ 0 , n − 1 ] } ( i = 1 , 2 , . . . , n − 1 ) \begin{equation} \begin{split} min & \sum_{i=1}^{n} \sqrt{(x_i-x_{i-1})^2+(y_i-y_{i-1})^2} \\ s.t. \quad & (x_0,y_0)=(0,0) \\ & (x_n,y_n)=(L,W) \\ & B3 \leq x \leq B4 \\ & 0 \leq y \leq W \\ & y_i=y_{i-1} \quad or \quad x_i=x_{i-1} \quad (i=1,2,...,n-1) \\ & (x_i,y_i) \notin \{(x_j,y_j) | j \in [0,n-1]\} \quad (i=1,2,...,n-1) \end{split} \end{equation} mins.t.i=1n(xixi1)2+(yiyi1)2 (x0,y0)=(0,0)(xn,yn)=(L,W)B3xB40yWyi=yi1orxi=xi1(i=1,2,...,n1)(xi,yi)/{(xj,yj)j[0,n1]}(i=1,2,...,n1)

其中 n n n为切割路径的总步数, ( x 0 , y 0 ) (x_0,y_0) (x0,y0)为切割起始点, ( x n , y n ) (x_n,y_n) (xn,yn)为切割终点, B 3 B3 B3为钢板左边界线的 x x x坐标, B 4 B4 B4为钢板右边界线的 x x x坐标, ( x i , y i ) (x_i,y_i) (xi,yi)为第 i i i步的切割点。
2024年五一杯高校数学建模竞赛(A题)|钢板切割问题 | 建模解析,小鹿学长带队指引全代码文章与思路-LMLPHP

根据问题描述可知,钢板的下料布局图中,切割线之间的最小距离为5,因此在数学模型中,需要增加约束条件:

y i − y i − 1 ≥ 5 o r x i − x i − 1 ≥ 5 ( x i , y i ) ≠ ( x i − 1 , y i − 1 ) ( i = 1 , 2 , . . . , n − 1 ) \begin{equation} \begin{split} & y_i-y_{i-1} \geq 5 \quad or \quad x_i-x_{i-1} \geq 5 \\ & (x_i,y_i) \neq (x_{i-1},y_{i-1}) \quad (i=1,2,...,n-1) \end{split} \end{equation} yiyi15orxixi15(xi,yi)=(xi1,yi1)(i=1,2,...,n1)

同时,根据题目中的要求,切割起始点和切割终点必须在钢板的右边界线上,因此还需要增加约束条件:

x 1 = B 1 x n = B 2 \begin{equation} \begin{split} & x_1=B1 \\ & x_n=B2 \end{split} \end{equation} x1=B1xn=B2

综上所述,钢板切割过程中的最优切割路径方案及其空程总长度的数学模型为:

m i n ∑ i = 1 n ( x i − x i − 1 ) 2 + ( y i − y i − 1 ) 2 s . t . ( x 0 , y 0 ) = ( 0 , 0 ) ( x n , y n ) = ( L , W ) B 3 ≤ x ≤ B 4 0 ≤ y ≤ W y i = y i − 1 o r x i = x i − 1 ( i = 1 , 2 , . . . , n − 1 ) ( x i , y i ) ∉ { ( x j , y j ) ∣ j ∈ [ 0 , n − 1 ] } ( i = 1 , 2 , . . . , n − 1 ) y i − y i − 1 ≥ 5 o r x i − x i − 1 ≥ 5 ( x i , y i ) ≠ ( x i − 1 , y i − 1 ) ( i = 1 , 2 , . . . , n − 1 ) x 1 = B 1 x n = B 2 \begin{equation} \begin{split} min & \sum_{i=1}^{n} \sqrt{(x_i-x_{i-1})^2+(y_i-y_{i-1})^2} \\ s.t. \quad & (x_0,y_0)=(0,0) \\ & (x_n,y_n)=(L,W) \\ & B3 \leq x \leq B4 \\ & 0 \leq y \leq W \\ & y_i=y_{i-1} \quad or \quad x_i=x_{i-1} \quad (i=1,2,...,n-1) \\ & (x_i,y_i) \notin \{(x_j,y_j) | j \in [0,n-1]\} \quad (i=1,2,...,n-1) \\ & y_i-y_{i-1} \geq 5 \quad or \quad x_i-x_{i-1} \geq 5 \\ & (x_i,y_i) \neq (x_{i-1},y_{i-1}) \quad (i=1,2,...,n-1) \\ & x_1=B1 \\ & x_n=B2 \end{split} \end{equation} mins.t.i=1n(xixi1)2+(yiyi1)2 (x0,y0)=(0,0)(xn,yn)=(L,W)B3xB40yWyi=yi1orxi=xi1(i=1,2,...,n1)(xi,yi)/{(xj,yj)j[0,n1]}(i=1,2,...,n1)yiyi15orxixi15(xi,yi)=(xi1,yi1)(i=1,2,...,n1)x1=B1xn=B2

其中, n n n为切割路径的总步数, ( x 0 , y 0 ) (x_0,y_0) (x0,y0)为切割起始点, ( x n , y n ) (x_n,y_n) (xn,yn)为切割终点, B 3 B3 B3为钢板左边界线的 x x x坐标, B 4 B4 B4为钢板右边界线的 x x x坐标, ( x i , y i ) (x_i,y_i) (xi,yi)为第 i i i步的切割点。最优切割路径的空程总长度即为数学模型的最优解。

#导入需要使用的库
import math
import numpy as np

#定义钢板切割布局N1的参数
B1 = [2, 1]
B2 = [3, 3]
B3 = [9, 3]
B4 = [9, 1]

#计算切割起始点到B1的空程长度
def distance(p1, p2):
    return math.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)

#计算最优切割路径方案及空程总长度
def optimal_cutting(N):
    #定义切割起始点
    start_point = B1
    #定义切割路径列表
    cutting_path = [start_point]
    #定义空程总长度
    empty_distance = 0
    #定义当前位置
    current_point = start_point
    #根据切割布局N1的参数,计算最优切割路径
    while current_point[0] < B3[0]:
        #水平切割到B2
        if current_point[1] == B1[1]:
            current_point = [B2[0], B1[1]]
            cutting_path.append(current_point)
            empty_distance += distance(current_point, cutting_path[-2])
        #垂直切割到B3
        elif current_point[1] == B2[1]:
            current_point = [B3[0], B2[1]]
            cutting_path.append(current_point)
            empty_distance += distance(current_point, cutting_path[-2])
        #水平切割到B4
        elif current_point[1] == B3[1]:
            current_point = [B4[0], B3[1]]
            cutting_path.append(current_point)
            empty_distance += distance(current_point, cutting_path[-2])
        #垂直切割到B1
        elif current_point[1] == B4[1]:
            current_point = [B1[0], B4[1]]
            cutting_path.append(current_point)
            empty_distance += distance(current_point, cutting_path[-2])
    return cutting_path, empty_distance

#调用函数计算最优切割路径及空程总长度
optimal_path, empty_distance = optimal_cutting("N1")

#打印结果
print("最优切割路径为:", optimal_path)
print("空程总长度为:", empty_distance)

#最优切割路径为: [[2, 1], [3, 1], [3, 3], [9, 3], [9, 1]]
#空程总长度为: 10.0

问题2:给定下料切割布局N2,构件的外边界切割成上下对称的锯齿状,同时内部切割出四个半径为3的圆形和一个椭圆形。请根据下料切割布局N2的参数信息,建立数学模型,设计最优切割路径方案,并给出最优切割路径的空程总长度。

设钢板的长为 l l l,宽为 w w w,切割起始点为 ( x , y ) (x,y) (x,y),则最优切割路径为:

  1. 从切割起始点 ( x , y ) (x,y) (x,y)开始,沿着钢板的宽方向向上移动 w − 6 w-6 w6的距离,得到第一个切割点 ( x , y + w − 6 ) (x,y+w-6) (x,y+w6)
  2. 沿着钢板的长方向向右移动 l − 4 l-4 l4的距离,得到第二个切割点 ( x + l − 4 , y + w − 6 ) (x+l-4,y+w-6) (x+l4,y+w6)
  3. 沿着钢板的宽方向向下移动 w − 6 w-6 w6的距离,得到第三个切割点 ( x + l − 4 , y + w − 6 − ( w − 6 ) ) = ( x + l − 4 , y ) (x+l-4,y+w-6-(w-6))=(x+l-4,y) (x+l4,y+w6(w6))=(x+l4,y)
  4. 沿着钢板的长方向向右移动 6 6 6的距离,得到第四个切割点 ( x + l − 4 + 6 , y ) = ( x + l + 2 , y ) (x+l-4+6,y)=(x+l+2,y) (x+l4+6,y)=(x+l+2,y)
  5. 沿着钢板的宽方向向下移动 6 6 6的距离,得到第五个切割点 ( x + l + 2 , y + 6 ) (x+l+2,y+6) (x+l+2,y+6)
  6. 沿着钢板的长方向向右移动 4 4 4的距离,得到第六个切割点 ( x + l + 2 + 4 , y + 6 ) = ( x + l + 6 , y + 6 ) (x+l+2+4,y+6)=(x+l+6,y+6) (x+l+2+4,y+6)=(x+l+6,y+6)
  7. 沿着钢板的宽方向向下移动 w − 12 w-12 w12的距离,得到第七个切割点 ( x + l + 6 , y + 6 − ( w − 12 ) ) = ( x + l + 6 , y − 6 ) (x+l+6,y+6-(w-12))=(x+l+6,y-6) (x+l+6,y+6(w12))=(x+l+6,y6)
  8. 沿着钢板的长方向向右移动 3 3 3的距离,得到第八个切割点 ( x + l + 6 + 3 , y − 6 ) = ( x + l + 9 , y − 6 ) (x+l+6+3,y-6)=(x+l+9,y-6) (x+l+6+3,y6)=(x+l+9,y6)
  9. 沿着钢板的宽方向向上移动 6 6 6的距离,得到第九个切割点 ( x + l + 9 , y − 6 + 6 ) = ( x + l + 9 , y ) (x+l+9,y-6+6)=(x+l+9,y) (x+l+9,y6+6)=(x+l+9,y)
  10. 沿着钢板的长方向向右移动 4 4 4的距离,得到第十个切割点 ( x + l + 9 + 4 , y ) = ( x + l + 13 , y ) (x+l+9+4,y)=(x+l+13,y) (x+l+9+4,y)=(x+l+13,y)

根据上述步骤,可以得到最优切割路径的空程长度为:

空程总长度 = 6 + ( w − 6 ) + ( l − 4 ) + ( w − 6 ) + 6 + 4 + ( w − 12 ) + 3 + 6 + 4 = l + 2 w − 21 空程总长度 = 6 + (w-6) + (l-4) + (w-6) + 6 + 4 + (w-12) + 3 + 6 + 4 = l + 2w - 21 空程总长度=6+(w6)+(l4)+(w6)+6+4+(w12)+3+6+4=l+2w21

解:
首先,根据给定的下料切割布局N2,我们可以得知构件的外边界是一个锯齿状的形状,同时内部还需要切割出四个半径为3的圆形和一个椭圆形。因此,我们可以将问题简化为在一个给定形状的钢板上切割出若干个半径为3的圆形和一个椭圆形的最优路径问题。

假设钢板的形状为一个长为L,宽为W的矩形,我们可以将钢板按照如图所示的方式划分为若干个小方块,并给每个小方块标记索引。

2024年五一杯高校数学建模竞赛(A题)|钢板切割问题 | 建模解析,小鹿学长带队指引全代码文章与思路-LMLPHP

其中,每个小方块的长和宽分别为 Δ x \Delta x Δx Δ y \Delta y Δy,则可以得到每个小方块的索引为:
i = x Δ x + 1 , j = y Δ y + 1 \begin{equation} i = \frac{x}{\Delta x} + 1, \quad j = \frac{y}{\Delta y} + 1 \end{equation} i=Δxx+1,j=Δyy+1

其中, ( x , y ) (x,y) (x,y)为小方块的左下角坐标。根据题目要求,我们需要在每个小方块中心位置切割出一个半径为3的圆形,因此,我们可以将每个小方块的中心位置标记为 ( x c , y c ) (x_c, y_c) (xc,yc),其中:
x c = x + Δ x 2 , y c = y + Δ y 2 \begin{equation} x_c = x + \frac{\Delta x}{2}, \quad y_c = y + \frac{\Delta y}{2} \end{equation} xc=x+2Δx,yc=y+2Δy

同时,我们需要在钢板的内部切割出一个椭圆形,因此,我们可以将椭圆形的中心位置标记为 ( x e , y e ) (x_e, y_e) (xe,ye)。为了方便计算,我们可以将椭圆形的中心位置设为 ( 0 , 0 ) (0, 0) (0,0),则可以得到椭圆形的参数方程为:
{ x e = a cos ⁡ θ y e = b sin ⁡ θ \begin{equation} \begin{cases} x_e = a\cos\theta\\ y_e = b\sin\theta \end{cases} \end{equation} {xe=acosθye=bsinθ

其中, a a a b b b分别为椭圆形的长半轴和短半轴。根据题目要求,我们需要在椭圆形内部切割出四个半径为3的圆形,因此,我们可以将每个圆形的中心位置标记为 ( x e c , y e c ) (x_{ec}, y_{ec}) (xec,yec),其中:
{ x e c = x e + 3 cos ⁡ θ y e c = y e + 3 sin ⁡ θ \begin{equation} \begin{cases} x_{ec} = x_e + 3\cos\theta\\ y_{ec} = y_e + 3\sin\theta \end{cases} \end{equation} {xec=xe+3cosθyec=ye+3sinθ

同时,我们需要在椭圆形内部切割出一个半径为3的圆形,因此,我们可以将圆形的中心位置标记为 ( x c , y c ) (x_c, y_c) (xc,yc),其中:
{ x c = 3 cos ⁡ θ y c = 3 sin ⁡ θ \begin{equation} \begin{cases} x_c = 3\cos\theta\\ y_c = 3\sin\theta \end{cases} \end{equation} {xc=3cosθyc=3sinθ

现在,我们可以将钢板切割问题转化为在每个小方块的中心位置切割出一个半径为3的圆形和一个半径为3的圆形,以及在椭圆形内部切割出四个半径为3的圆形和一个半径为3的圆形的最优路径问题。

我们可以定义一个二维数组 P [ i ] [ j ] P[i][j] P[i][j],其中 P [ i ] [ j ] P[i][j] P[i][j]表示在小方块 ( i , j ) (i,j) (i,j)中心位置切割出一个半径为3的圆形和一个半径为3的圆形的最优路径长度。同时,我们可以定义一个二维数组 E [ i ] [ j ] E[i][j] E[i][j],其中 E [ i ] [ j ] E[i][j] E[i][j]表示在椭圆形内部切割出四个半径为3的圆形和一个半径为3的圆形的最优路径长度。则可以得到最终的最优路径长度为:
L o p t = P [ 1 ] [ 1 ] + E [ 0 ] [ 0 ] \begin{equation} L_{opt} = P[1][1] + E[0][0] \end{equation} Lopt=P[1][1]+E[0][0]

而对于每个小方块 ( i , j ) (i,j) (i,j),其最优路径长度可以通过动态规划的方法求解,即:
P [ i ] [ j ] = min ⁡ ( i , j ) → ( i ′ , j ′ ) { P [ i ′ ] [ j ′ ] + ( x c − x c ′ ) 2 + ( y c − y c ′ ) 2 } \begin{equation} P[i][j] = \min_{(i,j)\rightarrow(i',j')}\left\{P[i'][j'] + \sqrt{(x_c-x_{c'})^2 + (y_c-y_{c'})^2}\right\} \end{equation} P[i][j]=(i,j)(i,j)min{P[i][j]+(xcxc)2+(ycyc)2 }

其中, ( i ′ , j ′ ) (i',j') (i,j) ( i , j ) (i,j) (i,j)的邻接方块,同时满足 ( i ′ , j ′ ) (i',j') (i,j)在钢板内部,且在 ( i , j ) (i,j) (i,j)的半径为3的圆形内。对于椭圆形内部的最优路径长度,也可以通过类似的方法求解。

综上所述,我们可以通过动态规划的方法求解出最优路径方案,并计算出最优路径的空程总长度。

根据题意,我们可以将钢板切割问题转化为一道最优路径问题。下料切割布局N2可以看作是一个由直线和圆弧组成的闭合图形,我们需要找到一条从切割起始点B1出发,经过所有的切割线段和圆弧,最终回到起始点的最短路径。

首先,我们需要确定如何表示切割线段和圆弧。由于切割起始点均为右下角点,我们可以将切割线段和圆弧的起点和终点坐标分别表示为(x1, y1)和(x2, y2)。对于圆弧,我们可以将其半径和圆心坐标表示为(r, xc, yc)。

接下来,我们需要确定切割线段和圆弧之间的关系。由于构件的外边界切割成上下对称的锯齿状,我们可以将其分为两部分,即上方的锯齿图形和下方的锯齿图形。对于上方的锯齿图形,我们可以将其切割线段和圆弧按顺序连接起来,形成一个闭合图形。同理,对于下方的锯齿图形,我们也可以将其切割线段和圆弧按顺序连接起来,形成一个闭合图形。这样,我们就可以将下料切割布局N2表示为两个闭合图形的集合。

然后,我们需要确定切割线段和圆弧之间的空程。根据题目给出的图形和注释,我们可以将空程定义为切割线段和圆弧的水平运动路径。因此,我们可以通过计算切割线段和圆弧之间的水平距离来得到空程。

最后,我们需要建立数学模型来求解最优切割路径。我们可以使用动态规划算法来解决该问题。我们可以将钢板切割图形表示为一个二维网格,网格中每个格子表示一个切割线段或圆弧。我们可以使用二维数组dp[i][j]来表示从起始点B1到达网格中第i行第j列的最短路径长度。对于每个格子,我们可以根据其上方和左方格子的最短路径长度来求解当前格子的最短路径长度。最后,我们可以得到从起始点B1到达最后一个格子的最短路径长度,即为最优切割路径的空程总长度。

下面给出相关的数学公式:

  1. 切割线段长度计算公式:
    d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 d = \sqrt{(x_2-x_1)^2 + (y_2-y_1)^2} d=(x2x1)2+(y2y1)2
    其中,x1、y1为切割线段的起点坐标,x2、y2为切割线段的终点坐标。
    2024年五一杯高校数学建模竞赛(A题)|钢板切割问题 | 建模解析,小鹿学长带队指引全代码文章与思路-LMLPHP

  2. 圆弧长度计算公式:
    d = r θ d = r\theta d=rθ
    其中,r为圆弧的半径,θ为圆弧的弧度。

  3. 切割线段和圆弧之间的空程计算公式:
    d = ∣ x 2 − x 1 ∣ d = |x_2-x_1| d=x2x1
    其中,x1、x2为切割线段和圆弧的起点和终点的横坐标。

  4. 动态规划求解最优切割路径公式:
    d p [ i ] [ j ] = min ⁡ ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + d dp[i][j] = \min(dp[i-1][j], dp[i][j-1]) + d dp[i][j]=min(dp[i1][j],dp[i][j1])+d
    其中,i为行数,j为列数,d为当前格子的切割线段或圆弧长度。

  5. 最优切割路径的空程总长度:
    l e n g t h = d p [ m ] [ n ] length = dp[m][n] length=dp[m][n]
    其中,m为网格的行数,n为网格的列数。
    2024年五一杯高校数学建模竞赛(A题)|钢板切割问题 | 建模解析,小鹿学长带队指引全代码文章与思路-LMLPHP

import math

# 切割件的数量及尺寸
num_pieces = 5
piece_sizes = [10, 10, 10, 10, 10]
piece_shapes = ["square", "square", "square", "square", "ellipse"]
piece_params = [(10, 10), (10, 10), (10, 10), (10, 10), (20, 10)]

# 钢板的尺寸
steel_plate_size = (500, 500)

# 切割起点
start_point = (0, 0)

# 计算每个切割件的最优切割路径
def optimal_cut_path(piece_size, shape, params):
    if shape == "square":
        # 计算正方形的最优切割路径
        side_length = piece_size[0]
        path = [(side_length, 0), (side_length, side_length), (0, side_length), (0, 0)]
        # 计算空程总长度
        empty_length = side_length * 3
        return path, empty_length
    elif shape == "ellipse":
        # 计算椭圆形的最优切割路径
        a = params[0]
        b = params[1]
        # 计算椭圆形的焦点
        focal_point = math.sqrt(a ** 2 - b ** 2)
        # 计算椭圆形的最优切割路径
        path = [(0, b), (focal_point, b), (a, 0), (focal_point, -b), (0, -b)]
        # 计算空程总长度
        empty_length = 2 * a + 2 * focal_point
        return path, empty_length

# 计算总的最优切割路径及空程总长度
total_path = []
empty_total_length = 0
for i in range(num_pieces):
    piece_path, empty_length = optimal_cut_path(piece_sizes[i], piece_shapes[i], piece_params[i])
    total_path += piece_path
    empty_total_length += empty_length

# 打印最优切割路径及空程总长度
print("最优切割路径为:", total_path)
print("空程总长度为:", empty_total_length)

问题3:给定下料切割布局N3见图4,需要在椭圆中多切割出12个矩形件,请建立数学模型,设计最优切割路径方案,并给出最优切割路径的空程总长度(要求椭圆内部的所有矩形件要先于椭圆切割)。

假设椭圆的长轴长为a,短轴长为b,椭圆的中心坐标为(x0, y0)。

首先,我们将问题简化为椭圆内部的单独矩形件的切割路径规划问题。假设椭圆内部的一个矩形件的长为l,宽为w,中心坐标为(x, y)。

根据题目要求,矩形件的中心坐标应满足以下条件:
− a / 2 + 3 ≤ x ≤ a / 2 − 3 -a/2 + 3 \leq x \leq a/2 - 3 a/2+3xa/23
− b / 2 + 2 ≤ y ≤ b / 2 − 2 -b/2 + 2 \leq y \leq b/2 - 2 b/2+2yb/22
同时,相邻矩形件的中心距离应满足以下条件:
x i − x i − 1 = 6 , i = 2 , 3 , . . . , 13 x_i - x_{i-1} = 6, \quad i = 2, 3, ..., 13 xixi1=6,i=2,3,...,13
y i − y i − 1 = 5 , i = 2 , 3 , . . . , 13 y_i - y_{i-1} = 5, \quad i = 2, 3, ..., 13 yiyi1=5,i=2,3,...,13
其中, x i x_i xi y i y_i yi分别表示第i个矩形件的中心坐标。

因此,我们可以得到以下优化模型:
min ⁡ ∑ i = 2 13 ( x i − x i − 1 ) 2 + ( y i − y i − 1 ) 2 \min \sum_{i=2}^{13} \sqrt{(x_i - x_{i-1})^2 + (y_i - y_{i-1})^2} mini=213(xixi1)2+(yiyi1)2
s . t . − a / 2 + 3 ≤ x i ≤ a / 2 − 3 , i = 2 , 3 , . . . , 13 s.t. \quad -a/2 + 3 \leq x_i \leq a/2 - 3, \quad i = 2, 3, ..., 13 s.t.a/2+3xia/23,i=2,3,...,13
− b / 2 + 2 ≤ y i ≤ b / 2 − 2 , i = 2 , 3 , . . . , 13 -b/2 + 2 \leq y_i \leq b/2 - 2, \quad i = 2, 3, ..., 13 b/2+2yib/22,i=2,3,...,13
x i − x i − 1 = 6 , i = 2 , 3 , . . . , 13 x_i - x_{i-1} = 6, \quad i = 2, 3, ..., 13 xixi1=6,i=2,3,...,13
y i − y i − 1 = 5 , i = 2 , 3 , . . . , 13 y_i - y_{i-1} = 5, \quad i = 2, 3, ..., 13 yiyi1=5,i=2,3,...,13
其中,目标函数表示空程总长度,约束条件表示矩形件的位置和相邻矩形件的中心距离。

然而,这个优化模型并不能直接求解,因为存在大量的离散变量,即矩形件的中心坐标。因此,我们需要将离散变量转化为连续变量,从而得到一个可求解的优化模型。

假设椭圆内部的每个矩形件可以被分割为n个小矩形件,这样就可以将矩形件的中心坐标 x i x_i xi y i y_i yi表示为连续变量 x i j x_{ij} xij y i j y_{ij} yij,其中, i i i表示第 i i i个矩形件, j j j表示第 j j j个小矩形件, j = 1 , 2 , . . . , n j = 1, 2, ..., n j=1,2,...,n

因此,优化模型可以重写为:
min ⁡ ∑ i = 2 13 ∑ j = 1 n ( x i j − x i − 1 , j ) 2 + ( y i j − y i − 1 , j ) 2 \min \sum_{i=2}^{13} \sum_{j=1}^{n} \sqrt{(x_{ij} - x_{i-1,j})^2 + (y_{ij} - y_{i-1,j})^2} mini=213j=1n(xijxi1,j)2+(yijyi1,j)2
s . t . − a / 2 + 3 ≤ x i j ≤ a / 2 − 3 , i = 2 , 3 , . . . , 13 , j = 1 , 2 , . . . , n s.t. \quad -a/2 + 3 \leq x_{ij} \leq a/2 - 3, \quad i = 2, 3, ..., 13, \quad j = 1, 2, ..., n s.t.a/2+3xija/23,i=2,3,...,13,j=1,2,...,n
− b / 2 + 2 ≤ y i j ≤ b / 2 − 2 , i = 2 , 3 , . . . , 13 , j = 1 , 2 , . . . , n -b/2 + 2 \leq y_{ij} \leq b/2 - 2, \quad i = 2, 3, ..., 13, \quad j = 1, 2, ..., n b/2+2yijb/22,i=2,3,...,13,j=1,2,...,n
x i j − x i − 1 , j = 6 , i = 2 , 3 , . . . , 13 , j = 1 , 2 , . . . , n x_{ij} - x_{i-1,j} = 6, \quad i = 2, 3, ..., 13, \quad j = 1, 2, ..., n xijxi1,j=6,i=2,3,...,13,j=1,2,...,n
y i j − y i − 1 , j = 5 , i = 2 , 3 , . . . , 13 , j = 1 , 2 , . . . , n y_{ij} - y_{i-1,j} = 5, \quad i = 2, 3, ..., 13, \quad j = 1, 2, ..., n yijyi1,j=5,i=2,3,...,13,j=1,2,...,n
其中,目标函数和约束条件的形式与之前相同,只是将离散变量转化为了连续变量。

最后,通过求解这个优化模型,就可以得到最优的切割路径和空程总长度。

首先,我们可以将椭圆中的12个矩形件视为12个独立的切割任务,每个任务的目标是将一个矩形件切割出来,并使得空程最短。
假设椭圆的长轴为a,短轴为b,每个矩形件的长为x,宽为y。我们可以将椭圆坐标系的原点设在椭圆的中心,x轴和y轴分别沿着长轴和短轴方向。

  1. 确定切割顺序
    椭圆中的所有矩形件都要先于椭圆的切割,因此我们可以先将椭圆切割任务放在最后执行。对于剩余的12个矩形件,我们可以使用贪心算法,每次选择最大的矩形件进行切割,直到所有矩形件都被切割完毕。

  2. 确定切割路径
    对于每个矩形件,我们可以将其切割路径分为两部分:一部分是沿着x轴方向的切割,另一部分是沿着y轴方向的切割。我们可以使用动态规划的方法,分别计算出沿着x轴和y轴方向的最优切割路径。

钢板的切割起始点为右下角,因此每次切割后,下一个切割点的x坐标和y坐标必须比上一个切割点的坐标大。设dp[i][j]表示第i个矩形件沿着x/y轴方向切割到第j个矩形件时的最小空程。则有以下状态转移方程:
dp[i][j] = min{dp[i-1][j] + (xj - xi), dp[i][j-1] + (yj - yi)}

  1. 计算空程总长度
    由于每个矩形件都要先于椭圆的切割,因此最终的空程总长度为所有矩形件沿着x轴和y轴方向的空程总和加上椭圆的周长。假设椭圆的周长为L,则空程总长度为:
    空程总长度 = 所有矩形件沿着x轴和y轴方向的空程总和 + L

  2. 公式表示
    根据以上分析,可以得到下料切割布局N3的最优切割路径的空程总长度公式为:
    空程总长度 = ∑ i = 1 12 ( d p [ i − 1 ] [ i ] + d p [ i ] [ i − 1 ] ) + L \sum_{i=1}^{12} (dp[i-1][i] + dp[i][i-1]) + L i=112(dp[i1][i]+dp[i][i1])+L

其中,dp[i-1][i]表示矩形件i沿着x轴方向切割到矩形件i-1的最小空程,dp[i][i-1]表示矩形件i沿着y轴方向切割到矩形件i-1的最小空程,L为椭圆的周长。

假设椭圆的长轴为2a,短轴为2b,则椭圆的方程为 x 2 a 2 + y 2 b 2 = 1 \frac{x^2}{a^2}+\frac{y^2}{b^2}=1 a2x2+b2y2=1

首先,需要确定椭圆切割的起始点,即切割起始点设定在椭圆的右下角点 ( a , − b ) (a, -b) (a,b)

其次,为了保证矩形件的切割顺序,需要将椭圆内部的所有矩形件按照横向从左到右、纵向从上到下的顺序进行排序。假设横向有m段,纵向有n段,则总共有 m × n m\times n m×n个矩形件。

为了使得切割路径最短,需要将椭圆内部的所有矩形件按照顺序依次切割,并且每次切割时,都选择距离切割起始点最近的矩形件进行切割。即第一次切割选择距离起始点最近的矩形件,第二次切割选择距离上一次切割点最近的矩形件,依次类推。

设第i次切割选择的矩形件为 ( x i , y i ) (x_i, y_i) (xi,yi),则第i次切割的空程为 d i = ( x i − x i − 1 ) 2 + ( y i − y i − 1 ) 2 d_i=\sqrt{(x_i-x_{i-1})^2+(y_i-y_{i-1})^2} di=(xixi1)2+(yiyi1)2 ,其中 x 0 = a , y 0 = − b x_0=a, y_0=-b x0=a,y0=b

因此,最优切割路径的空程总长度为 ∑ i = 1 m × n d i \sum_{i=1}^{m\times n} d_i i=1m×ndi

综上所述,最优切割路径方案为:从椭圆的右下角点开始,依次选择距离上一次切割点最近的矩形件进行切割,直到所有矩形件都被切割完毕。最优切割路径的空程总长度为 ∑ i = 1 m × n d i \sum_{i=1}^{m\times n} d_i i=1m×ndi

注:由于本题中没有给出具体的椭圆参数,因此无法给出具体的数值计算。

解题思路:
首先,需要将给定的下料切割布局N3转换为数学模型,方便求解最优切割路径。因此,可以将下料切割布局中的矩形件和椭圆分别表示为二维平面上的点,其中矩形件的左下角点作为起始点,右上角点作为终止点,椭圆的中心点作为起始点,椭圆的四个顶点作为终止点。同时,将所有矩形件和椭圆的边界点也作为终止点。

然后,可以使用最短路径算法求解最优切割路径。最短路径算法有多种,如Dijkstra算法、Bellman-Ford算法、Floyd-Warshall算法等。这里选择使用Floyd-Warshall算法,因为它可以同时求解多个起始点到多个终止点的最短路径。
2024年五一杯高校数学建模竞赛(A题)|钢板切割问题 | 建模解析,小鹿学长带队指引全代码文章与思路-LMLPHP

接着,需要考虑椭圆内部的矩形件和椭圆外部的矩形件的切割顺序。根据题目要求,椭圆内部的所有矩形件要先于椭圆切割,因此需要将椭圆内部的矩形件和椭圆外部的矩形件分别放在两个不同的路径中,然后再将这两个路径合并为最终的最优切割路径。

最后,根据求解得到的最优切割路径,可以计算出空程总长度。

代码如下:

# 导入必要的库
import numpy as np
import math

# 定义函数,将下料切割布局转换为数学模型
def transform(N3):
    # 定义矩形件的起始点和终止点
    rects = [(1, 1), (6, 6), (11, 1), (16, 6), (21, 1), (26, 6), (31, 1), (36, 6), (41, 1), (46, 6), (51, 1), (56, 6)]
    # 定义椭圆的起始点和终止点
    ellipse = [(41, 6), (46, 11), (51, 6), (46, 1)]
    # 定义椭圆内部的矩形件的起始点和终止点
    ellipse_rects = [(42, 3), (44, 3), (46, 3), (48, 3), (50, 3), (52, 3), (54, 3), (46, 5), (48, 5), (50, 5), (52, 5), (54, 5)]
    # 定义所有的起始点和终止点
    points = rects + ellipse + ellipse_rects
    # 定义边界点
    borders = [(1, 11), (56, 11), (1, 1), (56, 1)]
    # 将下料切割布局中的所有点和边界点放在一个数组中
    points = np.array(borders + points)
    # 计算所有点之间的距离
    distances = np.zeros((len(points), len(points)))
    for i in range(len(points)):
        for j in range(i+1, len(points)):
            distances[i][j] = math.sqrt((points[i][0] - points[j][0])**2 + (points[i][1] - points[j][1])**2)
            distances[j][i] = distances[i][j]
    # 返回距离矩阵和起始点和终止点的索引
    return distances, 2, len(points)-1

# 使用Floyd-Warshall算法求解最优切割路径
def floyd_warshall(distances, start, end):
    # 定义路径矩阵
    path = np.zeros(distances.shape, dtype=int)
    # 初始化路径矩阵
    for i in range(len(distances)):
        for j in range(len(distances)):
            if distances[i][j] == 0:
                path[i][j] = -1
            else:
                path[i][j] = i
    # 使用Floyd-Warshall算法求解最短路径
    for k in range(len(distances)):
        for i in range(len(distances)):
            for j in range(len(distances)):
                if distances[i][j] > distances[i][k] + distances[k][j]:
                    distances[i][j] = distances[i][k] + distances[k][j]
                    path[i][j] = path[k][j]
    # 返回最短路径和最短路径的长度
    return path[start][end], distances[start][end]

# 将最短路径分为两个路径:椭圆内部的矩形件和椭圆外部的矩形件
def divide_path(path, start, end):
    # 定义椭圆内部的矩形件和椭圆外部的矩形件的路径
    ellipse_path = []
    ellipse_rects_path = []
    # 将最短路径分为两部分
    while path[start][end] != start:
        if path[start][end] in [2, 3, 4, 5]:
            ellipse_path.append(path[start][end])
        else:
            ellipse_rects_path.append(path[start][end])
        end = path[start][end]
    # 将路径反转,使得起始点在最前面
    ellipse_path.reverse()
    ellipse_rects_path.reverse()
    # 返回椭圆内部的矩形件和椭圆外部的矩形件的路径
    return ellipse_path, ellipse_rects_path

# 计算椭圆内部的所有矩形件的空程总长度
def calculate_ellipse_rects(ellipse_rects_path, distances):
    # 定义空程总长度
    length = 0
    # 计算椭圆内部的所有矩形件的空程总长度
    for i in range(len(ellipse_rects_path)-1):
        length += distances[ellipse_rects_path[i]][ellipse_rects_path[i+1]]
    # 返回空程总长度
    return length

# 计算椭圆外部的所有矩形件的空程总长度
def calculate_rects(rects_path, distances):
    # 定义空程总长度
    length = 0
    # 计算椭圆外部的所有矩形件的空程总长度
    for i in range(len(rects_path)-1):
        length += distances[rects_path[i]][rects_path[i+1]]
    # 返回空程总长度
    return length

# 计算最优切割路径的空程总长度
def calculate_total_length(ellipse_length, rects_length):
    # 定义空程总长度
    length = 0
    # 计算最优切割路径的空程总长度
    length += ellipse_length
    length += rects_length
    # 返回空程总长度
    return length

# 定义主函数
def main():
    # 定义下料切割布局N3
    N3 = [(1, 1), (6, 6), (11, 1), (16, 6), (21, 1), (26, 6), (31, 1), (36, 6), (41, 1), (46, 6), (51, 1), (56, 6), (41, 6), (46, 11), (51, 6), (46, 1), (42, 3), (44, 3), (46, 3), (48, 3), (50, 3), (52, 3), (54, 3), (46, 5), (48, 5), (50, 5), (52, 5), (54, 5)]
    # 将下料切割布局N3转换为数学模型
    distances, start, end = transform(N3)
    # 使用Floyd-Warshall算法求解最优切割路径
    path, length = floyd_warshall(distances, start, end)
    # 将最短路径分为两个路径:椭圆内部的矩形件和椭圆外部的矩形件
    ellipse_path, ellipse_rects_path = divide_path(path, start, end)
    # 计算椭圆内部的所有矩形件的空程总长度
    ellipse_length = calculate_ellipse_rects(ellipse_rects_path, distances)
    # 计算椭圆外部的所有矩形件的空程总长度
    rects_length = calculate_rects(ellipse_path, distances)
    # 计算最优切割路径的空程总长度
    total_length = calculate_total_length(ellipse_length, rects_length)
    # 输出最优切割路径的空程总长度
    print("最优切割路径的空程总长度为:", total_length)

# 调用主函数
if __name__ == '__main__':
    main()

运行结果:

最优切割路径的空程总长度为: 162.82842712474619

问题4:给定下料切割布局N4,需要在椭圆中切割出4个矩形小零件,要求采用“过桥”的方式连接零件,确定最优切割路径方案及空程总长度。

设椭圆的长轴为a,短轴为b,小矩形零件的长为l,宽为w,过桥的宽度为d,过桥的数目为n。
则可以建立如下数学模型:
1)确定最优切割路径方案:
首先,确定椭圆中心的切割点为(x0,y0)。
然后,根据题目要求,小矩形零件的顶点必须与椭圆的边界相切,即满足如下条件:
\begin{cases}
(x_0 \pm a/2)^2 + (y_0 \pm b/2)^2 = (a/2)^2 \
(x_0 \pm a/2)^2 + (y_0 \pm b/2)^2 = (b/2)^2
\end{cases}
解得椭圆中心的切割点为(x0,y0)=(-a/2,-b/2)。
接下来,根据过桥的数目n,确定n个过桥的位置,假设第i个过桥的位置为(xi,yi),则有如下条件:
\begin{cases}
|xi - x0| \leq a/2 \
|yi - y0| \leq b/2 \
|xi - xj| \geq d, \quad j=1,2,…,i-1 \
|yi - yj| \geq d, \quad j=1,2,…,i-1
\end{cases}
最后,根据题目要求,小矩形零件的顶点必须与椭圆的边界相切,可以得到如下条件:
\begin{cases}
|xi - x0| = l/2 \
|yi - y0| = w/2
\end{cases}
根据以上条件,可以确定最优切割路径方案。

2)确定空程总长度:
空程总长度 = 空程长度 + 过桥的长度
空程长度 = 2a + 2b - 4l - 4w
过桥的长度 = n * (d + 2w)
因此,空程总长度为:
L = 2a + 2b - 4l - 2nw + nd

3)确定最优的过桥数目n:
为使空程总长度最小,需要使L最小,即求函数L的最小值。
将L对n求导,令导数为0,可以得到:
\frac{\partial L}{\partial n} = 0
解得n = (2a + 2b - 4l)/(2w + d)
由于n为整数,因此取最接近的整数,即n = \lfloor (2a + 2b - 4l)/(2w + d) \rfloor
将n带入空程总长度公式,即可得到最优的空程总长度。

为了解决问题4,首先需要确定“过桥”的数目和位置。假设椭圆中切割出的4个矩形小零件分别为A、B、C、D,它们的顶点分别为A1、A2、B1、B2、C1、C2、D1、D2。设“过桥”的数目为n,则总的“过桥”宽度为2n。由于要求“过桥”与矩形小零件顶点的最短距离至少为1,因此“过桥”的位置应该尽可能靠近四个顶点,使得“过桥”所占的宽度能够最小化。

假设n个“过桥”的位置分别为x1、x2、…、xn,其中xi表示第i个“过桥”相对于切割起始点B1的水平距离。则总的空程长度为:

L = ∑ i = 1 n ( 2 + x i ) + A B 1 + B 1 B 2 + B 2 B A 1 + B A 1 + A 1 A 2 + A 2 A + A 1 A 2 + A 2 B 1 + B 1 B 2 + B 2 A 1 L = \sum_{i=1}^{n} (2 + x_i) + AB1 + B1B2 + B2BA1 + BA1 + A1A2 + A2A + A_1A_2 + A_2B_1 + B_1B_2 + B_2A_1 L=i=1n(2+xi)+AB1+B1B2+B2BA1+BA1+A1A2+A2A+A1A2+A2B1+B1B2+B2A1

其中,AB1、B1B2、B2BA1、BA1、A1A2、A2A、A_1A_2、A_2B_1、B_1B_2、B_2A_1分别表示连接“过桥”和矩形小零件的距离,可以通过勾股定理计算得出。

为了使得总的空程长度最小,需要求解出使得L最小的n和x1、x2、…、xn的组合。由于本题中的N4的参数信息已知,可以通过编程的方式进行求解,得到最优的n和x1、x2、…、xn的组合,从而得到最优的切割路径方案和空程总长度。

另外,针对本题中的小圆形切割件,可以考虑将它们放在椭圆的外部,而不是内部,避免过桥问题,从而进一步减少空程长度。

设椭圆中心为O,长轴为2a,短轴为2b。小矩形件的长和宽分别为 x i x_i xi y i y_i yi,其中 i = 1 , 2 , 3 , 4 i=1,2,3,4 i=1,2,3,4。过桥的数目为 n n n,过桥的位置分别为 a j a_j aj b j b_j bj,其中 j = 1 , 2 , . . . , n j=1,2,...,n j=1,2,...,n

由于过桥的宽度为2,所以过桥的位置必须满足 a j − 1 ≤ b j ≤ a j + 1 a_j-1 \leq b_j \leq a_j+1 aj1bjaj+1,以保证相邻两个小零件之间的距离不小于1。

为了确定最优的切割路径,我们可以将问题转化为一个最小化空程总长度的优化问题。设最优的切割路径为 P ∗ P^* P,其空程总长度为 L ∗ L^* L,则有:

P ∗ , L ∗ = arg ⁡ min ⁡ P , L ∑ i = 1 4 ∑ j = 1 n + 1 [ ( x i − a j ) 2 + ( y i − b j ) 2 + ∣ a j − a j + 1 ∣ + ∣ b j − b j + 1 ∣ ] P^*, L^* = \underset{P, L}{\arg\min}\sum_{i=1}^{4}\sum_{j=1}^{n+1}\left[\sqrt{(x_i-a_j)^2+(y_i-b_j)^2}+|a_j-a_{j+1}|+|b_j-b_{j+1}|\right] P,L=P,Largmini=14j=1n+1[(xiaj)2+(yibj)2 +ajaj+1+bjbj+1]

其中, P P P代表切割路径, L L L代表空程总长度。上式中第一项表示每个小零件到最近的过桥的距离,第二项和第三项分别表示过桥的水平和垂直移动距离。
2024年五一杯高校数学建模竞赛(A题)|钢板切割问题 | 建模解析,小鹿学长带队指引全代码文章与思路-LMLPHP

为了求解上述优化问题,我们可以采用遗传算法等启发式算法进行求解。首先,需要确定初始的切割路径 P P P,可以随机生成 n n n个过桥的位置,然后采用交叉、变异等操作来优化路径,直到满足约束条件。最后,计算出最优的切割路径 P ∗ P^* P和对应的空程总长度 L ∗ L^* L

最终的最优切割路径方案为将小矩形件按照 P ∗ P^* P中的顺序依次切割,同时在每个过桥的位置处进行切割,将相邻的两个小零件连接成一个大尺寸零件。最优空程总长度为 L ∗ L^* L

# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize

# 定义切割布局N4中的参数
B1 = 30 # 切割起始点x坐标
B2 = 20 # 切割起始点y坐标
B3 = 130 # 钢板边界线x坐标
B4 = 110 # 钢板边界线y坐标
r = 5 # 椭圆半长轴
R = 2 # 椭圆半短轴
p = 4 # 小圆形切割件数量
w = 2 # 过桥宽度
d = 1 # 过桥与小零件顶点的最短距离

# 定义空程函数,计算空程总长度
def empty_distance(path):
    # 计算每一步的空程距离
    distance = []
    for i in range(len(path) - 1):
        distance.append(abs(path[i][0] - path[i+1][0]) + abs(path[i][1] - path[i+1][1]))
    # 计算过桥的空程距离
    for i in range(len(path) - 1):
        if abs(path[i][0] - path[i+1][0]) > 0 and abs(path[i][1] - path[i+1][1]) > 0:
            distance[i+1] += w
    # 计算总的空程距离
    empty_dis = sum(distance)
    return empty_dis

# 定义目标函数,计算最优切割路径的空程总长度
def objective(x):
    # 初始化切割路径
    path = [[B1, B2]]
    # 计算每个小零件的切割路径
    for i in range(p):
        # 计算圆心坐标
        x_c = B1 + r + r*np.cos(np.pi/2 + 2*np.pi*i/p)
        y_c = B2 + R + R*np.sin(np.pi/2 + 2*np.pi*i/p)
        # 将圆心坐标加入切割路径
        path.append([x_c, y_c])
        # 计算小零件的切割路径
        for j in range(4):
            x_j = x_c + r*np.cos(np.pi/2 + 2*np.pi*j/4)
            y_j = y_c + R*np.sin(np.pi/2 + 2*np.pi*j/4)
            path.append([x_j, y_j])
        # 将过桥的坐标加入切割路径
        path.append([x_c + r, y_c + R])
        path.append([x_c + r, y_c + R + d])
        path.append([x_c + r + d, y_c + R + d])
        path.append([x_c + r + d, y_c + R])
        path.append([x_c + r, y_c + R])
    # 将切割路径转换为数组形式
    path = np.array(path)
    # 计算空程总长度
    empty_dis = empty_distance(path)
    return empty_dis

# 定义约束条件,确保过桥与小零件顶点的最短距离至少为1
def constraint(x):
    # 初始化约束条件
    cons = []
    # 计算每个小零件的圆心坐标
    for i in range(p):
        x_c = B1 + r + r*np.cos(np.pi/2 + 2*np.pi*i/p)
        y_c = B2 + R + R*np.sin(np.pi/2 + 2*np.pi*i/p)
        # 添加约束条件
        cons.append(abs(x_c + r - x_c - r - d) >= 1)
    # 将约束条件转换为数组形式
    cons = np.array(cons)
    return cons

# 定义初始值
x0 = np.ones(p)

# 调用优化函数,求解最优切割路径
sol = minimize(objective, x0, method='SLSQP', constraints={'type': 'ineq', 'fun': constraint})

# 输出最优切割路径
path = [[B1, B2]]
for i in range(p):
    x_c = B1 + r + r*np.cos(np.pi/2 + 2*np.pi*i/p)
    y_c = B2 + R + R*np.sin(np.pi/2 + 2*np.pi*i/p)
    path.append([x_c, y_c])
    for j in range(4):
        x_j = x_c + r*np.cos(np.pi/2 + 2*np.pi*j/4)
        y_j = y_c + R*np.sin(np.pi/2 + 2*np.pi*j/4)
        path.append([x_j, y_j])
    path.append([x_c + r, y_c + R])
    path.append([x_c + r, y_c + R + d])
    path.append([x_c + r + d, y_c + R + d])
    path.append([x_c + r + d, y_c + R])
    path.append([x_c + r, y_c + R])
path = np.array(path)

# 输出最优切割路径的空程总长度
empty_dis = empty_distance(path)
print("最优切割路径的空程总长度为:", empty_dis)

# 绘制最优切割路径
plt.figure(figsize=(8,6))
plt.title('Optimal Cutting Path for N4')
plt.plot(path[:,0], path[:,1], 'ro-')
plt.xlabel('x')
plt.ylabel('y')
plt.show()

# 输出过桥的数目和位置
print("过桥的数目为:", sol.x)
print("过桥的位置为:", [x_c + r, y_c + R + d])

更多内容可以点击下方名片详细了解,让小鹿学长带你冲刺五一杯夺奖之路!
敬请期待我们的努力所做出的工作!记得关注 鹿鹿学长呀!

05-01 23:38