LP线性规划求解 之 单纯形 算法

认识-单纯形

  • 核心: 顶点旋转
  1. 随机找到一个初始的基本可行解

  2. 不断沿着可行域旋转(pivot)

  3. 重复2,直到结果不能改进为止

案例-过程

以上篇的case2的松弛型为例.

\(min \ y = -x1-x2\)

s.t.

\(50x1 + 20x2 + a1 = 2000 \\ -1.5x1+x2 + a2 =0 \\ x1-x2+a3=0 \\ x1,x2,a1,a2,a3 >=0\\ 其中a1,a2,a3为松弛变量\)

即:

基本变量(松弛): a1, a2, a3

非基本变^量: x1, x2

\(min \ y=-x1-x2\\ s.t.\)

\(a1 = 2000-50 x1-20 x2 \\ a2 = 1.5x1 -x2 \\ a3 = -x1+x2 \\ x1,x2,a1,a2,a3 >=0\)

基本可行解即将右边非基本变量设置为0, 计算左边基本变量(松弛)的值

令: x1, x2为0, 即基本可行解为:

\(x^t = (0,0,2000,0,0)^t, 目标值y= (-x1-x2) = 0\)

旋转(pivot)流程

  • 替入变量: 当前目标函数中第一个系数为负的非基本变量(松弛)为替入变量

  • 替出变量: 最严格约束里的基本变量为替出变量

即:

  • x1 是目标函数中第一个系数为负数(替入变量), 计算x1在各条件下的约束值

  • case1: x1 = 40

  • case2: x1 = \(\infty\)

  • case3: x1 = 0

得到条件3为最严格约束, 即对应的a3为替出变量.

即由 \(a3 = -x1+x2 \ 得 x1 = x2-a3\)

对原目标及约束中的x1进行替换即:

\(min \ y = -2x2+a3 \\ s.t.\)

\(x1 = x2-a3 \\ a1 = 2000-50(x2-a3) - 20x2 = 2000 - 70x2 + 50a3 \\ a2 = 1.5(x2 - a3) - x2 = 0.5x2 - 1.5a3\)

然后旋转,令右边变量为0, 即:

\(x = (0,0,0,2000,0)^t, 目标y=0\)

发现目标值y没有变小, 于是再继续转

  • 目标中第一为负的是x2, 其在各条件下的约束值为

  • case1: \(x2 =\infty\)

  • case2: \(x2 = \frac {2000}{70}\)

  • case3: \(x2 = \infty\)

得到条件2为最严格约束, 即对应的a1为替出变量.

即由\(a1 = 2000-70x2+50a3 \ 得 \ x2 = \frac {2000 + 50a3 -a1}{70}\)

对原目标的x2作替换即:

\(min \ y = \frac{-4000}{70} - \frac{3}{7} a3 + \frac{1}{35}xa1 \\ s.t.\)

\(x1 =\frac{2000}{70} - \frac{2}{7}a3- \frac{1}{70}a1 \\ x2 = \frac {2000 + 50a3 -a1}{70} \\ a2 = \frac {1000}{70} - \frac {16}{14}a3 - \frac {1}{140}a1\)

然后再旋转, 令右边的变量为0, 即:

\(x = (\frac {200}{70}, \frac {2000}{70}, 0, \frac{1000}{70},0), 目标 \ y = - \frac{4000}{70}\)

然后再继续旋转...

....

当目标函数没有系数为负, 即说明无法再通过旋转继续减小目标函数, 此时收敛,即停止旋转, 此时的基本解即为最优解.

最后得 \(x = (25,37,5,12.5,0,0), 达到最优解目标 \ min \ y = -62.5\)

单纯形算法步骤(参考网上)

  1. 将LP的目标函数及约束转为标准型

  2. 转换为松弛型 (即将不等于转为等于)

  3. 找到一个基本可行解, 寻找目标的替入变量, 约束的替出变量, 替换目标函数, 不断旋转

  4. 重复步骤3, 直到目标系数中没有系数为负数的项, 收敛, 即结束算法

(附) Python代码实现

  • 是搬运大佬的代码, 自己有很多也尚未看明白, 只作个笔记, 当然还是为了copy
  • 个人觉得这个大佬的代码,追求简洁但严重丢失了可读性, PEP8
  • 注释 是后面加的, 当然,原来的版本也基本没啥注释, 很是任性

