frogfish 发表于 2005-11-16 15:31

单纯型法解线性规划问题(两阶段法)

<P>/*************************************************************************<BR>                  单纯型法解线性规划问题(两阶段法)      <BR><BR>编程环境:VC++6.0   <BR>方程组输入说明:<BR>变量非负,按提示输入相关参数。<BR>*************************************************************************/<BR>#include &lt;stdio.h&gt;<BR>#include &lt;stdlib.h&gt;<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,b,c,temp_c,max=0; //方程组相关系数<BR>int num_x; //变量个数 <BR>int num_st; //约束方程数<BR>int num_ar=0; //人工变量个数<BR>int arti; //人工变量下标<BR>int base; //基变量下标<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&lt;=num_x;i++) {<BR>k=0;<BR>for(j=1;j&lt;=num_ar;j++) if(i==arti) 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&lt;=num_ar;i++) {<BR>c]=0;<BR>for(j=1;j&lt;=num_st;j++) a]=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);<BR>for(i=2;i&lt;=num_ar;i++) printf(" + x[%d]",arti);<BR>break;<BR>case 2:<BR>printf("max z= ");<BR>printf("%lg x[%d]",c,1);<BR>for(i=2;i&lt;=num_x;i++) {<BR>if(c==1) printf(" + x[%d]",i);<BR>else if(c==-1) printf(" - x[%d]",i);<BR>else if(c&gt;=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&lt;=num_st;i++) {<BR>k=0;<BR>for(j=1;j&lt;=num_x;j++) { <BR>   if(a!=0) {<BR>    if(a==1&amp;&amp;k!=0) printf(" + x[%d]",j);<BR>    else if(a==1&amp;&amp;k==0) printf("x[%d]",j);<BR>    else if(a==-1) printf(" - x[%d]",j);<BR>    else if(a&gt;=0&amp;&amp;k!=0) printf(" +%lg x[%d]",a,j);<BR>    else if(a&gt;=0&amp;&amp;k==0) printf(" %lg x[%d]",a,j);<BR>    else printf(" %lg x[%d]",a,j);<BR>    k=1;<BR>   }<BR>}<BR>printf(" == %lg\n",b); <BR>}<BR>printf(" x~x[%d]&gt;=0",num_x);<BR>}
<p>void exchange() {<BR>int i;<BR>double temp;<BR>for(i=1;i&lt;=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,tnum_x,num_addv=0,num_ba=0;<BR>char confirm;<BR><BR>while(1) {<BR>printf("请选择:1、求最大值,2、求最小值:(1/2)");<BR>scanf("%d",&amp;ma_mi);<BR>if(ma_mi!=1&amp;&amp;ma_mi!=2) printf("输入错误,重新选择。");<BR>else break;<BR>}<BR><BR>while(1) {<BR>printf("指定变量个数:");<BR>scanf("%d",&amp;num_x);<BR>printf("输入价值系数c1-c%d:\n",num_x);<BR>for(i=1;i&lt;=num_x;i++) {   <BR>   printf("c%d=",i);<BR>   scanf("%lf",&amp;c);<BR>}<BR>if(ma_mi==1) printf("max z= ");<BR>else printf("min z= ");<BR>printf("%lg x[%d]",c,1);<BR>for(i=2;i&lt;=num_x;i++) {<BR>   if(c&gt;=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",&amp;num_st);<BR>for(i=1;i&lt;=num_st;i++) {<BR>printf("st.%d:\n",i);<BR>while(1) {<BR>   printf("请选择:1、==,2、&gt;=,3、&lt;= :(1/2/3)");<BR>   scanf("%d",&amp;re_st);<BR>   if(re_st!=1&amp;&amp;re_st!=2&amp;&amp;re_st!=3) printf("输入错误,请重新选择。");<BR>   else break;<BR>}<BR>printf("输入技术系数:\n");<BR>for(j=1;j&lt;=num_x;j++) {<BR>   printf("a%d=",j);<BR>   scanf("%lf",&amp;a);<BR>}<BR>printf("输入资源拥有量:\nb%d=",i);<BR>scanf("%lf",&amp;b);<BR><BR>printf("st.%i:\n",i);<BR>printf("%lg x[%d]",a,1);<BR>for(j=2;j&lt;=num_x;j++) {<BR>   if(a&gt;=0) printf(" +%lg x[%d]",a,j);<BR>   else printf(" %lg x[%d]",a,j);<BR>}<BR>switch(re_st) {<BR>   case 1: printf(" == %lg",b); break;<BR>   case 2: printf(" &gt;= %lg",b); break;<BR>   case 3: printf(" &lt;= %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);<BR>for(i=2;i&lt;=num_x;i++) {<BR>if(c==1) printf(" + x[%d]",i);<BR>else if(c==-1) printf(" - x[%d]",i);<BR>else if(c&gt;=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&lt;=num_st;i++) { <BR>k=0;<BR>for(j=1;j&lt;=num_x;j++) {<BR>   if(a!=0) {<BR>    if(a==1&amp;&amp;k!=0) printf(" + x[%d]",j);<BR>    else if(a==1&amp;&amp;k==0) printf("x[%d]",j);<BR>    else if(a==-1) printf(" - x[%d]",j);<BR>    else if(a&gt;=0&amp;&amp;k!=0) printf(" +%lg x[%d]",a,j);<BR>    else if(a&gt;=0&amp;&amp;k==0) printf(" %lg x[%d]",a,j);<BR>    else printf(" %lg x[%d]",a,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(" &gt;= %lg\n",b); <BR>    break;<BR>   case 3: <BR>    printf(" &lt;= %lg\n",b); <BR>    break;<BR>}<BR>}<BR>printf(" x~x[%d]&gt;=0\n",num_x);
<p>tnum_x=num_x;<BR>for(i=1;i&lt;=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&lt;=tnum_x;i++) c*=-1; //求最小值时,系数变相反数<BR>for(i=1;i&lt;=num_st;i++) {<BR>switch(re_st) {<BR>   case 1:<BR>    num_addv++;<BR>    num_ba++;<BR>    num_ar++;<BR>    c=0; <BR>    base=arti=tnum_x+num_addv;<BR>    for(j=tnum_x+1;j&lt;=num_x;j++) <BR>   if(j==tnum_x+num_addv) a=1;<BR>   else a=0;<BR>    break;<BR>   case 2:<BR>    num_addv++;<BR>    c=0;<BR>    num_addv++;<BR>    num_ba++;<BR>    num_ar++;<BR>    c=0; <BR>    base=arti=tnum_x+num_addv;<BR>    for(j=tnum_x+1;j&lt;=num_x;j++) <BR>   if(j==tnum_x+num_addv-1) a=-1;<BR>   else if(j==tnum_x+num_addv) a=1;<BR>   else a=0;<BR>    break;<BR>   case 3:<BR>    num_addv++;<BR>    num_ba++;<BR>    c=0;<BR>    base=tnum_x+num_addv;<BR>    for(j=tnum_x+1;j&lt;=num_x;j++) <BR>   if(j==tnum_x+num_addv) a=1;<BR>   else a=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);<BR>for(i=2;i&lt;=num_x;i++) { <BR>k=0;<BR>for(j=1;j&lt;=num_ar;j++)<BR>if(i==arti) 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&gt;=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&lt;=num_st;i++) {<BR>k=0;<BR>for(j=1;j&lt;=num_x;j++) {<BR>   if(a!=0) {<BR>    if(a==1&amp;&amp;k!=0) printf(" + x[%d]",j);<BR>    else if(a==1&amp;&amp;k==0) printf("x[%d]",j);<BR>    else if(a==-1) printf(" - x[%d]",j);<BR>    else if(a&gt;=0&amp;&amp;k!=0) printf(" +%lg x[%d]",a,j);<BR>    else if(a&gt;=0&amp;&amp;k==0) printf(" %lg x[%d]",a,j);<BR>    else printf(" %lg x[%d]",a,j);<BR>    k=1;<BR>   }<BR>}<BR>printf(" == %lg\n",b); <BR>}<BR>printf(" x~x[%d]&gt;=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,temp;<BR>double value_be; //高斯消元里保存主元素值
<p>printf("\n\n第%d次迭代:\n\n",stop); <BR>for(i=1;i&lt;=num_st;i++) {<BR>printf("c%d=%lg\t",base,c]);<BR>printf("b%d=%lg\t",i,b);
<p>switch(step) {<BR>   case 1:<BR>    for(j=1;j&lt;=num_x;j++)<BR>    {<BR>   printf("a[%d][%d]=%lg\t",i,j,a);<BR>    }<BR>    printf("\n");<BR>    break;<BR>   case 2:<BR>    for(j=1;j&lt;=num_x;j++) {<BR>   k_a=0;<BR>   for(l=1;l&lt;=num_ar;l++) if(j==arti)k_a=1;<BR>   if(k_a!=1) printf("a[%d][%d]=%lg\t",i,j,a);<BR>    }<BR>    printf("\n");<BR>    break;<BR>}<BR>}<BR>//求检验数sigma<BR>for(i=1;i&lt;=num_x;i++) {<BR>sigma=c;<BR>for(j=1;j&lt;=num_st;j++) sigma-=c]*a;<BR>for(j=1;j&lt;=num_st;j++) if(i==base) 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&lt;=num_ar;l++) if(i==arti) 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&lt;=num_x;i++) {<BR>if(sigma&gt;0) <BR>k=1;<BR>}<BR>if(k==0) {<BR>//sigma是全小于等于0时,检查是否为无穷多最优解<BR>for(i=1;i&lt;=num_x;i++) { <BR>   k_f=k_a=0;<BR>   for(j=1;j&lt;=num_ar;j++)<BR>   if(i==arti) k_a=1;<BR>   if(sigma==0&amp;&amp;k_a!=1) {<BR>    for(j=1;j&lt;=num_st;j++) if(i==base) 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&lt;=num_x;i++) { <BR>k_f=0;<BR>if(sigma&gt;0) {<BR>   for(j=1;j&lt;=num_st;j++) if(a&gt;0) k_f=1;<BR>   if(k_f!=1) {status=0; return;}<BR>}<BR>}
<p>//确定换入变量<BR>for(i=1;i&lt;=num_x;i++) { <BR>k=0;<BR>for(j=1;j&lt;=num_st;j++) if(i==base) k=1;<BR>if(k==0&amp;&amp;sigma&gt;0) temp=sigma-1;<BR>}//temp赋初值<BR>for(i=1;i&lt;=num_x;i++) {<BR>k=0;<BR>for(j=1;j&lt;=num_st;j++) if(i==base) k=1;<BR>if(k==0)<BR>   if(sigma&gt;temp&amp;&amp;sigma&gt;0) {<BR>    base_in=i;<BR>    temp=sigma;<BR>   }<BR>}
<p>//确定换出变量<BR>for(i=1;i&lt;=num_st;i++) <BR>if(a&gt;0) {<BR>   temp=b/a+1;<BR>   break;<BR>}//temp赋初值<BR>for(i=1;i&lt;=num_st;i++) {<BR>if(b/a&lt;=temp&amp;&amp;a&gt;0) {<BR>   for(j=1;j&lt;=num_ar;j++)<BR>    if(base==arti) { <BR>   base_out=base;<BR>   base_elem=i;<BR>   temp=b/a;<BR>   break;<BR>    }<BR>}//人工变量优先换出<BR>if(b/a&lt;temp&amp;&amp;a&gt;0) {<BR>   base_out=base;<BR>   base_elem=i;<BR>   temp=b/a;<BR>}<BR>}
<p>printf(" 基变量:");<BR>for(i=1;i&lt;=num_st;i++) printf("x[%d] ",base);<BR>printf("换入变量:x[%d] 换出变量:x[%d]",base_in,base_out);<BR>//基变量变换,进行新方程初始化后迭代<BR>for(i=1;i&lt;=num_st;i++) {<BR>if(base==base_out) base=base_in;<BR>}<BR>//初始化主元素行系数<BR>value_be=a;<BR>b/=value_be;<BR>for(i=1;i&lt;=num_x;i++) a/=value_be;
<p>for(i=1;i&lt;=num_st;i++) {<BR>if(i!=base_elem) {<BR>   b-=b*a;<BR>   value_be=a;<BR>   for(j=1;j&lt;=num_x;j++) a-=a*value_be;<BR>}<BR>}<BR>stop++;<BR>if(stop&gt;STP) {status=-2; return;}<BR>iterative();<BR>}
<p>void output() {<BR>int i,j;<BR>double X;<BR>printf("\n结果如下:\n");<BR>printf("\nX=(");<BR>for(i=1;i&lt;=num_x;i++) {<BR>for(j=1;j&lt;=num_st;j++)<BR>if(i==base) {X=b;break;}<BR>else X=0;<BR>printf("%lg ",X);<BR>}<BR>printf(")");<BR>for(i=1;i&lt;=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>}

幻觉 发表于 2006-7-20 18:42

调试过吗
页: [1]
查看完整版本: 单纯型法解线性规划问题(两阶段法)