Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C++;单纯形法的实现_C++_Algorithm_Simplex - Fatal编程技术网

C++ C/C++;单纯形法的实现

C++ C/C++;单纯形法的实现,c++,algorithm,simplex,C++,Algorithm,Simplex,我找不到单纯形法的实现方法。我有一组点,想最小化他们的距离,所以我只需要单纯形法 在发布这个问题之前,我已经在谷歌上找到了我可以使用的任何东西/* /* What: Simplex in C AUTHOR: GPL(C) moshahmed/at/gmail. What: Solves LP Problem with Simplex: { maximize cx : Ax <= b, x >= 0 }. Input: { m, n, Mat[m x n] }

我找不到单纯形法的实现方法。我有一组点,想最小化他们的距离,所以我只需要单纯形法 在发布这个问题之前,我已经在谷歌上找到了我可以使用的任何东西

/*
/*
  What: Simplex in C
  AUTHOR: GPL(C) moshahmed/at/gmail.

  What: Solves LP Problem with Simplex:
    { maximize cx : Ax <= b, x >= 0 }.
  Input: { m, n, Mat[m x n] }, where:
    b = mat[1..m,0] .. column 0 is b >= 0, so x=0 is a basic feasible solution.
    c = mat[0,1..n] .. row 0 is z to maximize, note c is negated in input.
    A = mat[1..m,1..n] .. constraints.
    x = [x1..xm] are the named variables in the problem.
    Slack variables are in columns [m+1..m+n]

  USAGE:
    1. Problem can be specified before main function in source code:
      c:\> vim mosplex.c  
      Tableau tab  = { m, n, {   // tableau size, row x columns.
          {  0 , -c1, -c2,  },  // Max: z = c1 x1 + c2 x2,
          { b1 , a11, a12,  },  //  b1 >= a11 x1 + a12 x2
          { b2 , a21, a22,  },  //  b2 >= a21 x1 + a22 x2
        }
      };
      c:\> cl /W4 mosplex.c  ... compile this file.
      c:\> mosplex.exe problem.txt > solution.txt

    2. OR Read the problem data from a file:
      $ cat problem.txt
            m n
            0  -c1 -c2
            b1 a11 a12
            b2 a21 a11 
      $ gcc -Wall -g mosplex.c  -o mosplex
      $ mosplex problem.txt > solution.txt
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>

#define M 20
#define N 20

static const double epsilon   = 1.0e-8;
int equal(double a, double b) { return fabs(a-b) < epsilon; }

typedef struct {
  int m, n; // m=rows, n=columns, mat[m x n]
  double mat[M][N];
} Tableau;

void nl(int k){ int j; for(j=0;j<k;j++) putchar('-'); putchar('\n'); }

void print_tableau(Tableau *tab, const char* mes) {
  static int counter=0;
  int i, j;
  printf("\n%d. Tableau %s:\n", ++counter, mes);
  nl(70);

  printf("%-6s%5s", "col:", "b[i]");
  for(j=1;j<tab->n; j++) { printf("    x%d,", j); } printf("\n");

  for(i=0;i<tab->m; i++) {
    if (i==0) printf("max:"); else
    printf("b%d: ", i);
    for(j=0;j<tab->n; j++) {
      if (equal((int)tab->mat[i][j], tab->mat[i][j]))
        printf(" %6d", (int)tab->mat[i][j]);
      else
        printf(" %6.2lf", tab->mat[i][j]);
      }
    printf("\n");
  }
  nl(70);
}

/* Example input file for read_tableau:
     4 5
      0   -0.5  -3 -1  -4 
     40    1     1  1   1 
     10   -2    -1  1   1 
     10    0     1  0  -1  
*/
void read_tableau(Tableau *tab, const char * filename) {
  int err, i, j;
  FILE * fp;

  fp  = fopen(filename, "r" );
  if( !fp ) {
    printf("Cannot read %s\n", filename); exit(1);
  }
  memset(tab, 0, sizeof(*tab));
  err = fscanf(fp, "%d %d", &tab->m, &tab->n);
  if (err == 0 || err == EOF) {
    printf("Cannot read m or n\n"); exit(1);
  }
  for(i=0;i<tab->m; i++) {
    for(j=0;j<tab->n; j++) {
      err = fscanf(fp, "%lf", &tab->mat[i][j]);
      if (err == 0 || err == EOF) {
        printf("Cannot read A[%d][%d]\n", i, j); exit(1);
      }
    }
  }
  printf("Read tableau [%d rows x %d columns] from file '%s'.\n",
    tab->m, tab->n, filename);
  fclose(fp);
}

