JAVA实现线性优化的单纯形算法

@TOCJAVA实现线性优化的单纯形算法

JAVA实现线性优化的单纯形算法

网上的一些单纯形算法基本都是基于Python或者matlab的库自带函数进行计算,基于JAVA实现该算法的例子相对较少,因此我将本人做的一个实现案例发布供大家参考。
网上关于该算法的原理已经有不少的介绍,因此下文不做过多赘述。

实现思路

给出以下限定条件:
①每一个优化变量的取值范围均为Xi>=0
②对于一个目标函数为max优化的案例,当目标函数变量的系数全都小于等于0时,此时目标函数的常数项为目标值。
同理,对于min优化的案例,当目标函数变量的系数全都大于等于0时,此时的目标函数的常数项为目标值。
③由②可推得,当目标函数为min优化时,让目标函数的每一个变量的系数乘以-1可以转化为max优化,反之亦然。

**实现步骤:**

步骤一:把不等式约束转化为等式约束

为所有的不等式约束添加一个松弛变量,使不等式约束变成等式约束。

例子:
max: Z=3X1+X2+2X3


在这个案例中,有三个不等式约束,因此我们添加一个松弛变量,使得等式成立。如 X1+X2+3X3+X4=30,即,在X4取得某个大于等于零的值的情况下该等式成立。由此,我们构造出了以下的等式约束:

在这里插入图片描述

步骤二:根据目标函数,选取入变量和出变量

若目标函数的变量系数全都小于等于零,则此时的目标函数值为常数项。
否则,进行如下操作:
由目标函数可以看出,三个系数均大于零,为了避免混淆,我们规定了如下的消元变量选取规则:
① :变量的下标尽可能的小
② :变量的系数需大于0
由此,可以选出第一个需要消元的变量:X1

确定了目标函数中待消元的变量(出变量),我们就可以把目标函数的X1用约束条件中的某一个等式约束进行替换,因此,我们还需要判断选取哪一个等式作为入变量。

入变量的选取规则:
① :入变量所在的等式的常数与出变量的系数之比的相反数最小。
② :入变量所在的等式的出变量的系数需小于0
如该案例中,出变量为X1,三个等式约束中,等式一的常数与出变量系数之比为30,同理,等式二的比值为12,等式三的比值为9 。因此,我们选取X6作为入变量。经过整理后,可得如下等式约束:
X1=9 - 1/4*X2 -1/2*X3 - 1/4*X6

步骤三:进行高斯消元,使得新的目标函数不再包含出变量

将该式带入目标函数以及其他各式里,得到新的目标函数以及等式约束如下:

在这里插入图片描述

可以看到,目标函数的目标值此时是27,变量中不再含有X1,而多了X6,且X6的系数小于等于零。
因此,回到步骤二,反复执行步骤二、三,直到目标函数所有变量的系数均小于或等于0 。

说明:

以上的步骤均是基于所给的例子进行,因此编写的代码也是基于这些步骤,而实际案例中,出了例子中的<=约束,还存在>=约束或者等式约束,对于出现这类情况,我们在构造松弛型约束矩阵的时候遵循以下的规则:
①:只给不等式约束添加松弛型变量。若一开始所给的约束条件中包含m个不等式约束,n个等式约束,则只需要添加m个松弛型变量。
这是因为我们的算法是基于等式约束进行消元得到的解,因此我们只需要把不等式转化为等式,若该约束一开始便是等式,则不需要额外的处理。
②:为了处理方便,我们需要把所有的不等式约束均处理为AX<=B的模式,若存在AX>=B的情况存在,只需要在不等式两边乘以-1即可改变符号。

代码设计:

算法以及在上面交代好了,可运行的代码我会通过网盘分享给大家。因此在这里不做赘述。
本代码可以解决大多数基础的线性优化问题,但是存在以下不足,因时间问题未能完善:
①:没有设计一个函数来判断输入的线性优化问题是否有解
解决方法:在步骤二的选取入变量的部分中,我们要求“入变量所在的等式的出变量的系数需小于0”。若存在一个线性优化案例,该案例中,选取好了出变量后,每一个等式约束中出变量的系数均大于0,则该问题无解。
②:本代码只给出了目标值以及该目标值对应的基变量的系数,并没有给出变量的取值。
③:由于JAVA缺乏矩阵的处理函数,因此该算法实现案例中有着大量笔者自写的函数,由于笔者自身水平局限,不免存在着许多不足需要去完善。

代码链接:
https://pan.baidu.com/s/1O6LnLIb4UAwkBymrdLZJTA
提取码:zc66

本代码的使用说明:

在输入系数矩阵的时候,应该严格按照以下规则输入数据:
若对于 aX1+bX2+cX3<=d,输入的顺序应该是
d a b c
即,常数项放在第一个,其他变量的系数依次输入,若无,则补零。
目标函数的输入也按照此规则。

本代码求解上文案例:
输入:
在这里插入图片描述
输出:在这里插入图片描述

参考文献:

算法导论 第三版 p507~510

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值