作者: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]<<"\t"; 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 /////////////////////////////////////