zoukankan      html  css  js  c++  java
  • 单纯形法C++实现

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4156685.html

    使用单纯型法来求解线性规划,输入单纯型法的松弛形式,是一个大矩阵,第一行为目标函数的系数,且最后一个数字为当前轴值下的 z 值。下面每一行代表一个约束,数字代表系数每行最后一个数字代表 b 值。

    算法和使用单纯性表求解线性规划相同。

    对于线性规划问题:

    Max      x1 + 14* x2 + 6*x3 

    s . t .  x1 + x2 + x3 <= 4

        x1<= 2

        x3 <= 3

        3*x2 + x3 <= 6

        x1,x2,x3 >= 0

    我们可以得到其松弛形式:

    Max  x1 +  14*x2 + 6*x3
    s.t.   x1 +  x2   + x3   + x4 = 4
        x1               + x5 = 2
                x3           + x6 = 3
             3*x2   + x3               + x7 = 6
        x1 , x2 , x3 , x4 , x5 , x6 , x7 ≥ 0

    我们可以构造单纯性表,其中最后一行打星的列为轴值。

    单纯性表
    x1 x2 x3 x4 x5 x6 x7 b
    c1=1 c2=14 c3=6 c4=0 c5=0 c6=0 c7=0 -z=0
    1 1 1 1 0 0 0 4
    1 0 0 0 1 0 0 2
    0 0 1 0 0 1 0 3
    0 3 1 0 0 0 1 6
          * * * *  

    在单纯性表中,我们发现非轴值的x上的系数大于零,因此可以通过增加这些个x的值,来使目标函数增加。我们可以贪心的选择最大的c,再上面的例子中我们选择c2作为新的轴,加入轴集合中,那么谁该出轴呢?

    其实我们由于每个x都大于零,对于x2它的增加是有所限制的,如果x2过大,由于其他的限制条件,就会使得其他的x小于零,于是我们应该让x2一直增大,直到有一个其他的x刚好等于0为止,那么这个x就被换出轴。

    我们可以发现,对于约束方程1,即第一行约束,x2最大可以为4(4/1),对于约束方程4,x2最大可以为3(6/3),因此x2最大只能为他们之间最小的那个,这样才能保证每个x都大于零。因此使用第4行,来对各行进行高斯行变换,使得二列第四行中的每个x都变成零,也包括c2。这样我们就完成了把x2入轴,x7出轴的过程。变换后的单纯性表为:

    单纯性表
    x1 x2 x3 x4 x5 x6 x7 b
    c1=1 c2=0 c3=1.33 c4=0 c5=0 c6=0 c7=-4.67 -z=-28
    1 0 0.67 1 0 0 -0.33 2
    1 0 0 0 1 0 0 2
    0 0 1 0 0 1 0 3
    0 1 0.33 0 0 0 0.33 2
        * * *    

    继续计算,我们得到:

    单纯性表
    x1 x2 x3 x4 x5 x6 x7 b
    c1=-1 c2=0 c3=0 c4=0 c5=-2 c6=0 c7=0 -z=-32
    1.5 0 1 1.5 0 0 -0.5 3
    1 0 0 0 1 0 0 2
    0 0 1 0 0 1 0 3
    0 1 0.33 0 0 0 0.33 2
        * * *    

    此时我们发现,所有非轴的x的系数全部小于零,即增大任何非轴的x值并不能使得目标函数最大,从而得到最优解32.

    整个过程代码如下所示:

      1 #include <cstdio>
      2 #include <climits>
      3 #include <cstdlib>
      4 #include <iostream>
      5 #include <cstring>
      6 #include  <vector>
      7 #include  <fstream>
      8 #include <set>
      9 using namespace std;
     10 vector<vector<double> > Matrix;
     11 double Z;
     12 set<int> P;
     13 size_t cn, bn;
     14 
     15 bool Pivot(pair<size_t, size_t> &p)//返回0表示所有的非轴元素都小于0
     16 {
     17     int x = 0, y = 0;
     18     double cmax = -INT_MAX;
     19     vector<double> C = Matrix[0];
     20     vector<double> B;
     21 
     22     for( size_t i = 0 ; i < bn ; i++ )
     23     {
     24         B.push_back(Matrix[i][cn-1]);
     25     }
     26     
     27     for( size_t i = 0 ; i < C.size(); i++ )//在非轴元素中找最大的c
     28     {
     29         if( cmax < C[i] && P.find(i) == P.end())
     30         {
     31             cmax = C[i];
     32             y = i;
     33         }
     34     }
     35     if( cmax < 0 )
     36     {
     37         return 0;
     38     }
     39 
     40     double bmin = INT_MAX;
     41     for( size_t i = 1 ; i < bn ; i++ )
     42     {
     43         double tmp = B[i]/Matrix[i][y];
     44        if( Matrix[i][y] != 0 && bmin > tmp )
     45        {
     46            bmin = tmp;
     47            x = i;
     48        }
     49     }
     50 
     51     p = make_pair(x, y);
     52 
     53     for( set<int>::iterator it = P.begin() ; it != P.end() ; it++)
     54     {
     55         if( Matrix[x][*it] != 0 )
     56         {
     57             //cout<<"erase "<<*it<<endl;
     58             P.erase(*it);
     59             break;
     60         }
     61     }
     62     P.insert(y);
     63     //cout<<"add "<<y<<endl;
     64     return true;
     65 }
     66 
     67 void pnt()
     68 {
     69     for( size_t i = 0 ; i < Matrix.size() ; i++ )
     70     {
     71         for( size_t j = 0 ; j < Matrix[0].size() ; j++ )
     72         {
     73             cout<<Matrix[i][j]<<"	";
     74         }
     75     cout<<endl;
     76     }
     77     cout<<"result z:"<<-Matrix[0][cn-1]<<endl;
     78 }
     79 
     80 void Gaussian(pair<size_t, size_t> p)//行变换
     81 {
     82     size_t  x = p.first;
     83     size_t y = p.second;
     84     double norm = Matrix[x][y];
     85     for( size_t i = 0 ; i < cn ; i++ )//主行归一化
     86     {
     87         Matrix[x][i] /= norm;
     88     }
     89     for( size_t i = 0 ; i < bn && i != x; i++ )
     90     {
     91         if( Matrix[i][y] != 0)
     92         {
     93             double tmpnorm = Matrix[i][y];
     94             for( size_t j = 0 ; j < cn ; j++ )
     95             {
     96                 Matrix[i][j] = Matrix[i][j] - tmpnorm * Matrix[x][j];
     97             }
     98         }
     99     }
    100 }
    101 
    102 void solve()
    103 {
    104     pair<size_t, size_t> t;
    105     while(1)
    106     {
    107 
    108         pnt();
    109         if( Pivot(t) == 0 )
    110         {
    111             return;
    112         }        
    113         cout<<t.first<<" "<<t.second<<endl;
    114         for( set<int>::iterator it = P.begin(); it != P.end()  ; it++ )
    115         {
    116             cout<<*it<<" ";
    117         }
    118         cout<<endl;
    119         Gaussian(t);
    120     }
    121 }
    122 
    123 int main(int argc, char *argv[])
    124 {
    125     ifstream fin;
    126     fin.open("./test");
    127     fin>>cn>>bn;
    128     for( size_t i = 0 ; i < bn ; i++ )
    129     {
    130         vector<double> vectmp;
    131         for( size_t j = 0 ; j < cn ; j++)
    132         {
    133             double tmp = 0;
    134             fin>>tmp;
    135             vectmp.push_back(tmp);
    136         }
    137         Matrix.push_back(vectmp);
    138     }
    139 
    140     for( size_t i = 0 ; i < bn-1 ; i++ )
    141     {
    142         P.insert(cn-i-2);
    143     }
    144     solve();
    145 }
    146 /////////////////////////////////////
    147 //glpk input:
    148 ///* Variables */
    149 //var x1 >= 0;
    150 //var x2 >= 0;
    151 //var x3 >= 0;
    152 ///* Object function */
    153 //maximize z: x1 + 14*x2 + 6*x3;
    154 ///* Constrains */
    155 //s.t. con1: x1 + x2 + x3 <= 4;
    156 //s.t. con2: x1  <= 2;
    157 //s.t. con3: x3  <= 3;
    158 //s.t. con4: 3*x2 + x3  <= 6;
    159 //end;
    160 /////////////////////////////////////
    161 //myinput:
    162 //8 5
    163 //1 14 6 0 0 0 0 0
    164 //1 1 1 1 0 0 0 4
    165 //1 0 0 0 1 0 0 2
    166 //0 0 1 0 0 1 0 3
    167 //0 3 1 0 0 0 1 6
    168 /////////////////////////////////////
    View Code
  • 相关阅读:
    JDBC 关闭数据库连接与自动提交【转】
    va注解应用实例
    Java IO流操作汇总: inputStream 和 outputStream【转】
    dom4j,json,pattern性能对比【原】
    JSP中setattribute与setParameter的区别
    setAttribute()和getAttibute(),getParameter()
    org.hibernate.MappingException: Unknown entity
    SQL保留关键字不能用作表名
    缺jstl.jar包导致的代码出现异常
    sessionFactory
  • 原文地址:https://www.cnblogs.com/jostree/p/4156685.html
Copyright © 2011-2022 走看看