我写了一个管理运筹学中的单纯形算法程序,大M法计算,数据使用了double型,但在迭代数次后显示出现1.#INF、-1.#INF这样的结果,而不是正确的小数类型,不知道什么原因。
以下是我的完整代码:
#include<iostream.h>
#include<string.h>
#include<iomanip.h>
#include<math.h>
#define LONG 251
#define MM 10000
/************变量声明***************/
int i=0,
j=0,
m=0, //约束条件个数
n=0, //变量个数
ziyou=0, //松弛变量个数
man=0, //人工变量个数
s=0, //主元列号
r=0, //行号
cnt=0, //记录迭代次数
k=0, //记录temp_a的行数
opt[LONG+1] //操作符 0、-1、1 表示等于、小于、大于
={0,-1,1,0};
char ziyoujie[50]="最优解:", //用于显示最优解和最优值
leixing[4]="Min"; //目标函数类型
double z, //目标函数值
yi[LONG+1]={0},
xianshi1[LONG+1][LONG+1]={0}, //用于显示结果
temp_a[LONG+1][LONG+1]={0}, //临时变量,辅助a的调整
temp_b[LONG+1]={0}, //临时变量,辅助b的调整
a[LONG+1][LONG+1] //系数矩阵
={{0},{0,1,-2,1},{0,-4,1,2},{0,-2,0,1}},
b[LONG+1] //不等式值
={0,11,3,1},
c[LONG+1] //原始目标函数
={0,-3,1,1},
temp=0,
d[LONG+1]={0}, //检验数
juece[LONG+1]; //决策变量
bool t=false; //辅助判断变量是否为基变量
/*-------------------------------函数声明--------------------------------*/
bool requirem(void){
int i=0;
for(i=1;i<=m;i++)
if(opt[i]>-1)
return true;
return false;
}
bool panduan_d(void){
/***********对应原理第四步,判断目标函数有无负值**************/
for(j=1;j<=n+ziyou+man;j++)
if(d[j]<0)
return false;
return true;
}
int find_s(void){
/***********找主元列。从行向量中选取最小的数,返回其位置**************/
int l=1;
temp=d[1];
for(i=2;i<=sizeof(d)/sizeof(double);i++){
if(d[i] < temp){
temp=d[i];
l=i;
}
}
return l;
}
bool panduan_r(int s){
/***********判断的r列的元素有无正值**************/
for(i=1;i<=m;i++)
if(a[i][s] > 0)
return true;
return false;
}
int find_r(int s){
/***********找主元行。从主元列中选取比之最小的行,返回其位置**************/
for(i=1;i<=m;i++)
if(a[i][s]>0){ //首先寻求一个正的元素
k=i;
break;
}
temp=b[k]/a[k][s];
for(i=k+1;i<=m;i++)
if(a[i][s]>=0 && b[i]/a[i][s]-temp < 0.00000001){
temp=b[i]/a[i][s];
return i; //找比值最小的行
}
return k;
}
bool nbv(void){
for(i=1;i<=m;i++)
if(juece[i] > n+ziyou)
return true;
return false;
}
void output(void){
cnt==0?cout<<"初始单纯形表为:\n":cout<<"第"<<cnt<<"次迭代,单纯形表为:\n";
cout<<'\t'<<"基变量";
cout<<'\n';
for(i=1;i<=m;i++){
cout<<'\t'<<'X'<<juece[i]<<" ";
for(j=1;j<=n+ziyou+man;j++){
cout<<'\t'<<a[i][j]<<" ";
}
cout<<'\t'<<b[i]<<'\n';
}
cout<<"检验数为:\t";
for(j=1;j<=n+ziyou+man;j++)
cout<<d[j]<<'\t';
cout<<'\n'<<setw(8)<<"Z="<<setprecision(6)<<z;
cout<<'\n';
}
void diedai(void){
/************对应原理第六步,完成迭代变换***********/
//double temp; //保存主元素的值
//double yi[LONG+1]={0}; //临时变量,用于存放每次迭代时每一行的比例因子
juece[r]=s;
temp=a[r][s];
for(j=1;j<=n+ziyou+man;j++)
a[r][j]=a[r][j]/temp;
b[r]=b[r]/temp; //变换主元素行
for(i=1;i<=m;i++){
yi[i]=a[i][s];
if(i!=r){ //变换主行以外的所有行
for(j=1;j<=n+ziyou+man;j++)
a[i][j]=a[i][j]-a[r][j]*yi[i]; //系数据阵的变换
b[i]=b[i]-b[r]*yi[i]; //检验数的变换
}
}
yi[m+1]=d[s]; //借用yi的第m+1行存放主元列所对应的目标函数系数
for(j=1;j<=n+ziyou+man;j++)
d[j]-=a[r][j]*yi[m+1]; //变换目标函数系数
z=z-yi[m+1]*b[r]; //更新目标函数值
for(i=1;i<=m;i++){
if(i==r)
a[i][s]=1;
else
a[i][s]=0; //变换主元素列
}
cnt++;
output();
}
void jisuan_d_z(void){
/******在目标函数中,加入人工变量和大M*******/
if(leixing=="Max")
for(j=n+ziyou+1;j<=n+ziyou+man;j++)
d[j]=-MM; //求最大化问题时人工变量系数取一个非常大的负数
else
for(j=n+ziyou+1;j<=n+ziyou+man;j++)
d[j]=MM; //求最大化问题时人工变量系数取一个非常大的正数
/******对应原理的第二步和第三步*******/
if(!strcmp(leixing,"Min"))
for(j=1;j<=n+ziyou+man;j++)
d[j]=-d[j]; //将最小化问题,转化为最大化问题
for(j=1;j<=n+ziyou+man;j++)
d[j]=-d[j]; //对于最大化问题,检验数为目标函数系数的相反数
z=0;
for(i=1;i<=m;i++){
temp=d[(int)juece[i]]; //临时变量存取比例因子
for(j=1;j<=n+ziyou+man;j++)
d[j]-=temp*a[i][j]; //求取检验数
z-=b[i]*temp; //求目标函数初始值
}
}
void main(){
/*--------------------初始化变量---------------------*/
for(i=1;i<=m;i++) //使右边非负
if(b[i]<0){
opt[i]=-opt[i];
for(j=0;j<=n;j++)
a[i][j]=-a[i][j];
}
/*---------------------变量赋值-----------------------*/
m=3;
n=3;
/*-------------------显示原始目标函数及约束条件----------------------*/
cout<<setw(10)<<"目标函数为:"<<leixing<<" Z=";
for(j=1;j<=n;j++){
c[j]>=0?cout<<"+"<<c[j]<<'x'<<j:cout<<c[j]<<'x'<<j;
}
cout<<'\n';
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
cout<<setw(4)<<a[i][j]<<" ";
}
cout<<setw(4)<<b[i]<<'\n';
}
//c[n+1]==1?cout<<">=":c[n+1]==0?cout<<"=":cout<<"<=";
cout<<'\n';
/*---------------------运算过程-----------------------*/
for(j=1;j<=n;j++)
d[j]=c[j];
if(requirem()){
cout<<"需要加入人工变量和大M\n\n";
}else{
cout<<"不需要加入大M\n\n";
}
/*--------------------对应原理的第一步,约束变换。加入松弛变量和人工变量,构造
不带目标函数的初始表格,并调整使基变量(juece)的后man行为人工变量---------------------*/
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
temp_a[i][j]=a[i][j]; //将系数矩阵付给临时变量
/******对于操作符是"<"的处理*******/
for(i=1;i<m;i++)
if(opt[i]==-1){
k++; //已变换的行数的累加
ziyou++; //松弛变量个数累加
for(j=1;j<=n;j++)
temp_a[i][j]=a[i][j]; //交换系数矩阵行
temp_a[k][n+ziyou]=1; //添加松弛变量系数
juece[k]=(n+ziyou); //记录决策变量
temp_b[k]=b[i]; //交换不等式常数项
}
/******对于操作符是">"的初步处理*******/
for(i=1;i<=m;i++)
if(opt[i]==1){
opt[i]=0; //将大于号转化为等于号
ziyou++;
temp_a[i][n+ziyou] = -1;
}
/******对于操作符是等于号,以及由大于号转换而来的情况的处理*******/
for(i=1;i<=m;i++)
if(opt[i]==0){
k++;
man++;
for(j=1;j<=n;j++)
temp_a[k][j]=a[i][j];
temp_a[k][n+ziyou+man]=1;
temp_b[k]=b[i];
juece[k]=(n+ziyou+man);
}
for(i=1;i<=m;i++)
for(j=1;j<=n+ziyou+man;j++)
a[i][j]=temp_a[i][j]; //将调整后的系数矩阵赋给a
for(i=1;i<=m;i++)
b[i]=temp_b[i]; //将调整后的不等式常数项付给b
jisuan_d_z();
//--------------显示初始单纯形表格------------------------------------
output();
//-------------------继续运算------------------------------------------
/******对目标函数系数全为非负值的处理*******/
loop:if(panduan_d()){
if(nbv()){
cout<<"原线性规划没有可行解!\n";
}else{
output();
cout<<'\n'<<ziyoujie<<'\n';
for(i=1;i<=n;i++){
t=false;
for(j=1;j<=m;j++)
if(juece[j]==i){
//strcat(ziyoujie,strcat("\nx",strcat((char*)&i,strcat("=",(char*)&b[j]))));
cout<<"x"<<i<<"="<<b[j]<<"\n";
t=true;
}
if(!t)
//strcat(ziyoujie,strcat(x,str(char*)&i));
cout<<"x"<<i<<"=0\n";
}
if(strcmp(leixing,"Min"))
z=-z;
cout<<"最优值为:Z="<<z<<'\n';
}
/******第一阶段的人工目标函数系数不全为正值的处理*******/
}else{ //存在负值,继续迭代
s=find_s();
if(panduan_r(s)){
r=find_r(s);
diedai();
goto loop;
}else{
output();
cout<<'\n'<<"原线性规划问题具有无界解。";
}
}
}