单纯形及对偶单纯形程序.docx
《单纯形及对偶单纯形程序.docx》由会员分享,可在线阅读,更多相关《单纯形及对偶单纯形程序.docx(18页珍藏版)》请在冰豆网上搜索。
单纯形及对偶单纯形程序
人间客制作
编程实现单纯形法的程序。
包括单纯形法、对偶单纯形法。
单纯形法的程序如下:
#include"stdio.h"
#definem4
#definen6
inti,j,r,k,l,lj[m],maxl,minh,q=0,g,h;
floata[m][n];
floatb[m][m],d[m][m],f[m][m],y[m],maxcj,bi[m],ai[m],c[m],e[n],seta,p,z;
voidchushihuaxishuhanglieshi();
voidshuchuxishuhanglieshi();
voidshuchujibianliangdelie();
voiddanweikexingjijuzhen();
voidshuchujibianliangjiazhixishu();
voidshuchujianyanshu();
voidshuchurujibianliang();
voidchujibianliang();
voidshuzuzhuanhuan();
voidyunsuanjieguo();
voidmain()
{
chushihuaxishuhanglieshi();
shuchuxishuhanglieshi();
shuchujibianliangdelie();
danweikexingjijuzhen();
shuchujibianliangjiazhixishu();
shuchujianyanshu();
shuchurujibianliang();
while(maxcj>0)
{
chujibianliang();
shuzuzhuanhuan();
shuchujibianliangjiazhixishu();
shuchujianyanshu();
shuchurujibianliang();
}
yunsuanjieguo();
}
voidchushihuaxishuhanglieshi()
{
printf("请以增广矩阵形式输入系数:
\n");
for(i=0;ifor(j=0;jscanf("%f",&a[i][j]);
}
voidshuchuxishuhanglieshi()
{printf("系数增广矩阵\n");
for(i=0;i{
for(j=0;jprintf("\n");
}
}
voidshuchujibianliangdelie()
{
for(j=1,h=1;j{
for(g=0,i=0;iif(g==(m-1))
{
lj[h]=j;
h++;
}
}
printf("基变量的列下标");
printf("\n");
for(i=1;iprintf("%5d",lj[i]);
printf("\n\n");
}
voiddanweikexingjijuzhen()
{
for(i=0;ifor(j=0;jfor(i=1;i}
voidshuchujibianliangjiazhixishu()
{
for(i=1;ic[i]=a[0][lj[i]];
printf("基变量价值系数:
");
for(i=1;iprintf("%9.3f",c[i]);
printf("\n");
}
voidshuchujianyanshu()
{
for(j=1;j{
y[j]=0.0;
for(i=1;iy[j]+=c[i]*b[i][j];
}
for(j=1;j{
for(r=1;rif(lj[r]==j)
{
e[j]=0.0;
break;
}
e[j]=a[0][j];
for(i=1;ie[j]=e[j]-y[i]*a[i][j];
}
printf("检验数:
");
for(i=1;iprintf("%9.3f",e[i]);
printf("\n");
}
voidchujibianliang()
{
for(i=1;i{
bi[i]=0.0;
for(r=1;rbi[i]+=b[i][r]*a[r][0];
}
printf("bi[i]**");
for(i=1;iprintf("%9.3f",bi[i]);
printf("\n");
for(i=1;i{
ai[i]=0.0;
for(r=1;rai[i]+=b[i][r]*a[r][k];
}
printf("ai[i]**");
for(i=1;iprintf("%9.3f",ai[i]);
printf("\n");
seta=1650.0;
for(j=1;j{
if(ai[j]>0)
if(seta>bi[j]/ai[j])
{
seta=bi[j]/ai[j];
minh=j;
}
}
printf("出基变量:
x%d\n",lj[minh]);
lj[minh]=k;
printf("当前基变量下标\n");
for(i=1;iprintf("%5d",lj[i]);
printf("\n");
}
voidshuzuzhuanhuan()
{
l=minh;
p=ai[l];
lj[l]=k;
for(i=0;ifor(j=0;jd[i][j]=0.0;
for(i=1;ifor(i=1;id[l][l]=(float)1.0/p;
for(i=1;ifor(j=1;j{
f[i][j]=0.0;
for(r=1;r}
for(i=1;ifor(j=1;jb[i][j]=f[i][j];
}
voidshuchurujibianliang()
{
maxcj=e[1];
maxl=1;
for(j=2;jif(maxcj{
maxcj=e[j];
maxl=j;
}
if(maxcj==0)gotoloop;
k=maxl;
printf("入基变量:
x%d\n",k);
loop:
;
}
voidyunsuanjieguo()
{
for(i=1;i{
bi[i]=0.0;
for(r=1;r}
z=0.0;
for(i=1;i{
c[i]=a[0][lj[i]];
printf("x%d=%9.3f\n",lj[i],bi[i]);
z+=bi[i]*c[i];
}
printf("Zmax=%9.3f\n",z);
}
程序说明:
由于程序中要调用子程序,因此将所有的变量都定义为全局变量。
第二行和第三行为预编译命令。
由于C语言中不允许定义动态数组,因此该程序的通用性有一定的局限性:
对于不同的变量数目和约束方程个数,要修改对数组的预编译值。
但使用预编译能做到一改全改,在一定程度上缓解了这种局限性。
不过,如果将数组定义的足够大,那么便不存在这样的局限性,但是这将浪费很大的内存空间,也是不太可取的。
接下来几行是对程序中用到的变量进行定义。
紧接着的是对子程序的声明。
各子程序的意义如下:
voidchushihuaxishuhanglieshi();该子程序为“初始化系数行列式”,有一点要注意,C语言中数组的下标是从零开始的,为了与我们的习惯相一致,对系数的初始化时可用如下方法:
0
C1
C2
C3
……
Cn
B1
A11
A12
A13
……
A1n
B2
A21
A22
A23
……
A2n
……
……
……
……
……
……
Bn
An1
An2
An3
……
Ann
其中,Ann是变量的系数,Bn是资源向量,Cn是价值系数。
voidshuchuxishuhanglieshi();该子程序将增广矩阵数组输出,不再做过多说明。
voidshuchujibianliangdelie();该子程序将在初始化后的矩阵中找出可行基的下标。
voiddanweikexingjijuzhenbianhuan();该子程序将完成对b[i][j]的转换,为下一步求解检验数做准备。
voidshuchujibianliangjiazhixishu();该子程序将输出基变量的价值系数。
voidshuchujianyanshu();该子程序输出基变量的检验数。
voidshuchurujibianliang();该子程序输出入基变量。
voidchujibianliang();该子程序给出基变量。
voidshuzuzhuanhuan();该子程序对a[i][j]数组进行变换。
voidyunsuanjieguo();该子程序将输出运算结果。
另外做一点说明,由于采用了预编译,编译系统偶尔可能提示‘警告’,‘警告’会出现在#definen6这一句,只需多点几次编译就行了。
例子可采用老师讲课时举的那个题目。
输入:
123000
812100
1640010
1204001
运行的结果可参见如下截图:
对偶单纯形法的程序如下:
#include
#include
#definem2
#definen5
#defineM1000000.0;
floata[m][n],c[n],b[m],seta[n],d[n];
intu[n];
inti,j,k,f,g,h;
intp,q;
floatz=0,min=0,p1,p2,p3;
intchujibianliang();
intrujibianliang(intp);
voiddanchunxingbiaodezhuanhuan(intp,intq);
voidprint1();
voidprint2();
voidinput();
voidmain()
{
input();
for(j=0,h=0;j{
for(g=0,i=0;iif(g==(m-1))
{
u[h]=j+1;
h++;
}
}
printf("基变量的列标\n");
for(i=0;iprintf("%5d",u[i]);
printf("\n");
for(i=0;i{
if(a[i][u[i]-1]<=0)
{
b[i]=-b[i];
for(j=0;ja[i][j]=-a[i][j];
}
}
for(i=0;iprint1();
print2();
while
(1)
{
p=chujibianliang();
if(p==-1)
{
printf("\n所得解已经是最优解!
\n");
for(i=0;iz+=b[i]*c[u[i]-1];
for(i=0;iprintf("X(%d)=%6.3f\t",u[i],b[i]);
printf("z=%6.3f\n",z);
break;
}
q=rujibianliang(p);
if(q==-1)break;
danchunxingbiaodezhuanhuan(p,q);
print2();
}
}
voidinput()
{
printf("请输入系数矩阵a(%d行%d列):
\n",m,n);
for(i=0;ifor(j=0;jscanf("%f",&a[i][j]);
printf("\n请输入资源向量b:
\n");
for(i=0;iscanf("%f",&b[i]);
printf("\n请输入目标函数系数矩阵c:
\n");
for(i=0;iscanf("%f",&c[i]);
}
intchujibianliang()
{
for(i=0;i{
if(b[i]>=0)
f=1;
else
{
f=0;
break;
}
}
if(f==1)
return-1;
for(i=0;i{
if(b[i]<0&&min>b[i])
{
min=b[i];
k=i;
}
}
returnk;
}
intrujibianliang(intp)
{
for(j=0;j{
if(a[p][j]>=0)
f=1;
else
{
f=0;
break;
}
}
if(f==1)
{
printf("\n原线性规划问题无可行解!
\n");
return-1;
}
for(j=0;j{
if(a[p][j]<0)
seta[j]=d[j]/a[p][j];
else
seta[j]=M;
}
min=M;
for(j=0;j{
if(min>=seta[j])
{
min=seta[j];
i=j;
}
}
u[p]=i+1;
returni;
}
voiddanchunxingbiaodezhuanhuan(intp,intq)
{
p1=a[p][q];
for(i=0;i{
if(i!
=p)
{
if(a[i][q]!
=0)
{
p2=a[i][q]/p1;
for(j=0;ja[i][j]-=a[p][j]*p2;
b[i]=b[i]-b[p]*p2;
}
}
}
p3=d[q]/p1;
for(i=0;id[i]-=a[p][i]*p3;
for(j=0;ja[p][j]/=p1;
b[p]=b[p]/p1;
}
voidprint1()
{
printf("\n");
printf("\t");
for(i=1;i<=n;i++)
printf("X(%d)\t",i);
printf("最优解取值\n");
printf("\n");
printf("\t");
for(i=0;iprintf("%6.3f\t",-c[i]);
printf("\n");
}
voidprint2()
{
printf("\n");
for(i=0;i{
printf("X(%d)\t",u[i]);
for(j=0;jprintf("%6.3f\t",a[i][j]);
printf("%6.3f\n",b[i]);
}
printf("\n");
printf("检验数");
for(i=0;iprintf("%8.3f",d[i]);
printf("\n");
}
程序说明:
由于程序中要调用子程序,因此将所有的变量都定义为全局变量。
同第一个程序一样,由于C语言中不允许定义动态数组,因此该程序的通用性有一定的局限性:
对于不同的变量数目和约束方程个数,要修改对数组的预编译值。
接下来几行是对程序中用到的变量进行定义。
紧接着的是对子程序的声明。
各子程序的意义如下:
voidinput();完成对各个量的初始化,即变量的系数、资源向量、价值系数。
intchujibianliang();给出出基变量。
intrujibianliang(intp);给出入基变量。
voiddanchunxingbiaodezhuanhuan(intp,intq);对系数行列式进行变换。
voidprint1();输出变量及对应的价值系数。
voidprint2();输出变量的系数、资源向量及检验数。
例1求解线性规划问题
min
;
添加松弛变量以后的标准型
min
将每个等式两边乘以-1,则上述问题转化为
min
;
可以输入:
-3-2-210
-5-1-201
-5-4
1551100
运行结果如下: