运筹优化学习21:Java调用Cplex实现求解Cuting Stock Porblem的列生成算法详解(上)

简介: 运筹优化学习21:Java调用Cplex实现求解Cuting Stock Porblem的列生成算法详解

1 CSP问题与模型

1.1 问题描述

我们有以下问题,原纸卷每个长为L=16m,顾客们分别需要25个3m长,20个6m长,18个7m长的纸卷。那么需要怎样切割才能使得浪费最小呢?

1.2 模型构建

假设有 n 中可行的裁切方案

image.png

由此我们得到模型如下:

gif.png

2 列生成方法理论

2.1 引子

列生成方法是求解大规模线性规划问题的有效方法,这里的大规模是指问题的约束数目有限变量数目随着问题规模的膨胀而急速膨胀的线性规划问题。

我们刚才讨论的CSP就很好的满足了这一点:

顾客需求确定,约束个数就是确定的;但是有效的方案数目是不确定的

假定n=100时,变量数为100;当n=1,000,000,000时,变量数为1,000,000,000

2.2 单纯形法到列生成

我们都知道求解线性规划的最经典的方法是单纯形法,它是一种在解空间的顶点上迁移来找到问题最优解的算法;但是对于变量很多的LP时,我们遍历顶点的代价是很大的。但是有一点我们肯定知道,那就是我们的约束个数是等于基变量的个数的。另外i啊我们每一步的操作只会让一个非基变量进基。


为了更好的说明先澄清几个概念:


image.png

image.png

基于上面的解释和概念定义,我们就可以描述单纯形法到列生成的演变路径:


将MP限制到一个变量更少的子问题RMP,使用单纯形法求解RMP的最优解

使用subproblem去检验剩余变量的reduced cost是否小于0;若是,将与该变量相关的系数列加入到RMP中,返回第1步;否则,得到了原问题的最优解。


2.3 subproblem

这里终点讨论一下子问题,子问题的作用是为了检查剩余非基变量的reduced cost,确定它能否作为入基变量。

先来一张规范的单纯形表:

20191108144037152.png

在单纯形法中,我们通过计算非基变量检验数 ,为负且最小的情况下的变量作为入基变量


在这个问题中,我们求解的关键是,它包含两重含义:


通过求解RMP问题得到的影子价格(shadow price)。

通过求解RMP对偶问题得到的对偶变量(dual variable)。

通俗的理解,影子价格是针对RMP本身而言的,而对偶变量是针对RMP的对偶问题而言的。


若对影子价格和对偶变量理论不熟悉,可前去阅读2.3.1和2.3.2的内容;否则我们继续


作为一个懒虫,我们肯定是咋简单咋来:


要想得到影子价格,我们就得解RMP,但是很不幸RMP有很多变量,单纯形法可能解不了;此路不通

对偶问题变量少啊,那我们当然选择从对偶变量下手

那就好办了,我们通过求RMP的对偶问题来求解gif.gif,从而得到非基变量的检验数gif.gif,然后建立以检验数最小为目标的subproblem,如果它的目标函数为负,说明这个列可以加入到RMP中;如果它非负,说明已经得到了最优解


2.3.1 对偶理论

对于每个线性规划问题都有一个对偶问题,得到了一个问题的解,另一个问题的解也就迎刃而解了。

20200202211511782.png

20200202212051210.png

再啰嗦一下:


对偶问题的目标函数的系数是原问题约束的右端项

对偶问题的系数矩阵是原问题系数矩阵的转置

对偶问题的约束都是 ≤ ;原问题的约束都是 ≥

对偶问题求最小则原问题求最大

对偶问题的剩余变量和原问题的基变量共同构成了变量空间

对偶问题研究的是资源的估价问题,原问题研究的是资源的最优分配问题


2.3.2 影子价格

对偶变量gif.gif表示市场对单位第 i 种资源的估价,这种估价是由资源在生产过程发挥的作用决定的。


在资源最优利用条件下的估价,被我们称为该资源的影子价格;


下面是几点解释:


也可认为是在最优条件下,增加每单位 i 资源,对目标函数的增量贡献值。

当资源利用不充分时,他的影子价格为0;而影子价格不为0时,表示该资源已经耗尽

结合检验数的计算,gif.gif,前一项为产品 j 的产值,后一项为生产该产品消耗各资源的影子价格之和(隐含成本)。当产品产值大于资源隐含成本时,生成才有意义,所以检验数必须为非负


2.4 小结


列生成就是从一个变量较少的RMP开始,在得到RMP最优解后,利用其对偶变量建立起一个检验数最小化subproblem;若subproblem目标值为负,则增加新列到RMP中;如果subproblem目标值非负,则得到RMP的最优解。


所谓列生成,就是在每次迭代中添加一个列,直到无列可加时,得到的RMP的最优解就是原问题最优解。


列生成解决的是线性规划问题,如果要解决整数规划问题,还需要借助分支定界法、分支定价、分支切割等方法


3 Cplex OPL演示列生成迭代过程

3.1 第一次迭代

如果每个纸卷只裁切一个类别的纸卷,我们可以得到初始方案:

