修正单纯性法
代码如下:
舍去了输入转化的内容,主要包含算法关键步骤。
public class LPSimplexM {
private static final double inf = 1e9;
private int n;// 约束个数
private double[][] A;// 输入函数参数
private double[] b;// 约束值
private double[] c;// 目标函数系数
private double Z;// 目标值
private void InitF() {// 初始化 First
/* problem 1.
* max Z = 5*x1 + 4*x2; min Z = -5*x1 - 4*x2;
* x1 + 3*x2 <= 90;x1 + 3*x2 + x3= 90;
* 2*x1 + x2 <= 80;=> 2*x1 + x2 + x4= 80;
* x1 + x2 <= 45;x1 + x2 + x5 = 45;
* xi >= 0
*/
/* problem 2.
* min Z = -7*x1 - 12*x2;
* 9*x1 + 4*x2 + x3 = 360;
* 4*x1 + 5*x2 +x4 = 200;
* 3*x1 + 10*x2 + x5 = 300;
* xi >= 0
*/
n = 3;
A = new double[n+1][n+1];
b = new double[n+1];
//c = new double[n<<1];
Z = inf;
// 约束初始条件
A[1][1] = 1;A[1][2] = 3;
A[2][1] = 2;A[2][2] = 1;
A[3][1] = 1;A[3][2] = 1;
// 条件值
// problem 1.
//b[1] = 90;
//b[2] = 80;
//b[3] = 45;
// problem 2.
b[1] = 360;
b[2] = 200;
b[3] = 300;
//for(int i = 1; i <= n; i++)System.out.println("b[" + i + "] = " + b[i]);
// 目标函数系数
//c[1] = -5;c[2] = -4;
}
int m;
private double[][] p;
private double[][] e, oe;
private double[][] E, oE;
private double[] X;
private boolean[] G;
private int[] S;
private void InitS() {
m = 2;
p = new double[n+1][n+m+1];
e = new double[n+1][n+1];
oe = new double[n+1][n+1];
E = new double[n+1][n+1];
oE = new double[n+1][n+1];
X = new double[n+1];
G = new boolean[n+m+1];
S = new int[n+1];
c = new double[n+m+1];
// problem 1.
//c[1] = -5;c[2] = -4;c[3] = 0;c[4] = 0;c[5] = 0;
// problem 2.
c[1] = -7;c[2] = -12;c[3] = 0;c[4] = 0;c[5] = 0;
// problem 1.
//p[1][1] = 1;p[1][2] = 3;p[1][3] = 1;p[1][4] = 0;p[1][5] = 0;
//p[2][1] = 2;p[2][2] = 1;p[2][3] = 0;p[2][4] = 1;p[2][5] = 0;
//p[3][1] = 1;p[3][2] = 1;p[3][3] = 0;p[3][4] = 0;p[3][5] = 1;
// problem 2.
p[1][1] = 9;p[1][2] = 4;p[1][3] = 1;p[1][4] = 0;p[1][5] = 0;
p[2][1] = 4;p[2][2] = 5;p[2][3] = 0;p[2][4] = 1;p[2][5] = 0;
p[3][1] = 3;p[3][2] = 10;p[3][3] = 0;p[3][4] = 0;p[3][5] = 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(i == j)E[i][j] = oE[i][j] = 1;
else E[i][j] = oE[i][j] = 0;
for(int i = 1; i <= n; i++)
X[i] = b[i];
G[1] = false;G[2] = false;G[3] = true;G[4] = true;G[5] = true;
S[1] = 3;S[2] = 4;S[3] = 5;
}
public LPSimplexM() {
InitF();
InitS();
AlgorithmProcess();
solve();
}
private void AlgorithmProcess() {
double[] coE = new double[n+1];// c * E^-1
double[] r = new double [n+m+1];// c - c * E^-1 * p
double[] oEp = new double[n+1];// E^-1 * p;
boolean flag = false;
while(true) {
// x = E^-1 * b
for(int i = 1; i <= n; i++){
X[i] = 0;
for(int j = 1; j <= n; j++)
X[i] += oE[i][j]*b[j];
}
// c * E^-1
for(int i = 1; i <= n; i++){
coE[i] = 0;
for(int j = 1; j <= n; j++)
coE[i] += c[S[j]]*oE[j][i];
}
// r = c - c * E^-1 * p => min r' id -> k
int k = -1;
flag = false;
for(int i = 1; i <= n+m; i++)if(!G[i]){
double ans = 0;
for(int j = 1; j <= n; j++)
ans += coE[j]*p[j][i];
r[i] = c[i] - ans;
if(!flag && r[i] < 0){
k = i;
flag = true;
}else if(flag && r[i] < r[k]){
k = i;
}
}
if(k == -1)return ;// solution output 1(X, S 为最优解)
// E^-1 * p;=> min theta>0' id -> s
int s = -1;
flag = false;
for(int i = 1; i <= n; i++){
oEp[i] = 0;
for(int j = 1; j <= n; j++){
oEp[i] += oE[i][j]*p[j][k];
}
if(oEp[i] > 0){
if(!flag){
s = i;
flag = true;
}else if(flag && X[i]/oEp[i] < X[s]/oEp[s]){
s = i;
}
}
}
if(!flag)return ; // no solution 1(无允许解)
if(s == -1)return ;// no solution 2(该问题有无解集)
// p[s] = p[k], 形成新的矢量基 E
G[S[s]] = false;G[k] = true;
S[s] = k;
//System.out.println("k = " + k + "; s = " + s);
for(int i = 1; i <= n; i++){
p[i][k] = -1.0*oEp[i]/oEp[s];
if(i == s)
p[i][k] = 1/oEp[s];
}
for(int i = 1; i <= n; i++){
int id = S[i];
for(int j = 1; j <= n; j++){
if(i == s){
e[j][i] = p[j][k];
}else{
if(j == i){
e[j][i] = 1;
}else{
e[j][i] = 0;
}
}
}
}
//for(int i = 1; i <= n; i++){
//for(int j = 1; j <= n; j++){
//System.out.print(oE[i][j] + " ");
//}System.out.println();
//}System.out.println("{oE}");
//for(int i = 1; i <= n; i++){
//for(int j = 1; j <= n; j++){
//System.out.print(e[i][j] + " ");
//}System.out.println();
//}System.out.println("{e}");
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
oe[i][j] = 0;
for(int t = 1; t <= n; t++){
oe[i][j] += e[i][t]*oE[t][j];
}
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
oE[i][j] = oe[i][j];
//System.out.print(oE[i][j] + " ");
}//System.out.println();
}//System.out.println();
}
}
// 最优解输出
private void solve() {
Z = 0;
for(int i = 1; i <= n; i++){
int id = S[i];
Z += c[id]*X[i];
System.out.println(id + " : " + X[i] + " * " + -c[id]);
}
System.out.println("Z = " + -Z);
}
public static void main(String[] args) {
new LPSimplexM();
}
}
如有问题,请网友指正。
希望网友的交流,共同进步。