⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 (全部指针)单纯型法解线性规划问题(两阶段法).cpp

📁 单纯型法解线性规划问题(两阶段法)指针改写.
💻 CPP
字号:
/*************************************************************************
                    单纯型法解线性规划问题(两阶段法)      
编程环境:VC++6.0     
方程组输入说明:
变量非负,按提示输入相关参数。
*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <conio.h>
#define MAX 257 //n=7
#define STP 100000
int base_elem;
int base_out,base_in;
int stop=1; //迭代记数变量
int status; //iterative迭代返回值:1唯一最优,0无界解,-1无穷多最优解 -2迭代超过限制次数
int step=1; //目前阶段 
double **a,*b,*c,*temp_c,max=0; //方程组相关系数
int num_x; //变量个数 
int num_st; //约束方程数
int num_ar=0; //人工变量个数
int *arti; //人工变量下标
double *sigma;
int *base; //基变量下标
int ma_mi; //1为求最大值,2为求最小值 
void Create(); //建立方程组
void iterative(); //单纯型法迭代
void Output(); //输出结果
void Exchange(double *c,double *temp_c); //交换两阶段价值系数
//########################################################################
void main() {
int i,j,k;
b=new double [MAX];c=new double [MAX];temp_c=new double [MAX];
a=new double *[MAX];
for(i=0;i<MAX;i++) *(a+i)=new double[MAX];
arti=new int[MAX];
base=new int[MAX];
sigma=new double [MAX];
////////////////////////////////////////*/
Create();				//建立方程组
/*///////////////////////////////////////////////////////////////////////////////
cout<<"指定变量个数:";
cout<<num_x; 
cout<<"\n输入函数f=max()系数c1-c"<<num_x<<endl;
for(i=1;i<=num_x/2;i++)  cout<<*(c+i);     
cout<<"\n输入约束方程组个数:";         cout<<num_st;
cout<<"\n输入方程系数矩阵:\n";
for(i=1;i<=num_st;i++) 
for(j=1;j<=num_x/2;j++) cout<<*(*(a+i)+j)<<"	"; 
cout<<"\n输入常数项向量b"<<i<<":"<<endl;
for(i=1;i<=num_st/2;i++) cout<<*(b+i)<<"	";  
////////////////////////////////////////////////////////////////////////////////*/
for(i=1;i<=num_x;i++) {	//保存原价值系数,转换为第一阶段价值系数
  k=0;
  for(j=1;j<=num_ar;j++) if(i==*(arti+j)) k=1;
  if(k==1) *(temp_c+i)=-1;
  else *(temp_c+i)=0;
}
Exchange(c,temp_c); 
step++;
iterative();
if(status==-2) {
  puts("迭代超过限制次数强行终止!\n");
  puts("\n按回车结束");
  getchar();
  exit(0);
}
//Output(); 
if(max!=0) {
  puts("\n\n原问题无可行解。\n");
  puts("\n按回车结束");
  getchar();
  exit(0);
} 
Exchange(c,temp_c);//转换为第二阶段价值系数
for(i=1;i<=num_ar;i++) {//把人工变量列全设为0
  c[arti[i]]=0;
  for(j=1;j<=num_st;j++) *(*(a+j)+*(arti+i))=0;
} 
iterative();
	switch(status) {
	case 1:
	  Output();
	  puts("\n\n原问题有唯一最优解。\n");
	  puts("\n按回车结束");
	  getchar();
	  break;
	case 0:
	  puts("\n\n原问题为无界解。\n");
	  puts("\n按回车结束");
	  getchar();
	  break;
	case -1:
	  Output();
	  puts("\n\n原问题有无穷多最优解。\n");
	  puts("\n按回车结束");
	  getchar();
	  break;
	case -2:
	  puts("迭代超过限制次数强行终止!\n");
	  puts("\n按回车结束");
	  getchar();
	  break;
	}//switch
