单纯形法的代码实现

    刚学习了线性规划的部分,作业就是自行实现单纯形法,看起来麻烦,其实也不麻烦,详细单纯形内容参见《运筹学》,算法部分参照《算法导论》。

注:以下代码缺少判定是否无界的情况,只要在代码中加入验证即可。

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;
         }

你可能感兴趣的:(C#)