C语言实现单纯行法与对偶单纯行法
某次为了完成课程要求所做:
单纯形法代码如下,使用方法修改二位数组A[ip][jp],
#include<stdio.h>
#define ip 3
#define jp 7
int i,j,m,n,flag=1;
float max=-1,min=1000,guiyi;
float C[jp-1]={-100,-100,100,0,0,0};
float A[ip][jp]={{1,1,2,1,0,0,-1},{1,1,-1,0,1,0,-1},{-1,1,1,0,0,1,-1}};
float X[ip]={0,0,0};
float zc[jp-1]={0};
int ji[ip]={3,4,5};//第3、4、5为4.5.6前系数
void show();
void jinji();
void chuji();
void trans();
void show_result();
int main()
{char c;
//初始矩阵显示
show();
//计算矩阵的判别数 记录大于0的最大的判别数 确认进基变量
jinji();
while(flag==1)
{
//确认出基变量
chuji();
//初等行变换
trans();
//初等行变换后结果
show();
//计算矩阵的判别数 记录大于0的最大的判别数 确认进基变量
jinji();
flag=0;
for(j=0;j<jp-1;j++)
{
if(zc[j]>0)
flag=1;
}
}
show_result();
c=getchar();
return 0;
}
void show()
{
printf(" ") ;
for(j=0;j<jp-1;j++)//显示x1~x6
{
printf("x%d ",j+1);
}
printf("\n");
for(i=0;i<ip;i++)
{
printf("x%d ",ji[i]+1);
for(j=0;j<jp;j++)
{
if(A[i][j]>=0)
printf(" ");
printf("%.2f ",A[i][j]);
}
printf("\n");
}
}
void jinji()
{max=-1;
printf("Z-C ");
for(j=0;j<jp-1;j++)
{
zc[j]=0;
for(i=0;i<ip;i++)
zc[j]=C[ji[i]]*A[i][j]+zc[j];
zc[j]=zc[j]-C[j];
if(zc[j]>=0)
{
{
if(zc[j]>max)
{
max=zc[j];
m=j;
}
printf(" ");
}
}
printf("%.2f ",zc[j]);
}
printf("%d\n",m);
}
void chuji()
{min=1000;
for(i=0;i<ip;i++)
if(A[i][m]>0)
{
if(A[i][jp-1]/A[i][m]<min)
min=A[i][jp-1]/A[i][m];
n=i;
}
printf("%d",n);
}
void trans()
{
guiyi=1.0/A[n][m];
for(j=0;j<jp;j++)
A[n][j]=A[n][j]*guiyi;
float tem[ip];
//保留矩阵A中行变换需要归零的列
for(i=0;i<ip;i++)
{
tem[i]=A[i][m];
}
for(i=0;i<ip;i++)
{
if(i!=n)//保留用于变换的行,否则会被归零
for(j=0;j<jp;j++)
{
A[i][j]=A[i][j]-A[n][j]*tem[i];
}
}
//改变基
ji[n]=m;//矩阵是从0开始的
}
void show_result()
{
for(n=0;n<ip;n++)
{
printf("%d",ji[n]);
if(ji[n]<3)
X[ji[n]]=A[n][jp-1];
}
printf("\n(x1,x2,x3)=(%.2f,%.2f,%.2f)",X[0],X[1],X[2]);
printf("最优解为%f",C[0]*X[0]+C[1]*X[1]+C[2]*X[2]);
}
对偶单纯形法
#include<stdio.h>
#define ip 4
#define jp 8
int i,j,m,n,flag=1;
float min=0,guiyi;
float C[jp-1]={1,1,-4,0,0,0};
float A[ip][jp]={
{ 1, -1.0/3, 0, 1.0/3, 0, -2.0/3, 0, 1.0/3},
{ 0, 2, 0, 0, 1, 1, 0, 6},
{ 0, 2.0/3, 1, 1.0/3, 0, 1.0/3, 0, 13.0/3},
{-3, 1, 6, 0, 0, 0, 1, 17}
};
float X[3]={1.0/3,0,13.0/3};//原先最优解
float zc[jp-1]={0};//检验数
int ji[ip]={0,4,2,6};//基
void show();
void jinji();
void chuji();
void trans();
void trans_init();
void show_result();
int main()
{char c;//用于暂停
for(j=0;j<3;j++)
{
min=A[ip-1][j]*X[j]+min;
}
if(min>A[ip-1][jp-1])
{
printf("新增条件改变了原有最优解\n");
show();
trans_init();
show();
chuji();
jinji();
while(flag==1)
{
trans();
show();
chuji();
jinji();
flag=0;//假设全大于0
for(i=0;i<ip;i++)
if(A[i][jp-1]<0)//只要有b小于0继续循环
flag=1;
}
show_result();//至此单纯形法结束
}
else
{
printf("最优解未变");
show_result();
}
min=0;
c=getchar(); //暂停一下
return 0;
}
void show()
{
printf(" ") ;
for(j=0;j<jp-1;j++)//显示x1~x6
{
printf("x%d ",j+1);
}
printf("\n");
for(i=0;i<ip;i++)
{
printf("x%d ",ji[i]+1);
for(j=0;j<jp;j++)
{
if(A[i][j]>-0.01)
printf(" ");
printf("%.2f ",A[i][j]);
}
printf("\n");
}
}
void jinji()
{
printf("Z-C ");
for(j=0;j<jp-1;j++)
{
zc[j]=0;
for(i=0;i<ip;i++)
zc[j]=C[ji[i]]*A[i][j]+zc[j];
zc[j]=zc[j]-C[j];
if(zc[j]>=0)
{
printf(" ");
}
printf("%.2f ",zc[j]);
}
printf("\n");
min=0;
for(j=0;j<jp-1;j++)
{
if((A[n][j]<0)&&(A[n][j]<min))
{
min=zc[j]/A[n][j];
m=j;
}
}
// printf("%d",m);
}
void chuji()
{min=0;
for(i=0;i<ip;i++)
if(A[i][jp-1]<min)
{
min=A[i][jp-1];
n=i;
}
// printf("%d",n);
}
void trans_init()
{
float tem[ip-1];
for(i=0;i<ip-1;i++)
{
if(A[ip-1][ji[i]]!=0)
tem[i]=A[ip-1][ji[i]];
}
for(i=0;i<ip-1;i++)
{for(j=0;j<jp;j++)
{
A[ip-1][j]=A[ip-1][j]-tem[i]*A[ji[i]][j];
}
}
}
void trans()
{
guiyi=1.0/A[n][m];
for(j=0;j<jp;j++)
{
A[n][j]=A[n][j]*guiyi;
if(A[n][j]==-0.0)//修正bug
A[n][j]=0.0;
}
float tem[ip];
//保留矩阵A中行变换需要归零的列
for(i=0;i<ip;i++)
{
tem[i]=A[i][m];
}
for(i=0;i<ip;i++)
{
if(i!=n)//保留用于变换的行,否则会被归零
for(j=0;j<jp;j++)
{
A[i][j]=A[i][j]-A[n][j]*tem[i];
}
}
//改变基
ji[n]=m;//矩阵是从0开始的
}
void show_result()
{
for(n=0;n<ip;n++)
{
// printf("%d",ji[n]);
if(ji[n]<3)
X[ji[n]]=A[n][jp-1];
}
printf("\n(x1,x2,x3)=(%.2f,%.2f,%.2f)",X[0],X[1],X[2]);
printf("最优解为%f",C[0]*X[0]+C[1]*X[1]+C[2]*X[2]);
}