本文主要讲述使用MindOpt工具优化切割问题
视频讲解👈👈👈👈👈👈👈👈👈
案例场景
切割问题涉及从一维的原材料如木材、钢材、布匹卷等切割出特定长度的零件以满足不同需求。同时最小化浪费成本。这个问题可以形式化为在满足需求的同时减少原材料的使用量。对于一维切割的思路,可以进行扩展。实际中有很多的应用。
扩展的思路例如钢筋切割将统一长钢筋原材料根据需求切割成不同长度小尺寸,例如切割能最小化原材料数量。
木材加工从长度不一的原材料中切割出多种长度的小段。如何切割能最大化成品总数长度数、提高原材料利用率。
一维切割的应用场景包括但不限于以下几点:制造业中切割问题应用于各种物料和材料的切割例如金属塑料木材等,通过优化切割方案可以提高原材料的利用率,减少成本的浪费。
在建筑业中切割问题应用于各种材料的切割例如钢筋管道石材等,通过优化切割方案可以满足建筑结构的需求,减少材料浪费,提高施工效率。
在木工行业中,切割问题可以应用于各种木材的切割例如板材木块等,通过优化切割方案可以提高木材的利用率,减少浪费,提高生产效率。
在服装、纺织和皮革业中,切割问题用于面料皮革等的切割例如服装鞋子等的剪裁。通过优化切割方案,可以提高面料和皮革的利用率,减少浪费,提高生产效率。
数学规划
切割问题可以使用数学规划的方法解决。数学规划是一种数学优化方法,主要寻找变量取值在特定的约束情况下,使得我们的决策目标得到一个最大或最小值的决策。常见的数学优化方法有线性规划、混合优化、整数规划和非线性规划。在实际应用中,需要确定问题的目标约束变量的取值范围,对其建立一个数学模型,对数学模型进行求解,得出的结果就是问题的最优决策。在求解时往往将数学模型转换为一个代码,通过代码调用优化求解器工具。优化求解器可以帮助我们计算大规模数据的数学规划问题。
问题描述
假设有一批长度统一的水管原材料,要切出不同长度。如何安排切割使得使用的原材料数量最少?考虑八点因素:第一是原材料长度,每个原材料长度统一是100单位,第二是需求量,需要不同规格的材料数量。第三是如何将不同长度的小段组合以最大限度的利用原材料,减少浪费。第四是每根原材料切割的结果必须是完整的小段,不能有分数或小数。第五每种切割方案的数量必须大于等于0。第六目标是使用最少的原材料数量来满足所有的需求。第七是切割过程中会有一定的损耗,该问题忽略不计。第八结合以上因素,寻找最少使用原材料的优化方案。
代码解析
在案例中,我们对这个问题进行数学建模和代码转化,用到MindOpt云上建模求解平台(一个页面版的线上开发环境,可在线的开发调试代码)、以及达摩院研发的建模语言MindOpt APL,与学公式非常贴近。
工具:
- MindOpt Studio 云建模平台,在线开发调试,免下载
- MindOpt APL(MAPL)建模语言编程,代数建模语言,语法与数学公式相近
- MindOpt优化求解器:帮我们求解大规模数据的数学规划问题。
声明集合、参数
首先定义了原材料的长度,也就是标准水管的长度。下面是使用map语法,从CSV文件中读取数据的一个方法,并且将其用作模型的一个参数。第一句表示CSV文件在data目录下。下面定义了一个名为demand 的集合,通过读取下面file d2目录下的demand.CSV文件来获取数据。依然表示读取该文件中的第一列数据。Ln表示数字,gap1表示读取操作跳过第一行。因为第一行通常是表头。最终这个集合demand将包含需求序号的列表123。
下面是读取需求长度。创建了一个名为demand size的参数,以demand集合为索引的映射,数据同样来自CSV文件。通过1n 2n读取第一列作为索引,也就是需求序号,并且读取第二列作为需求长度的值,即54 50 70,所以demand size将包含demand的集合每个序号对应的需求长度。DemandNum读取了需求个数,从demand集合为索引的映射,数据来源与前述相同,但是1n 3n表示使用第三列数据作为个数的值。所以demandNum将包含于demand集合中每个序号对应的需求个数。
下面是定义原材料的总数,pipe_num=15,创建了一个rawpipe的集合。只包含从1到pipe_num,表示15根原材料编号。
声明变量
然后来看定义的变量,第一个变量定义了一个变量x_pipeused,表示在满足所有需求后总共被使用的管道数量,也就是FUS。第二个变量定义了一个索引rawpipe的二元变量数组x_cuts,每个元素x_cuts[i]表示编号为i的原材料是否被切割使用。1表示原材料被切割,0表示原材料未被切割。该变量是二进制变量bi。第三个变量定义了一个证书变量数组x_cutnum,索引为rawpipe,原材料水管编号的集合,和demand需求序列集合的笛卡尔积,每个元素x_cutnum[i,j]表示编号为i的原材料水管中编号为j的需求长度被切割出的数量。整数变量意味着这些变量的值必须为非负整数。再来看定义的优化目标。
声明目标
我们的目标是最小化使用原材料的数量,最小化切割的总次数,最小化定义的第一个变量x_pipeused,最小化总共被使用的管道数量。
声明约束
第一个约束条件是每个需求j的尺寸需求应该得到满足,对于每个需求的需求量demandnum[j]必须小于或者等于所有原材料管道i中切割出该需求尺寸的数量x_cutnum[ij]的一个总和,这样确保了每个尺寸的需求都至少得到满足。
下面的需求是每个原材料i的切割方式不能超过其总长度。Demandsize是需求j的尺寸,typelength是原材料管道的长度,x_cutnum[ij]是从原材料管道i切割出满足需求j的数量,对所有需求尺寸的切割长度求和,得到的总长度不应该超过原材料管道长度乘该管道是否被使用的标志x_cuts。如果管道未被使用,x_cuts为0,因此等式右侧为零,满足约束。
确保变量typeused=实际被切割的原材料数量之和,对于集合rawpipe中的每个原材料管道,如果被切割,x_cuts i等于1就会在x_pipeused中累加计数。然后使用求解指令进行求解。一般遇到规模大的问题,变量取值会比较多,复杂程度高,解出的结果变量的取值可读性不高,所以使用map语法中打印CSV表格的方法,提高角色变量的可读性。这段代码是打印切割方案到一个切割方案CSV的文件中。
将结果打印为表格
这段代码是命令在切割方案点CSV文件中写入表头,表头包含了材料长度、需求数量以及对应的切割数量。然后使用close命令去关闭CSV文件。将数据写入到表格中。这段代码遍历了所有原材料,也就是rawpipe中的每一项,并且只考虑至少有一次被切割的。由于x_cuts[i]是一个二元变量,所以这里用0.5作为阈值来检测是否为1。对于每一根原材料,将长度以及每个需求的尺寸以及该原材料为每个需求切割出的数量打印到CSV文件中,格式化字符串括号用于插入变量值,百分号操作符用于将变量值传递给格式化字符串。然后使用追加符号表示向切割方案点CSV文件追加内容,而不是覆盖原有内容。最后使用close命令关闭文件。
结果解析
首先可以看到使用了七个原材料,使用七个水管。对第一根水管进行切割,得到了两个长度为14的水管,以及一个长度为70的水管。对第二根水管进行切割,得到了一个长度为14的水管以及一个长度为70的水管。剩下的变量的取值与上述类似,不详细介绍。
对本期内容进行回顾:
本期讲述切割问题,对水管原材料进行切割,需要最小化水管原材料的使用数量。使用工具是MIndopt云上建模求解平台,网址是opt.aliyun.com。
获取源代码
切割问题优化:一维长度或容量切割-MindOpt Studio
最后对这个问题进行扩展。
这个问题讲述的是一维切割,通常还有更为复杂的二维和三维切割,对应需要考虑的因素会指数升级,对应的解决方案可能会不一致。例如一维的控制量只有长度,二维有坐标xy和转角。三维对应xyz和roll、pitch、yaw三种选择角度。切割形状不能重叠表达。