刚学习了线性规划的部分,作业就是自行实现单纯形法,看起来麻烦,其实也不麻烦,详细单纯形内容参见《运筹学》,算法部分参照《算法导论》。
注:以下代码缺少判定是否无界的情况,只要在代码中加入验证即可。
1>确定基向量,即
//取得基向量,遍历A,取得一列仅有一个1的列
private List al = new List();//存储基变量的脚标
for (int i = 0; i < A.GetLength(1); i++)
{
flag = 0;
for (int j = 0; j < A.GetLength(0); j++)
{
if(A[j, i]==1) flag += 1;
if(A[j, i]==0) flag += 0;
if((A[j, i]!=1)&&(A[j, i]!=0)) flag+=2;
}
if (flag == 1) this.al.Add(i);
}
2>确定cj-zj
private void get_c_z() //得到判定数组
{
for (int i = 0; i < this.c_z.Length; i++)
{
this.c_z[i]= this.c[i];
for (int j = 0; j < this.A.GetLength(0); j++)
this.c_z[i] = this.c_z[i] - this.A[j, i] * this.al2[j];
}
}
3>找到主变元
private void get_variable()
{
//找到c_z最大的
int k = 0;
double temp = this.c_z[0];
for (int i = 1; i < this.c_z.Length; i++)
{
if (this.c_z[i] > temp) { k = i; temp = this.c_z[i]; }
}
//找k列中b/a最小的
int n= 0;
while(this.A[n,k]<=0)
n++;
double ratio=this.b[n]/this.A[n,k];
for (int j = n + 1; j < this.A.GetLength(0); j++)
if ((this.A[j, k] > 0) && (this.b[j] / this.A[j, k] < ratio)) { n = j; ratio = this.b[j] / this.A[j, k]; }
//交换的位置在n行k列,交换基
this.al[n] = k;
this.al2[n] = this.c[k];
//高斯消元
pivot(n,k);
//更新判定数组
get_c_z();
}
4>高斯消元实现
private void pivot(int n,int k)//n行k列为主变元,高斯消元
{
//k列全为1
double ratio;
for (int i = 0; i < this.A.GetLength(0); i++)
{
if ((this.A[i, k] != 0)&&(this.A[i,k]!=1))//等于0,1时不用运算
{
ratio = Math.Abs(this.A[i, k]) / 1;
for (int j = 0; j < this.A.GetLength(1); j++)
this.A[i, j] = this.A[i, j] / ratio;
this.b[i] = this.b[i] / ratio;
}
}
//除第n行保留为1外,其余行均减去第n行
for (int i = 0;i < this.A.GetLength(0); i++)
{
if (i != n)
{
if (this.A[i, k] != 0)//为零时不用运算
{
if (this.A[i, k] == 1)
{
for (int j = 0; j < this.A.GetLength(1); j++)
this.A[i, j] = this.A[i, j] - this.A[n, j];
this.b[i] = this.b[i] - this.b[n];
}
if (this.A[i, k] == -1)
{
for (int j = 0; j < this.A.GetLength(1); j++)
this.A[i, j] = this.A[i, j] + this.A[n, j];
this.b[i] = this.b[i] + this.b[n];
}
}
}
}
//将基变量行恢复,即al中存储的必须要为1,this.A[i, this.al[i]]==1
for (int i = 0; i < this.A.GetLength(0); i++)
{
if (this.A[i, this.al[i]] != 0)
{
ratio = this.A[i, this.al[i]] / 1;
for (int j = 0; j < this.A.GetLength(1); j++)
this.A[i, j] = this.A[i, j] / ratio;
this.b[i] = this.b[i] / ratio;
}
}
}
5>运行结束条件
while (is_negative() != true) //判定数组全为非正数,结束
{
//找到变元,交换基变量,高斯消元
get_variable();
}
private bool is_negative()
{
bool flag = true;
foreach (int i in this.c_z)
if (i > 0)
{
flag = false; break;
}
return flag;
}