cout<<endl;getch();
} 
//########################################################################
void Exchange(double *c,double *temp_c) {
int i;double* temp;
temp=new double[MAX];
	for(i=1;i<=num_x;i++) {
	  temp[i]=*(temp_c+i);
	  *(temp_c+i)=*(c+i);
	  *(c+i)=temp[i];
	}
delete[] temp;
} 
//########################################################################
void Create() {//输入方程组系数,每个方程输完后回显确认
int i,j,*re_st,tnum_x,num_addv=0,num_ba=0;
re_st=new int [MAX];
ma_mi=1;//printf("请选择:1、求最大值,2、求最小值:(1/2)");
////////////////////////////////////////////////////////////////////////////////
//输入参数形式:
//f=max(和a[i]);
//s.t. AX<=b
////////////////////////////////////////////////////////////////////////////////
cout<<"指定变量个数:";
cin>>num_x; 
cout<<"输入函数f=max()系数c1-c"<<num_x<<endl;for(i=1;i<=num_x;i++)  cin>>*(c+i);     
cout<<"输入约束方程组个数:";         cin>>num_st;
for(i=1;i<=num_st;i++)re_st[i]=3;//cout<<"请选择:1、==,2、>=,3、<= :(1/2/3)";
cout<<"输入方程系数矩阵:\n";
for(i=1;i<=num_st;i++) 
for(j=1;j<=num_x;j++) cin>>*(*(a+i)+j); 
cout<<"输入常数项向量b"<<i<<":"<<endl;
for(i=1;i<=num_st;i++) cin>>*(b+i);  
cout<<"输入参数完毕!"<<endl;getch();
/////////////////////////////////////////////////////////////////////////////////
tnum_x=num_x;
for(i=1;i<=num_st;i++) {
  switch(re_st[i]) {
  case 1:
  case 3:
   num_x+=1;
   break;
  case 2:
   num_x+=2;
   break;
  }
} 
//化为标准形式
if(ma_mi==2) for(i=1;i<=tnum_x;i++) *(c+i)*=-1; //求最小值时,系数变相反数
for(i=1;i<=num_st;i++) {
  switch(re_st[i]) {
   case 1:
    num_addv++;
    num_ba++;
    num_ar++;
    c[tnum_x+num_addv]=0; 
    base[num_ba]=arti[num_ar]=tnum_x+num_addv;
    for(j=tnum_x+1;j<=num_x;j++) 
     if(j==tnum_x+num_addv) a[i][tnum_x+num_addv]=1;
     else *(*(a+i)+j)=0;
    break;
   case 2:
    num_addv++;
    c[tnum_x+num_addv]=0;
    num_addv++;
    num_ba++;
    num_ar++;
    c[tnum_x+num_addv]=0; 
    base[num_ba]=arti[num_ar]=tnum_x+num_addv;
    for(j=tnum_x+1;j<=num_x;j++) 
     if(j==tnum_x+num_addv-1) a[i][tnum_x+num_addv-1]=-1;
     else if(j==tnum_x+num_addv) a[i][tnum_x+num_addv]=1;
     else *(*(a+i)+j)=0;
    break;
   case 3:
    num_addv++;
    num_ba++;
    c[tnum_x+num_addv]=0;
    base[num_ba]=tnum_x+num_addv;
    for(j=tnum_x+1;j<=num_x;j++) 
     if(j==tnum_x+num_addv) a[i][tnum_x+num_addv]=1;
     else *(*(a+i)+j)=0;
    break;
  }//switch
}//增加松弛变量、剩余变量、人工变量、确定基变量
delete[] re_st;
}
//########################################################################
void iterative() {
int i,j,k,k_a,k_f,l; //k_a,k_f值为0或1,记录当前下标在arti[]或base[]里的搜索结果
double temp;
double *sigma;sigma=new double [MAX];
double value_be; //高斯消元里保存主元素值 
//求检验数sigma
for(i=1;i<=num_x;i++) {
  *(sigma+i)=*(c+i);
  for(j=1;j<=num_st;j++) *(sigma+i)-=*(c+*(base+j))**(*(a+j)+i);
  for(j=1;j<=num_st;j++) if(i==*(base+j)) *(sigma+i)=0;
  switch(step) {
   case 1:
//    cout<<"sigma["<<i%<<"]="<<*(sigma+i)<<"\t";
    break;
   case 2:
    k_a=0;
    for(l=1;l<=num_ar;l++) if(i==*(arti+l)) k_a=1;
//    if(k_a!=1) printf("sigma[%d]=%lg\t",i,*(sigma+i));
    break;
  }
}
//检验检验数sigma是否全小于等于0
k=0;
for(i=1;i<=num_x;i++) {
  if(*(sigma+i)>0) 
  k=1;
}
if(k==0) {
  for(i=1;i<=num_x;i++){//sigma是全小于等于0时,检查是否为无穷多最优解
   k_f=k_a=0;
   for(j=1;j<=num_ar;j++)
   if(i==*(arti+j)) k_a=1;
   if(*(sigma+i)==0&&k_a!=1) {
    for(j=1;j<=num_st;j++) if(i==*(base+j)) k_f=1;
   if(k_f==0) {status=-1;return;}
   }
  }
  status=1; 
  return;
}
for(i=1;i<=num_x;i++) { //检查是否为无界解
  k_f=0;
  if(*(sigma+i)>0) {
   for(j=1;j<=num_st;j++) if(*(*(a+j)+i)>0) k_f=1;
   if(k_f!=1) {status=0;  return;}
  }
} 
//确定换入变量
for(i=1;i<=num_x;i++) { 
  k=0;
  for(j=1;j<=num_st;j++) if(i==*(base+j)) k=1;
  if(k==0&&*(sigma+i)>0) temp=*(sigma+i)-1;
}//temp赋初值
for(i=1;i<=num_x;i++) {
  k=0;
  for(j=1;j<=num_st;j++) if(i==*(base+j)) k=1;
  if(k==0)
   if(*(sigma+i)>temp&&*(sigma+i)>0) {
    base_in=i;
    temp=*(sigma+i);
   }
} 
//确定换出变量
for(i=1;i<=num_st;i++) 
  if((*(*(a+i)+base_in))>0) {
   temp=*(b+i)/(*(*(a+i)+base_in))+1;
   break;
  }//temp赋初值
for(i=1;i<=num_st;i++) {
  if(*(b+i)/(*(*(a+i)+base_in))<=temp&&(*(*(a+i)+base_in))>0) {
   for(j=1;j<=num_ar;j++)
    if(*(base+i)==*(arti+j)) { 
     base_out=*(base+i);
     base_elem=i;
     temp=*(b+i)/(*(*(a+i)+base_in));
     break;
    }
  }//人工变量优先换出
  if(*(b+i)/(*(*(a+i)+base_in))<temp&&(*(*(a+i)+base_in))>0) {
   base_out=*(base+i);
   base_elem=i;
   temp=*(b+i)/(*(*(a+i)+base_in));
  }
} 
//printf(" 基变量:");
//for(i=1;i<=num_st;i++) printf("x[%d] ",*(base+i));
//printf("换入变量:x[%d] 换出变量:x[%d]",base_in,base_out);
//基变量变换,进行新方程初始化后迭代
for(i=1;i<=num_st;i++) {
  if(*(base+i)==base_out) *(base+i)=base_in;
}
//初始化主元素行系数
value_be=a[base_elem][base_in];
b[base_elem]/=value_be;
for(i=1;i<=num_x;i++) *(*(a+base_elem)+i)/=value_be; 
for(i=1;i<=num_st;i++) {
  if(i!=base_elem) {
   *(b+i)-=b[base_elem]*(*(*(a+i)+base_in));
   value_be=(*(*(a+i)+base_in));
   for(j=1;j<=num_x;j++) *(*(a+i)+j)-=*(*(a+base_elem)+j)*value_be;
  }
}
stop++;cout<<"stop="<<stop<<endl;
if(stop>STP) {status=-2; return;}
iterative();
} 
//########################################################################
void Output() {
int i,j;
double *X;X=new double[MAX];
cout<<endl<<"结果如下:"<<endl;
cout<<"\nX=(";
for(i=1;i<=num_x;i++) {
  for(j=1;j<=num_st;j++)
  if(i==*(base+j)) {*(X+i)=*(b+j);break;}
  else *(X+i)=0;
} 
for(i=1;i<=num_x/2;i++) cout<<*(X+i)<<" ";
cout<<")";
for(i=1;i<=num_x;i++) max+=*(c+i)**(X+i);
if(ma_mi==1) cout<<"\nMax f="<<max<<endl;
else cout<<"Min f="<<-max<<endl;
delete[]X; 
}
//########################################################################

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -