·完整·单纯形算法(Simplex Algorithm),附C源码

前段时间参加了华为的2017软件精英挑战赛,用到了单纯形算法求解线性规划问题,学习了正单纯形,对偶单纯形以及割平面法并用C语言实现了完整的simplex算法。

单纯形算法是用来求解线性规划问题的,其被用在了众多SMT Solver中,如Yices, Z3等,都是基于的单纯形算法,其算法效率在最坏情况下为指数级别,不过实现证明其效率在大多数情况下都是令人满意的。

标准形式

max{b+1knckxk}

1knA1xkb1

1knAmxkbm
x1,...,xn0

对于 b1,...,bm0 的情况,可使用正单纯形算法求解,对于存在 bi<0 的情况,则需要使用对偶单纯形求解。这里求出来的解都是非整数解,若要得到目标式的整数最优解,在前面的基础上还需要使用割平面法,即引入Gomory(高莫雷)约束。

一些特殊情况的处理

1.对于不满足 xi0 的情况,可将 xi 化为两个非负数的差值,即
xi=xjxk , 其中 xj,xk0
2.如果限制式子为等式,可将其化为一个大于等于和小于等于,如
a+b=c(a+bca+bc)
3.如果要求的目标式 Z 的最小值,则可转化为先求Z的最大值

正单纯形算法

首先将标准形式写为如下形式(Slack Form)
Z=b+1knckxk

y1=b11knA1xk

ym=bm1knAmxk

这里引入了新的松弛变量 y1,...,ym0 ,不难证明,新的形式跟原不等式等价。 xk 称为basic variable(基变量), ym 称为non-basic variable(非基变量)。因为 b0 ,所以所有的非基变量为0为一组可行解,我们就是从这个初始可行解触发,一步一步找到最优解。下面是具体的步骤:
1.查找 ck ck>0 ,若不存在(目标式已经无法再继续增大),跳转到第4步
2.找到 minbiAi ,即限制条件最强的一组式子
3.交换 xk yi , xk 变为新的基变量, yi 变为新的非基变量,将其他式子中的 xk 替换为新的值,然后回到第1步
4.将所有的非基变量取0值,即可算出所有的基变量的值以及目标式的最大值,算法结束

单纯形的物理意义

A polyhedron dened by seven inequalities.
如上图所示,为7个限制不等式所构成的凸多面体,每个限制条件可看成正凸多面体的一个面,凸多面体的内部(包括表面)即为可行解区域。可以证明,最优解如果存在,则一定在凸多面体的顶点上。对于三维空间来说(更高维空间可类似推广),某个顶点比为三个或以上的平面的交点,这个交点满足对应相交平面的限制不等式。如点A,同时满足式子②③⑦。
算法中第3步中的交换因子(pivot),可以看成是从凸多面体的一个顶点走向另一个顶点。

对偶单纯形

在标准形式(Slack Form)中,如果 bm<0 ,则不能直接用正单纯形求解,需要使用对偶单纯形,先将标准型化为正单纯形的标准形式,即 bm0 ,然后再使用正单纯形进行求解。
对偶单纯形的求解步骤如下:
1.引入新的松弛变量 z0 ,得到如下新的标准型
Z=b+1knckxkz
y1=b11knA1xk+z

ym=bm1knAmxk+z
2.取 min{bi},0im ,交换 z yi z 变为基变量,yi变为非基变量。执行完此步骤后,新的所有常数 b 都将变为非负数
3.为了使得加入z后的标准型跟原标准型等价,需要满足 z=0 的条件。此时 z 已经是基变量,所以我们需要先将其从基变量中置换出来,即变为非基变量。如果无法将z变为非基变量,则原式无解
4.当 z 再次从基变量置换为非基变量后,此时z可以取最小值0。然后我们可将 z 忽略,使用正单纯形算法求解目标值的最大值

割平面法求整数最优解

以上求得的都是非整数最优解,即LP(Linear Programing),如果要求整数最优解(Interger Linear Programing),则需要在得到非整数最优解的基础上,对其进行切割,以得到整数解,这里采用割平面法。
设求出的最优解:
X=(b1,...,bm)
xi 不为整数,
xi=bi1knAkxk , xi 为基变量, xk 为非基变量
bi Ak 分离成一个整数与真分数之和,即
bi=[bi]+fi , Ak=[Ak]+fk
其中 [bi],[Ak] 为整数, fi,fk 为真分数,则有
xi=[bi]+fi1kn[Ak]xk1knfkxk
把整数项移到左边,分数项移到右边,得
xi[bi]+1kn[Ak]xk=fi1knfkxk
因为等式两边都为整数,且
fi1knfkxkfi<1
fi1knfkxk0 , 这就是高莫雷(Gomory)约束。
对上式引入一个新的松弛变量 gi
gi=fi+1knfkxk
将其添加到原式中,使用对偶单纯形进行求解。如果算出解仍不为整数解,则选取新的Gomory约束,继续进行切割

用C实现的源码地址如下:
(https://github.com/zjc666/Simplex_Algorithm)

  • 13
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
下坡单纯形算法(Downhill Simplex Algorithm)是一种优化算法,用于在多维空间中寻找函数的最小值。 该算法由Nelder和Mead于1965年提出,是一种直观而简单的算法。它的核心思想是通过构建一个简单形状的多面体,逐步收敛于最小值。 算法的基本步骤如下: 1. 初始化:选择一个初始多面体,其中包含一个初始点和周围一些相邻点。 2. 计算函数值:计算多面体的各个顶点对应的函数值,根据函数值的大小确定多面体的顶点的位置。 3. 变换:选择某个顶点,通过一系列的变换操作(如反射、扩展、收缩)生成新的顶点,仍然保持多面体的形状。 4. 评估:计算新顶点的函数值。 5. 更新:根据新的函数值对多面体进行更新,包括移动、旋转等操作。 6. 收敛判断:判断是否满足停止条件,即函数值足够小或者多面体的形状足够接近最小值的形状。 7. 终止或迭代:如果满足停止条件,算法结束,否则继续进行2-6步骤。 该算法的优点是简单易懂,不需要求导,适用于一般的非线性问题。然而,也存在一些缺点,如容易陷入局部最优解,对于高维问题收敛慢等。 总之,下坡单纯形算法是一种用于多维函数优化的简单而直观的方法,通过构建和调整多面体来逐步寻找最小值。它在实践中具有一定的应用价值,但也需要根据具体问题的特性进行适当的调整和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值