void pivot_on(Tableau *tab, int row, int col) {
  int i, j;
  double pivot;

  pivot = tab->mat[row][col];
  assert(pivot>0);
  for(j=0;j<tab->n;j++)
    tab->mat[row][j] /= pivot;
  assert( equal(tab->mat[row][col], 1. ));

  for(i=0; i<tab->m; i++) { // foreach remaining row i do
    double multiplier = tab->mat[i][col];
    if(i==row) continue;
    for(j=0; j<tab->n; j++) { // r[i] = r[i] - z * r[row];
      tab->mat[i][j] -= multiplier * tab->mat[row][j];
    }
  }
}

// Find pivot_col = most negative column in mat[0][1..n]
int find_pivot_column(Tableau *tab) {
  int j, pivot_col = 1;
  double lowest = tab->mat[0][pivot_col];
  for(j=1; j<tab->n; j++) {
    if (tab->mat[0][j] < lowest) {
      lowest = tab->mat[0][j];
      pivot_col = j;
    }
  }
  printf("Most negative column in row[0] is col %d = %g.\n", pivot_col, lowest);
  if( lowest >= 0 ) {
    return -1; // All positive columns in row[0], this is optimal.
  }
  return pivot_col;
}

// Find the pivot_row, with smallest positive ratio = col[0] / col[pivot]
int find_pivot_row(Tableau *tab, int pivot_col) {
  int i, pivot_row = 0;
  double min_ratio = -1;
  printf("Ratios A[row_i,0]/A[row_i,%d] = [",pivot_col);
  for(i=1;i<tab->m;i++){
    double ratio = tab->mat[i][0] / tab->mat[i][pivot_col];
    printf("%3.2lf, ", ratio);
    if ( (ratio > 0  && ratio < min_ratio ) || min_ratio < 0 ) {
      min_ratio = ratio;
      pivot_row = i;
    }
  }
  printf("].\n");
  if (min_ratio == -1)
    return -1; // Unbounded.
  printf("Found pivot A[%d,%d], min positive ratio=%g in row=%d.\n",
      pivot_row, pivot_col, min_ratio, pivot_row);
  return pivot_row;
}

void add_slack_variables(Tableau *tab) {
  int i, j;
  for(i=1; i<tab->m; i++) {
    for(j=1; j<tab->m; j++)
      tab->mat[i][j + tab->n -1] = (i==j);
  }
  tab->n += tab->m -1;
}

void check_b_positive(Tableau *tab) {
  int i;
  for(i=1; i<tab->m; i++)
    assert(tab->mat[i][0] >= 0);
}

// Given a column of identity matrix, find the row containing 1.
// return -1, if the column as not from an identity matrix.
int find_basis_variable(Tableau *tab, int col) {
  int i, xi=-1;
  for(i=1; i < tab->m; i++) {
    if (equal( tab->mat[i][col],1) ) {
      if (xi == -1)
        xi=i;   // found first '1', save this row number.
      else
        return -1; // found second '1', not an identity matrix.

    } else if (!equal( tab->mat[i][col],0) ) {
      return -1; // not an identity matrix column.
    }
  }
  return xi;
}

void print_optimal_vector(Tableau *tab, char *message) {
  int j, xi;
  printf("%s at ", message);
  for(j=1;j<tab->n;j++) { // for each column.
    xi = find_basis_variable(tab, j);
    if (xi != -1)
      printf("x%d=%3.2lf, ", j, tab->mat[xi][0] );
    else
      printf("x%d=0, ", j);
  }
  printf("\n");
} 

