zoukankan      html  css  js  c++  java
  • [单纯形法与线性规划]【学习笔记】

    很早以前学过理论,3个月前又学了一遍写了一点笔记,现在觉得以(已)前(经)写(完)的(全)太(忘)丑(记)于是重写一遍

    参考资料:

    1.算法导论

    2.2016国家集训队论文


    标准型

    $Maximizequad sumlimits_{j=1}^{n} c_jx_j$

    $Satisfyquad constraint:$

    $sumlimits_{j=1}^{n} a_{ij}x_j le b_i, i=1,2,...,m$

    $x_j ge 0, j=1,2,...,n$

    $n$个变量,$m+n$个约束

    构造$m*n$的矩阵$A$,$m$维向量$b$,$n$维向量$c$

    $Maximizequad c^Tx$

    $Satisfyquad constraint:$

    $Ax le b$

    $x ge 0$

    转化为标准型:

    松弛型

    松弛变量$x_{n+i}$

    $ sumlimits_{j=1}^{n} a_{ij}x_j le b_i   ightarrow  $$x_{n+i}=b_i - sumlimits_{j=1}^{n} a_{ij}x_j, x_{n+i} ge 0$

    等式左侧为基本变量,右侧为非基本变量


    单纯型算法

    每个约束定义了$n$维空间中的一个半空间(超平面),交集形成的可行域是一个凸区域称为单纯型

    目标函数是一个超平面,最优解在凸区域定点处取得

    基本解:非基本变量值为$0$,基本变量为右侧的常数

    基本可行解:所有$b_i ge 0$

    通过不断的转轴操作,在$n$维凸区域的顶点上不断移动(转轴),使得基本解的目标值不断变大,最终达到最优解

    转轴:

    选取一个非基本变量$x_e$为替入变量,基本变量$x_l$为替出变量,将其互换

    为了防止循环,根据$Bland$规则,选择下标最小的变量

    初始化:

    算法导论上有一个辅助线性规划的做法

    但我发现好多人都用了随机初始化的黑科技

    在所有$b_i < 0$的约束中随机选一个作为$x_l$,再随机选一个$a_{le} < 0$的作为$x_e$,然后$Pivot(l,e)$后$b_i$就变正了...



    代码实现:

    直接用一个$a[][]$来保存目标函数和约束

    $Pivot$里的各种操作推导一下很清楚,用了两个$trick$避免了一些判断

    $id$用来保存基本变量和非基本变量集合

     

    针对全幺模矩阵可以进行提取非零系数的优化

    UOJ#179. 线性规划

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int N=25;
    const double eps=1e-8,INF=1e15;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,m,type;
    double a[N][N],ans[N];
    int id[N<<1];
    int q[N];
    void Pivot(int l,int e){
        swap(id[n+l],id[e]);
        double t=a[l][e]; a[l][e]=1;
        for(int j=0;j<=n;j++) a[l][j]/=t;
        for(int i=0;i<=m;i++) if(i!=l && abs(a[i][e])>eps){
            t=a[i][e]; a[i][e]=0;
            for(int j=0;j<=n;j++) a[i][j]-=a[l][j]*t;
        }
    }
    bool init(){
        while(true){
            int e=0,l=0;
            for(int i=1;i<=m;i++) if(a[i][0]<-eps && (!l||(rand()&1))) l=i;
            if(!l) break;
            for(int j=1;j<=n;j++) if(a[l][j]<-eps && (!e||(rand()&1))) e=j;
            if(!e) {puts("Infeasible");return false;}
            Pivot(l,e);
        }
        return true;
    }
    bool simplex(){
        while(true){
            int l=0,e=0; double mn=INF;
            for(int j=1;j<=n;j++) 
                if(a[0][j]>eps) {e=j;break;}
            if(!e) break;
            for(int i=1;i<=m;i++) if(a[i][e]>eps && a[i][0]/a[i][e]<mn)
                mn=a[i][0]/a[i][e],l=i;
            if(!l) {puts("Unbounded");return false;}
            Pivot(l,e);
        }
        return true;
    }
    int main(){
        freopen("in","r",stdin);
        srand(317);
        n=read();m=read();type=read();
        for(int i=1;i<=n;i++) a[0][i]=read();
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++) a[i][j]=read();
            a[i][0]=read();
        }
        for(int i=1;i<=n;i++) id[i]=i;
        if(init() && simplex()){
            printf("%.8lf
    ",-a[0][0]);
            if(type){
                for(int i=1;i<=m;i++) ans[id[n+i]]=a[i][0];
                for(int i=1;i<=n;i++) printf("%.8lf ",ans[i]);
            }
        }
    }
    View Code

    问题转化为单纯型:

    最短路

    最大流

    最小费用最大流

    多商品流(目前没写过)

    对偶性:

    ${Max c^Tx : Ax le b, x ge 0} quad {Min b^Ty : A^Ty ge c, t ge 0}$

    最大化与最小化互换,常数与目标函数互换,改变不等号,变量与约束对应

    最大流与最小割

    二分图最大权匹配与最小顶标和

    最小顶标和:一个带权二分图,两个顶点的顶标之和不小于连接它们的边的边权,求最小顶标和

    所有边权为$1$,就是最大匹配和最小点覆盖

    $d_{uv}$表示$u,v$是否匹配

    $Maxquad sumlimits_{(u,v)in E}c_{uv}d_{uv}$

    $Sat$

    $sumlimits_{v in Y}d_{uv} le 1 quad quad u in X$

    $sumlimits_{u in X}d_{uv} le 1 quad quad v in Y$

    $d_{u,v}in {0,1}$

    令$p_u,p_v$为两类约束对偶之后的变量


    $Minquad sumlimits_{u in X}p_u + sumlimits_{v in Y}p_v$

    $Sat$

    $p_u+p_v ge c_{uv} quad quad u in X,v in Y$

    $p_u,p_v ge 0$

     

    全幺模矩阵(totally unimodular matrix)

    充分条件:

    1.仅有$-1,0,1$构成

    2.每列至多两个非零数

    3.行可分为两个集合:

    一列包含两个同号非零数,两行不在同一个集合

    一列包含两个异号非零数,两行在同一个集合

    线性规划中$A$为全幺模矩阵,则单纯形法过程中所有系数$in{-1,0,1}$

    可以去除系数为$0$的项进行优化!

    任何最大流、最小费用最大流的线性规划都是全幺模矩阵

  • 相关阅读:
    JavaScript打印99乘法表
    Python列表推导式玩法
    Python错误重试方法
    pandas + jupyter进行数据处理
    新手小白的爬虫神器-无代码高效爬取数据
    Adb连接模拟器出现版本错误
    Python发送多人邮件报错
    Django入门
    git clone 下载速度解决办法
    Python实现自动刷抖音
  • 原文地址:https://www.cnblogs.com/candy99/p/lp.html
Copyright © 2011-2022 走看看