A = [5,0,0; 0,2,0; 0,0,2]

因此我们选择前三个方案,构建的RMP模型为:

gif.png

Cplex OPL代码:

 dvar int+ y1; dvar int+ y2; dvar int+ y3;
 minimize y1 + y2 + y3;
 subject to{
5*y1 + 0*y2 + 0*y3 >= 25;
0*y1 + 2*y2 + 0*y3 >= 20;
0*y1 + 0*y2 + 2*y3 >= 18;
} 


得到结果为:Y = [5, 10, 9];

对偶变量为:gif.gif

现在我们要加一列到RMP中,记为gif.gif,计算其检验数:

gif.gif

我们便得到了一个子问题:

gif.png

Cplex代码:

dvar int+ a14; dvar int+ a24; dvar int+ a34;
minimize 1 - (0.2*a14 + 0.5*a24 + 0.5*a34);
subject to{
3*a14 + 6*a24 + 7*a34 <= 16;
}

得到image.png,ruduce cost的取值为负数,因此加入image.png

相关文章
|
17天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于PSO粒子群优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于MATLAB2022a/2024b开发,结合粒子群优化(PSO)算法与双向长短期记忆网络(BiLSTM),用于优化序列预测任务中的模型参数。核心代码包含详细中文注释及操作视频,涵盖遗传算法优化过程、BiLSTM网络构建、训练及预测分析。通过PSO优化BiLSTM的超参数(如学习率、隐藏层神经元数等),显著提升模型捕捉长期依赖关系和上下文信息的能力,适用于气象、交通流量等场景。附有运行效果图预览,展示适应度值、RMSE变化及预测结果对比,验证方法有效性。
|
18天前
|
机器学习/深度学习 边缘计算 算法
NOMA和OFDMA优化算法分析
NOMA和OFDMA优化算法分析
45 6
|
17天前
|
机器学习/深度学习 算法
基于遗传优化ELM网络的时间序列预测算法matlab仿真
本项目实现了一种基于遗传算法优化的极限学习机(GA-ELM)网络时间序列预测方法。通过对比传统ELM与GA-ELM,验证了参数优化对非线性时间序列预测精度的提升效果。核心程序利用MATLAB 2022A完成,采用遗传算法全局搜索最优权重与偏置,结合ELM快速训练特性,显著提高模型稳定性与准确性。实验结果展示了GA-ELM在复杂数据中的优越表现,误差明显降低。此方法适用于金融、气象等领域的时间序列预测任务。
|
16天前
|
Oracle Java 关系型数据库
java 入门学习视频_2025 最新 java 入门零基础学习视频教程
《Java 21 入门实操指南(2025年版)》提供了Java最新特性的开发指导。首先介绍了JDK 21和IntelliJ IDEA 2025.1的环境配置,包括环境变量设置和预览功能启用。重点讲解了Java 21三大核心特性:虚拟线程简化高并发编程,Record模式优化数据解构,字符串模板提升字符串拼接可读性。最后通过图书管理系统案例,展示如何运用Record定义实体类、使用Stream API进行数据操作,以及结合字符串模板实现控制台交互。该指南完整呈现了从环境搭建到实际项目开发的Java 21全流程实
44 1
|
19天前
|
Java
银行转账p图软件,对公转账截图生成器,java版开发银行模拟器【仅供学习参考】
这是一套简单的银行账户管理系统代码,包含`BankAccount`和`BankSystem`两个核心类。`BankAccount`负责单个账户的管理
|
19天前
|
存储 Java 数据库
银行流水生成器在线制作,银行转账p图在线生成,java实现最牛的生成器【仅供学习用途】
本示例展示了一个基于Java的银行交易记录管理系统基础架构,涵盖交易记录生成、数字签名加密及账本存储功能。核心内容包括:1) TransactionRecord类
|
2月前
|
算法 Java 调度
Java多线程基础
本文主要讲解多线程相关知识,分为两部分。第一部分涵盖多线程概念(并发与并行、进程与线程)、Java程序运行原理(JVM启动多线程特性)、实现多线程的两种方式(继承Thread类与实现Runnable接口)及其区别。第二部分涉及线程同步(同步锁的应用场景与代码示例)及线程间通信(wait()与notify()方法的使用)。通过多个Demo代码实例,深入浅出地解析多线程的核心知识点,帮助读者掌握其实现与应用技巧。
|
5月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
295 60
【Java并发】【线程池】带你从0-1入门线程池
|
3月前
|
Java 中间件 调度
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
本文涉及InheritableThreadLocal和TTL,从源码的角度,分别分析它们是怎么实现父子线程传递的。建议先了解ThreadLocal。
128 4
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
|
2月前
|
Java
java 多线程异常处理
本文介绍了Java中ThreadGroup的异常处理机制,重点讲解UncaughtExceptionHandler的使用。通过示例代码展示了当线程的run()方法抛出未捕获异常时,JVM如何依次查找并调用线程的异常处理器、线程组的uncaughtException方法或默认异常处理器。文章还提供了具体代码和输出结果,帮助理解不同处理器的优先级与执行逻辑。

热门文章

最新文章