void simplex(Tableau *tab) {
  int loop=0;
  add_slack_variables(tab);
  check_b_positive(tab);
  print_tableau(tab,"Padded with slack variables");
  while( ++loop ) {
    int pivot_col, pivot_row;

    pivot_col = find_pivot_column(tab);
    if( pivot_col < 0 ) {
      printf("Found optimal value=A[0,0]=%3.2lf (no negatives in row 0).\n",
        tab->mat[0][0]);
      print_optimal_vector(tab, "Optimal vector");
      break;
    }
    printf("Entering variable x%d to be made basic, so pivot_col=%d.\n",
      pivot_col, pivot_col);

    pivot_row = find_pivot_row(tab, pivot_col);
    if (pivot_row < 0) {
      printf("unbounded (no pivot_row).\n");
      break;
    }
    printf("Leaving variable x%d, so pivot_row=%d\n", pivot_row, pivot_row);

    pivot_on(tab, pivot_row, pivot_col);
    print_tableau(tab,"After pivoting");
    print_optimal_vector(tab, "Basic feasible solution");

    if(loop > 20) {
      printf("Too many iterations > %d.\n", loop);
      break;
    }
  }
}

Tableau tab  = { 4, 5, {                     // Size of tableau [4 rows x 5 columns ]
    {  0.0 , -0.5 , -3.0 ,-1.0 , -4.0,   },  // Max: z = 0.5*x + 3*y + z + 4*w,
    { 40.0 ,  1.0 ,  1.0 , 1.0 ,  1.0,   },  //    x + y + z + w <= 40 .. b1
    { 10.0 , -2.0 , -1.0 , 1.0 ,  1.0,   },  //  -2x - y + z + w <= 10 .. b2
    { 10.0 ,  0.0 ,  1.0 , 0.0 , -1.0,   },  //        y     - w <= 10 .. b3
  }
};