import numpy as np class Simplex(object):
def __init__(self, obj, max_mode=False):
self.max_mode = max_mode # 默认是求min,如果是max目标函数要乘-1
self.mat = np.array([[0] + obj]) * (-1 if max_mode else 1) def add_constraint(self, a, b):
self.mat = np.vstack([self.mat, [b] + a]) #矩阵加入约束 def solve(self):
m, n = self.mat.shape # 矩阵里有1行目标函数,m - 1行约束,应加入m-1个松弛变量
temp, B = np.vstack([np.zeros((1, m - 1)), np.eye(m - 1)]), list(range(n - 1, n + m - 1)) # temp是一个对角矩阵,B是个递增序列
mat = self.mat = np.hstack([self.mat, temp]) # 横向拼接
#判断目标函数里是否还有负系数项
while mat[0, 1:].min() < 0:
# 在目标函数里找到第一个负系数的变量,找到替入变量
col = np.where(mat[0, 1:] < 0)[0][0] + 1
row = np.array([mat[i][0] / mat[i][col] if mat[i][col] > 0 else 0x7fffffff for i in
range(1, mat.shape[0])]).argmin() + 1 # 找到最严格约束的行,也就找到替出变量
if mat[row][col] <= 0: return None # 若无替出变量,原问题无界
mat[row] /= mat[row][col] #替入变量和替出变量互换
ids = np.arange(mat.shape[0]) != row
# 对i!= row的每一行约束条件,做替入和替出变量的替换
mat[ids] -= mat[row] * mat[ids, col:col + 1]
B[row] = col #用B数组记录替入的替入变量
return mat[0][0] * (1 if self.max_mode else -1), {B[i]: mat[i, 0] for i in range(1, m) if B[i] < n} #返回目标值,对应x的解就是基本变量为对应的bi,非基本变量为0 """
minimize -x1 - 14x2 - 6x3
st
x1 + x2 + x3 <=4
x1 <= 2
x3 <= 3
3x2 + x3 <= 6
x1 ,x2 ,x3 >= 0
answer :-32
"""
t = Simplex([-1, -14, -6])
t.add_constraint([1, 1, 1], 4)
t.add_constraint([1, 0, 0], 2)
t.add_constraint([0, 0, 1], 3)
t.add_constraint([0, 3, 1], 6)
print(t.solve())
print(t.mat)

调参侠求解LP

这里以为case2作为例子, 化为minimize标准型哦.

\(min \ z = -x1 - x2 \\ s.t.\)

\(x1-x2<0 \\ -1.5x1 + x2 <= 0 \\ 50x1+20x2 <= 2000 \\ x1,x2 >=0\)

api: from scipy.optimize import linprog

我一般都是用pycharm来看源码的api文档, 这样会印象深刻一下.

  • c: 目标函数(minimize)的系数, 1D-array

  • A_ub: 左边不等号相关的系数矩阵 2D-array

  • b_ub: 即A_up中的对应行的右边值 1D-array

  • A_eq: 左边等号相关的系数矩阵 2D-array

  • b_eq: 即A_eq中的对应行的右边值 1D-array

  • bounds: sequence

    • (min, max) pairs for each element in "X"
from scipy.optimize import linprog
import numpy as np # 1. 目标函数系数
c = np.array([-1, -1])
# 2. 不等号
A_ub = np.array([[-1.5, 1], [50, 20]])
b_ub = np.array([0, 2000])
# 3. 等号(此题没有A_eq, b_eq)
# 4. bounds
limit_1, limit_2 = (0, None), (0, None)
# 5. solve: default "simplex"
ret = linprog(c, A_ub, b_ub, bounds(limit_1, limit_2))
print(ret)
     fun: -62.5
message: 'Optimization terminated successfully.'
nit: 2
slack: array([0., 0.])
status: 0
success: True
x: array([25. , 37.5])

LP线性规划求解 之 单纯形 算法的更多相关文章

  1. 线性规划之单纯形算法矩阵描述与python实现

    声明 本文为本人原创,转载请注明出处.本文仅发表在博客园,作者LightningStar. 问题描述 所有的线性规划问题都可以归约到标准型的问题,规约过程比较简单且已经超出本文范围,不再描述,可以参考 ...

  2. LP线性规划初识

    认识LP 线性规划(Linear Programming) 特指目标函数和约束条件皆为线性的最优化问题. 目标函数: 多个变量形成的函数 约束条件: 由多个等式/不等式形成的约束条件 线性规划: 在线 ...

  3. Excel与Google Sheets中实现线性规划求解

    很久没更新过APS系列文章了,这段时间项目工作确实非常紧,所以只能抽点时间学习一下运筹学的入门知识,算是为以后的APS项目积累点基础.看了一些运筹学的书(都是科普级别的)发现原来我目前面对的很多排产. ...

  4. 对偶理论、拉格朗日对偶问题、LP线性规划对偶性质

    Lagrange 对偶问题 定义其的对偶问题: Lagrange函数 考虑线性规划问题 若取集合约束D={x|x≥0},则该线性规划问题的Lagrange函数为 线性规划的对偶问题为: 对偶定理原问题 ...

  5. [转]利用excel进行线性规划求解

                           利用线性回归方法求解生产计划 方法一: 1.建立数学模型: 设变量:设生产拉盖式书桌x台,普通式书桌y台,可得最大利润 ‚确定目标函数及约束条件 目标函 ...

  6. 使用python scipy.optimize linprog和lingo线性规划求解最大值,最小值(运筹学学习笔记)

    1.线性规划模型: 2.使用python scipy.optimize linprog求解模型最优解: 在这里我们用到scipy中的linprog进行求解,linprog的用法见https://doc ...

  7. PCB仿真软件与电磁场求解器的算法

    1. 简介 目前商业化的PCB仿真软件主要有: Cadence公司的Sigrity.Ansys公司的SIwave/HFSS.CST公司的CST.Mentor公司的HyperLynx.Polor公司的S ...

  8. 使用excel结合线性规划求解Holt-Winters参数

      其实上面这个是Holt-Winters无季节趋势模型, 上面的S(t)对应下面的a(t)——截距(平滑值)            b(t)仍然对应b(t)——趋势,T对应k.           ...

  9. 单纯形算法 matlab

    %单纯形 %目标函数标准化 % min x1-3x2+2x3 %输入参量 N=[3 -1 2;-2 4 0;-4 3 8]; B=eye(3); A=[N B]; cn=[1;-3;2]; cb=ze ...

随机推荐

  1. browserslist详解

    https://www.jianshu.com/p/d45a31c50711 https://juejin.im/post/5b8cff326fb9a019fd1474d6 https://githu ...

  2. webpack中路径的理解

    webpack 前端打包工具, 开发人员要面对的路径主要是: 打包前的路径(开发环境路径)和打包后的路径(生产环境路径) 在webpack.config.js中配置的output.path, outp ...

  3. [RN] React Native 中使用 stickyHeaderIndices 实现 ScrollView 的吸顶效果

    React Native中,ScrollView组件可以使用 stickyHeaderIndices 轻松实现 sticky 效果. 例如下面代码中: <ScrollView showsVert ...

  4. NOIP2013-2014提高组题目浅析

    1.前言 迎接NOIP的到来...在这段闲暇时间,决定刷刷水题.这里只是作非常简单的一些总结. 2.NOIP2014 <1> 生活大爆炸之石头剪刀布(模拟) 这是一道考你会不会编程的题目. ...

  5. 三天精通Vue--Vue的常用语法

    Vue的介绍 官网教程:https://cn.vuejs.org/v2/guide/installation.html 掘金:https://juejin.im/ cdn(在线的网络连接资源):htt ...

  6. Salesforce 开发整理(二)报表开发学习

    Salesforce提供了强大的报表功能,支持表格.摘要.矩阵以及结合共四种形式,本文探讨在站在开发的角度要如何理解报表. 一:查询报表基本信息报表在Sales force中是Report对象,基本的 ...

  7. 2018-2019-2 20165313 《网络对抗技术》 Exp 9 Web安全基础

    一.实验要求 本实践的目标理解常用网络攻击技术的基本原理,做不少于7个题目,共3.5分.包括(SQL,XSS,CSRF).Webgoat实践下相关实验. 二.实验问题回答 (1)SQL注入攻击原理,如 ...

  8. Android的开机启动流程

    1.Android的开机启动流程 Android的层次框架图,如下所示: 图片清晰地展示了Android的五层架构,从上到下依次是:应用层.应用框架层.库层.运行时层以及Linux内核层.Androi ...

  9. Linux内核kobject结构体分析

    1.前言 Linux内核中有大量的驱动,而这些驱动往往具有类似的结构,根据面向对象的思想,可以将共同的部分提取为父类,而这个父类就是kobject,kobject结构体中包含了大量设备的必须信息,而三 ...

  10. SQL Server ----- 备份数据库 生成(.bak)文件

    转移数据库   备份数据库 选中数据库 进入后界面如图 选择合适位置进行备份 注意:选择配置好保存位置的 成功后出现 如果出现错误. 还有一种可能是哪个文件夹中已经有了一个 把文件家中的那个删了 还原 ...