|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?我要加入
x
<P>/*************************************************************************<BR> 单纯型法解线性规划问题(两阶段法) <BR><BR>编程环境:VC++6.0 <BR>方程组输入说明:<BR>变量非负,按提示输入相关参数。<BR>*************************************************************************/<BR>#include <stdio.h><BR>#include <stdlib.h><BR>#define MAX 100<BR>#define STP 100
<br>int stop=1; //迭代记数变量<BR>int status; //iterative迭代返回值:1唯一最优,0无界解,-1无穷多最优解 -2迭代超过限制次数<BR>int step=1; //目前阶段
<p>double a[MAX][MAX],b[MAX],c[MAX],temp_c[MAX],max=0; //方程组相关系数<BR>int num_x; //变量个数 <BR>int num_st; //约束方程数<BR>int num_ar=0; //人工变量个数<BR>int arti[MAX]; //人工变量下标<BR>int base[MAX]; //基变量下标<BR>int ma_mi; //1为求最大值,2为求最小值
<p>void create(); //建立方程组<BR>void iterative(); //单纯型法迭代<BR>void output(); //输出结果<BR>void banner(); //打印程序标题<BR>void exchange(); //交换两阶段价值系数<BR>void show(); //输出方程组
<p>void main() {<BR>int i,j,k;<BR>banner();<BR>create();<BR>//保存原价值系数,转换为第一阶段价值系数<BR>for(i=1;i<=num_x;i++) {<BR> k=0;<BR> for(j=1;j<=num_ar;j++) if(i==arti[j]) k=1;<BR> if(k==1) temp_c=-1;<BR> else temp_c=0;<BR>}<BR>exchange(c,temp_c);
<p>printf("\n\n第一阶段问题为:\n\n");<BR>show();<BR>step++;<BR>printf("\n\n按回车开始第一阶段迭代");<BR>getchar(); <BR>getchar();<BR>iterative();<BR>if(status==-2) {<BR> puts("迭代超过限制次数强行终止!\n");<BR> puts("\n按回车结束");<BR> getchar();<BR> exit(0);<BR>}<BR>output();
<p>if(max!=0) {<BR> puts("\n\n原问题无可行解。\n");<BR> puts("\n按回车结束");<BR> getchar();<BR> exit(0);<BR>}
<p>//转换为第二阶段价值系数<BR>exchange(c,temp_c);<BR>//把人工变量列全设为0<BR>for(i=1;i<=num_ar;i++) {<BR> c[arti]=0;<BR> for(j=1;j<=num_st;j++) a[j][arti]=0;<BR>}
<p>puts("\n\n第二阶段问题为:\n\n");<BR>show();<BR>puts("\n\n按回车开始第二阶段迭代");<BR>getchar(); <BR>iterative();<BR>switch(status) {<BR>case 1:<BR> output();<BR> puts("\n\n原问题有唯一最优解。\n");<BR> puts("\n按回车结束");<BR> getchar();<BR> exit(0);<BR>case 0:<BR> puts("\n\n原问题为无界解。\n");<BR> puts("\n按回车结束");<BR> getchar();<BR> exit(0);<BR>case -1:<BR> output();<BR> puts("\n\n原问题有无穷多最优解。\n");<BR> puts("\n按回车结束");<BR> getchar();<BR> exit(0);<BR>case -2:<BR> puts("迭代超过限制次数强行终止!\n");<BR> puts("\n按回车结束");<BR> getchar();<BR> exit(0);<BR>}//switch<BR>}
<p>void banner() {<BR>printf("\t\t****************************************\n");<BR>printf("\t\t 单纯型法解线性规划问题\n");<BR>printf("\t\t 作者:Thunder\n");<BR>printf("\t\t****************************************\n");<BR>printf("\n");<BR>}
<p>void show() {<BR>//对方程组以自然的格式输出,系数为零的x不显示<BR>//为1的不显示系数1,-1系数只显示负号<BR>int i,j,k;<BR>switch(step) {<BR>case 1:<BR> printf("min z= ");<BR> printf("x[%d]",arti[1]);<BR> for(i=2;i<=num_ar;i++) printf(" + x[%d]",arti);<BR> break;<BR>case 2:<BR>printf("max z= ");<BR>printf("%lg x[%d]",c[1],1);<BR>for(i=2;i<=num_x;i++) {<BR> if(c==1) printf(" + x[%d]",i);<BR> else if(c==-1) printf(" - x[%d]",i);<BR> else if(c>=0) printf(" +%lg x[%d]",c,i);<BR> else printf(" %lg x[%d]",c,i);<BR>}<BR>break;<BR>}
<p>printf("\nst:\n");<BR>for(i=1;i<=num_st;i++) {<BR> k=0;<BR> for(j=1;j<=num_x;j++) { <BR> if(a[j]!=0) {<BR> if(a[j]==1&&k!=0) printf(" + x[%d]",j);<BR> else if(a[j]==1&&k==0) printf(" x[%d]",j);<BR> else if(a[j]==-1) printf(" - x[%d]",j);<BR> else if(a[j]>=0&&k!=0) printf(" +%lg x[%d]",a[j],j);<BR> else if(a[j]>=0&&k==0) printf(" %lg x[%d]",a[j],j);<BR> else printf(" %lg x[%d]",a[j],j);<BR> k=1;<BR> }<BR> }<BR> printf(" == %lg\n",b); <BR>}<BR>printf(" x[1]~x[%d]>=0",num_x);<BR>}
<p>void exchange() {<BR>int i;<BR>double temp[MAX];<BR>for(i=1;i<=num_x;i++) {<BR> temp=temp_c;<BR> temp_c=c;<BR> c=temp;<BR>}<BR>}
<p>void create() {<BR>//输入方程组系数,每个方程输完后回显确认<BR>int i,j,k,re_st[MAX],tnum_x,num_addv=0,num_ba=0;<BR>char confirm;<BR><BR>while(1) {<BR> printf("请选择:1、求最大值,2、求最小值:(1/2)");<BR> scanf("%d",&ma_mi);<BR> if(ma_mi!=1&&ma_mi!=2) printf("输入错误,重新选择。");<BR> else break;<BR>}<BR><BR>while(1) {<BR> printf("指定变量个数:");<BR> scanf("%d",&num_x);<BR> printf("输入价值系数c1-c%d:\n",num_x);<BR> for(i=1;i<=num_x;i++) { <BR> printf("c%d=",i);<BR> scanf("%lf",&c);<BR> }<BR> if(ma_mi==1) printf("max z= ");<BR> else printf("min z= ");<BR> printf("%lg x[%d]",c[1],1);<BR> for(i=2;i<=num_x;i++) {<BR> if(c>=0) printf(" +%lg x[%d]",c,i);<BR> else printf(" %lg x[%d]",c,i);<BR> }<BR>printf("\n正确吗?:(y/n)");<BR>getchar();<BR>confirm=getchar();<BR>if (confirm=='y') break;<BR>else if(confirm=='n') continue;<BR>}
<p>printf("输入约束方程组个数:");<BR>scanf("%d",&num_st);<BR>for(i=1;i<=num_st;i++) {<BR> printf("st.%d:\n",i);<BR> while(1) {<BR> printf("请选择:1、==,2、>=,3、<= :(1/2/3)");<BR> scanf("%d",&re_st);<BR> if(re_st!=1&&re_st!=2&&re_st!=3) printf("输入错误,请重新选择。");<BR> else break;<BR> }<BR> printf("输入技术系数:\n");<BR> for(j=1;j<=num_x;j++) { <BR> printf("a%d=",j);<BR> scanf("%lf",&a[j]);<BR> }<BR> printf("输入资源拥有量:\nb%d=",i);<BR> scanf("%lf",&b);<BR> <BR> printf("st.%i:\n",i);<BR> printf("%lg x[%d]",a[1],1);<BR> for(j=2;j<=num_x;j++) {<BR> if(a[j]>=0) printf(" +%lg x[%d]",a[j],j);<BR> else printf(" %lg x[%d]",a[j],j);<BR> }<BR> switch(re_st) {<BR> case 1: printf(" == %lg",b); break;<BR> case 2: printf(" >= %lg",b); break;<BR> case 3: printf(" <= %lg",b); break;<BR> }
<p> while(1) {<BR> printf("\n正确吗?(y/n)");<BR> getchar();<BR> confirm=getchar();<BR> if (confirm=='y') break;<BR> else if(confirm=='n') {i-=1; break;}<BR> }<BR>}
<p>//显示输入的方程组<BR>printf("\n原问题为:\n\n");<BR>if(ma_mi==1) printf("max z= ");<BR>else printf("min z= ");<BR>printf("%lg x[%d]",c[1],1);<BR>for(i=2;i<=num_x;i++) {<BR> if(c==1) printf(" + x[%d]",i);<BR> else if(c==-1) printf(" - x[%d]",i);<BR> else if(c>=0) printf(" +%lg x[%d]",c,i);<BR> else printf(" %lg x[%d]",c,i);<BR>}
<p>printf("\nst:\n");<BR>for(i=1;i<=num_st;i++) { <BR> k=0;<BR> for(j=1;j<=num_x;j++) {<BR> if(a[j]!=0) {<BR> if(a[j]==1&&k!=0) printf(" + x[%d]",j);<BR> else if(a[j]==1&&k==0) printf(" x[%d]",j);<BR> else if(a[j]==-1) printf(" - x[%d]",j);<BR> else if(a[j]>=0&&k!=0) printf(" +%lg x[%d]",a[j],j);<BR> else if(a[j]>=0&&k==0) printf(" %lg x[%d]",a[j],j);<BR> else printf(" %lg x[%d]",a[j],j);<BR> k=1;<BR> }<BR> }<BR> switch(re_st) {<BR> case 1: <BR> printf(" == %lg\n",b); <BR> break;<BR> case 2: <BR> printf(" >= %lg\n",b); <BR> break;<BR> case 3: <BR> printf(" <= %lg\n",b); <BR> break;<BR> }<BR>}<BR>printf(" x[1]~x[%d]>=0\n",num_x);
<p>tnum_x=num_x;<BR>for(i=1;i<=num_st;i++) {<BR> switch(re_st) {<BR> case 1:<BR> case 3:<BR> num_x+=1;<BR> break;<BR> case 2:<BR> num_x+=2;<BR> break;<BR> }<BR>}
<p>//化为标准形式<BR>if(ma_mi==2) for(i=1;i<=tnum_x;i++) c*=-1; //求最小值时,系数变相反数<BR>for(i=1;i<=num_st;i++) {<BR> switch(re_st) {<BR> case 1:<BR> num_addv++;<BR> num_ba++;<BR> num_ar++;<BR> c[tnum_x+num_addv]=0; <BR> base[num_ba]=arti[num_ar]=tnum_x+num_addv;<BR> for(j=tnum_x+1;j<=num_x;j++) <BR> if(j==tnum_x+num_addv) a[tnum_x+num_addv]=1;<BR> else a[j]=0;<BR> break;<BR> case 2:<BR> num_addv++;<BR> c[tnum_x+num_addv]=0;<BR> num_addv++;<BR> num_ba++;<BR> num_ar++;<BR> c[tnum_x+num_addv]=0; <BR> base[num_ba]=arti[num_ar]=tnum_x+num_addv;<BR> for(j=tnum_x+1;j<=num_x;j++) <BR> if(j==tnum_x+num_addv-1) a[tnum_x+num_addv-1]=-1;<BR> else if(j==tnum_x+num_addv) a[tnum_x+num_addv]=1;<BR> else a[j]=0;<BR> break;<BR> case 3:<BR> num_addv++;<BR> num_ba++;<BR> c[tnum_x+num_addv]=0;<BR> base[num_ba]=tnum_x+num_addv;<BR> for(j=tnum_x+1;j<=num_x;j++) <BR> if(j==tnum_x+num_addv) a[tnum_x+num_addv]=1;<BR> else a[j]=0;<BR> break;<BR> }//switch<BR>}//增加松弛变量、剩余变量、人工变量、确定基变量
<p>//显示标准化后的方程组<BR>printf("\n化为标准形式后:\n\n");<BR>if(ma_mi==1) printf("max z= ");<BR>else printf("max z'= ");<BR>printf("%lg x[%d]",c[1],1);<BR>for(i=2;i<=num_x;i++) { <BR> k=0;<BR> for(j=1;j<=num_ar;j++)<BR> if(i==arti[j]) k=1;<BR> if(k==1) printf(" -M x[%d]",i);<BR> else if(c==1) printf(" + x[%d]",i);<BR> else if(c==-1) printf(" - x[%d]",i);<BR> else if(c>=0) printf(" +%lg x[%d]",c,i);<BR> else printf(" %lg x[%d]",c,i);<BR>}
<p>printf("\nst:\n");<BR>for(i=1;i<=num_st;i++) {<BR> k=0;<BR> for(j=1;j<=num_x;j++) {<BR> if(a[j]!=0) {<BR> if(a[j]==1&&k!=0) printf(" + x[%d]",j);<BR> else if(a[j]==1&&k==0) printf(" x[%d]",j);<BR> else if(a[j]==-1) printf(" - x[%d]",j);<BR> else if(a[j]>=0&&k!=0) printf(" +%lg x[%d]",a[j],j);<BR> else if(a[j]>=0&&k==0) printf(" %lg x[%d]",a[j],j);<BR> else printf(" %lg x[%d]",a[j],j);<BR> k=1;<BR> }<BR> }<BR> printf(" == %lg\n",b); <BR>}<BR>printf(" x[1]~x[%d]>=0",num_x);<BR>}
<p>void iterative() {<BR>int i,j,k,k_a,k_f,l; //k_a,k_f值为0或1,记录当前下标在arti[]或base[]里的搜索结果<BR>int base_elem;<BR>int base_out,base_in;<BR>double sigma[MAX],temp;<BR>double value_be; //高斯消元里保存主元素值
<p>printf("\n\n第%d次迭代:\n\n",stop); <BR>for(i=1;i<=num_st;i++) {<BR> printf("c%d=%lg\t",base,c[base]);<BR> printf("b%d=%lg\t",i,b);
<p> switch(step) {<BR> case 1:<BR> for(j=1;j<=num_x;j++)<BR> {<BR> printf("a[%d][%d]=%lg\t",i,j,a[j]);<BR> }<BR> printf("\n");<BR> break;<BR> case 2:<BR> for(j=1;j<=num_x;j++) {<BR> k_a=0;<BR> for(l=1;l<=num_ar;l++) if(j==arti[l])k_a=1;<BR> if(k_a!=1) printf("a[%d][%d]=%lg\t",i,j,a[j]);<BR> }<BR> printf("\n");<BR> break;<BR> }<BR>}<BR>//求检验数sigma<BR>for(i=1;i<=num_x;i++) {<BR> sigma=c;<BR> for(j=1;j<=num_st;j++) sigma-=c[base[j]]*a[j];<BR> for(j=1;j<=num_st;j++) if(i==base[j]) sigma=0;<BR> switch(step) {<BR> case 1:<BR> printf("sigma[%d]=%lg\t",i,sigma);<BR> break;<BR> case 2:<BR> k_a=0;<BR> for(l=1;l<=num_ar;l++) if(i==arti[l]) k_a=1;<BR> if(k_a!=1) printf("sigma[%d]=%lg\t",i,sigma);<BR> break;<BR> }<BR>}<BR>putchar('\n');<BR>//检验检验数sigma是否全小于等于0<BR>k=0;<BR>for(i=1;i<=num_x;i++) {<BR> if(sigma>0) <BR> k=1;<BR>}<BR>if(k==0) {<BR> //sigma是全小于等于0时,检查是否为无穷多最优解<BR> for(i=1;i<=num_x;i++) { <BR> k_f=k_a=0;<BR> for(j=1;j<=num_ar;j++)<BR> if(i==arti[j]) k_a=1;<BR> if(sigma==0&&k_a!=1) {<BR> for(j=1;j<=num_st;j++) if(i==base[j]) k_f=1;<BR> if(k_f==0) {status=-1; return;}<BR> }<BR> }<BR> status=1; <BR> return;<BR>}<BR>//检查是否为无界解<BR>for(i=1;i<=num_x;i++) { <BR> k_f=0;<BR> if(sigma>0) {<BR> for(j=1;j<=num_st;j++) if(a[j]>0) k_f=1;<BR> if(k_f!=1) {status=0; return;}<BR> }<BR>}
<p>//确定换入变量<BR>for(i=1;i<=num_x;i++) { <BR> k=0;<BR> for(j=1;j<=num_st;j++) if(i==base[j]) k=1;<BR> if(k==0&&sigma>0) temp=sigma-1;<BR>}//temp赋初值<BR>for(i=1;i<=num_x;i++) {<BR> k=0;<BR> for(j=1;j<=num_st;j++) if(i==base[j]) k=1;<BR> if(k==0)<BR> if(sigma>temp&&sigma>0) {<BR> base_in=i;<BR> temp=sigma;<BR> }<BR>}
<p>//确定换出变量<BR>for(i=1;i<=num_st;i++) <BR> if(a[base_in]>0) {<BR> temp=b/a[base_in]+1;<BR> break;<BR> }//temp赋初值<BR>for(i=1;i<=num_st;i++) {<BR> if(b/a[base_in]<=temp&&a[base_in]>0) {<BR> for(j=1;j<=num_ar;j++)<BR> if(base==arti[j]) { <BR> base_out=base;<BR> base_elem=i;<BR> temp=b/a[base_in];<BR> break;<BR> }<BR> }//人工变量优先换出<BR> if(b/a[base_in]<temp&&a[base_in]>0) {<BR> base_out=base;<BR> base_elem=i;<BR> temp=b/a[base_in];<BR> }<BR>}
<p>printf(" 基变量:");<BR>for(i=1;i<=num_st;i++) printf("x[%d] ",base);<BR>printf("换入变量:x[%d] 换出变量:x[%d]",base_in,base_out);<BR>//基变量变换,进行新方程初始化后迭代<BR>for(i=1;i<=num_st;i++) {<BR> if(base==base_out) base=base_in;<BR>}<BR>//初始化主元素行系数<BR>value_be=a[base_elem][base_in];<BR>b[base_elem]/=value_be;<BR>for(i=1;i<=num_x;i++) a[base_elem]/=value_be;
<p>for(i=1;i<=num_st;i++) {<BR> if(i!=base_elem) {<BR> b-=b[base_elem]*a[base_in];<BR> value_be=a[base_in];<BR> for(j=1;j<=num_x;j++) a[j]-=a[base_elem][j]*value_be;<BR> }<BR>}<BR>stop++;<BR>if(stop>STP) {status=-2; return;}<BR>iterative();<BR>}
<p>void output() {<BR>int i,j;<BR>double X[MAX];<BR>printf("\n结果如下:\n");<BR>printf("\nX=(");<BR>for(i=1;i<=num_x;i++) {<BR> for(j=1;j<=num_st;j++)<BR> if(i==base[j]) {X=b[j];break;}<BR> else X=0;<BR> printf("%lg ",X);<BR>}<BR>printf(")");<BR>for(i=1;i<=num_x;i++) max+=c*X;<BR>if(ma_mi==1) printf("\nMax z= %lf\n",max);<BR>else printf("\nMin z= %lf\n",-max);<BR>} |
|