int main(int argc, char *argv[]){
  if (argc > 1) { // usage: cmd datafile
    read_tableau(&tab, argv[1]);
  }
  print_tableau(&tab,"Initial");
  simplex(&tab);
  return 0;
} 
什么:C中的单纯形 作者:GPL(C)moshahmed/at/gmail。 内容:使用单纯形解决LP问题: {最大化cx:Ax=0}。 输入:{m,n,Mat[m x n]},其中: b=材料[1..m,0]。。列0是b>=0,因此x=0是一个基本可行的解决方案。 c=材料[0,1..n]。。第0行是要最大化的z,注释c在输入中被否定。 A=材料[1..m,1..n]。。限制。 x=[x1..xm]是问题中的命名变量。 松弛变量在[m+1..m+n]列中 用法: 1.问题可以在源代码中的main函数之前指定: c:\>vim mosplex.c Tableau tab={m,n,{//Tableau size,行x列。 {0,-c1,-c2,},//Max:z=c1x1+c2x2, {b1,a11,a12,},//b1>=a11x1+a12x2 {b2,a21,a22,},//b2>=a21-x1+a22-x2 } }; c:\>cl/W4 mosplex.c。。。编译这个文件。 c:\>mosplex.exe problem.txt>solution.txt 2.或从文件中读取问题数据: $cat problem.txt m n 0-c1-c2 b1 a11 a12 b2 a21 a11 $gcc-Wall-g mosplex.c-o mosplex $mosplex problem.txt>solution.txt */ #包括 #包括 #包括 #包括 #包括 #定义M20 #定义n20 静态常数双ε=1.0e-8; int等于(双a,双b){返回fabs(a-b)mat[i][j])) printf(“%6d”,(int)选项卡->材料[i][j]); 其他的 printf(“%6.2lf”,选项卡->材料[i][j]); } printf(“\n”); } nl(70); } /*read_tableau的输入文件示例: 4 5 0 -0.5 -3 -1 -4 40 1 1 1 1 10 -2 -1 1 1 10 0 1 0 -1 */ 无效读取表格(表格*选项卡,常量字符*文件名){ int-err,i,j; 文件*fp; fp=fopen(文件名,“r”); 如果(!fp){ printf(“无法读取%s\n”,文件名);退出(1); } memset(tab,0,sizeof(*tab)); err=fscanf(fp,“%d%d”,&tab->m,&tab->n); 如果(err==0 | | err==EOF){ printf(“无法读取m或n”);退出(1); } 对于(i=0;im;i++){ 对于(j=0;jn;j++){ err=fscanf(fp、%lf、&tab->mat[i][j]); 如果(err==0 | | err==EOF){ printf(“无法读取[%d][%d]\n”,i,j);退出(1); } } } printf(“从文件“%s”读取表格[%d行x%d列]。\n”, tab->m,tab->n,文件名); fclose(fp); } 无效轴(表格*选项卡,整数行,整数列){ int i,j; 双支点; 枢轴=制表符->垫[行][列]; 断言(pivot>0); 对于(j=0;jn;j++) tab->mat[行][j]/=pivot; 断言(相等(制表符->材料[行][列],1.); 对于(i=0;im;i++){//foreach剩余的行 双乘数=制表符->矩阵[i][col]; 如果(i==行)继续; 对于(j=0;jn;j++){//r[i]=r[i]-z*r[row]; tab->mat[i][j]=乘数*tab->mat[row][j]; } } } //查找pivot_col=mat[0][1..n]中最负的列 int find_pivot_列(表*选项卡){ int j,pivot_col=1; 双最低=制表符->垫[0][pivot_col]; 对于(j=1;jn;j++){ 如果(制表符->材料[0][j]<最低){ 最低=制表符->材料[0][j]; 枢轴_col=j; } } printf(“第[0]行中最负的列是列%d=%g.\n”,pivot\u col,最低); 如果(最低值>=0){ return-1;//第[0]行中的所有正列,这是最佳的。 } 返回轴坐标; } //找到pivot_行,最小正比率=col[0]/col[pivot] int find_pivot_行(表格*选项卡,int pivot_列){ int i,pivot_row=0; 双最小值比=-1; printf(“比率A[行i,0]/A[行i,%d]=[”,轴列); 对于(i=1;im;i++){ 双倍比率=制表符->材料[i][0]/制表符->材料[i][pivot_col]; printf(“%3.2lf”,比率); 如果((比率>0&&比率<最小比率)| |最小比率<0){ 最小比率=比率; 枢轴_行=i; } } printf(“].\n”); 如果(最小比值==-1) return-1;//无界。 printf(“在第%d行中找到轴A[%d,%d],最小正比率=%g。\n”, 枢轴行、枢轴列、最小比率、枢轴行); 返回第一行; } 无效添加松弛变量(表*选项卡){ int i,j; 对于(i=1;im;i++){ 对于(j=1;jm;j++) tab->mat[i][j+tab->n-1]=(i==j); } tab->n+=tab->m-1; } 无效检查(表格*选项卡){ int i; 对于(i=1;im;i++) 断言(tab->mat[i][0]>=0); } //给定一列单位矩阵,找到包含1的行。 //如果列不是来自标识矩阵,则返回-1。 int find_basis_变量(表格*选项卡,int col){ int i,xi=-1; 对于(i=1;im;i++){ if(相等(制表符->材料[i][col],1)){ 如果(xi==-1) xi=i;//找到第一个“1”,保存此行号。 其他的 return-1;//找到第二个“1”,不是一个单位矩阵。 }否则如果(!相等(制表符->材料[i][col],0)){ return-1;//不是标识矩阵列。 } } 返回席; } 无效打印向量(表格*选项卡,字符*消息){ 国际标准期刊席; printf(“%s at”,消息); 对于(j=1;jn;j++){//每列。 席= FungBasiSyValuy(Tab,J); 如果(xi!=-1) printf(“x%d=%3.2lf,”,j,tab->mat[xi][0]); 其他的 printf(“x%d=0,”,j); } printf(“\n”); } 无效单纯形(表*选项卡){ int循环=0; 添加松弛变量(选项卡); 检查_b_阳性(制表符); 打印表格(选项卡,“用松弛变量填充”); while(++循环){ int pivot\u col,pivot\u row; pivot\u col=查找pivot\u列(选项卡); 如果(轴坐标<0){ printf(“找到的最佳值=A[0,0]=%3.2lf(第0行没有负片)。\n”, tab->mat[0][0]); 打印最佳矢量(选项卡“最佳矢量”); 打破 } printf(“输入变量x%d使其成为基本变量,因此pivot\u col=%d。\n”,