#include<stdio.h>
#include<math.h>
#include<conio.h>
#define MAXSIZE 20 /*数组最大的维数*/
#define TOTALGRIDNUM 30 /*最多可以有30个表即A+C<=30*/
#define eps 0.000001 /*Similar 0*/
#define FILENAMELEN 50 /*文件名长度*/
/*存放不同的随机一致性指标RI*/
float valueRI[15]={0, 0, 0.58,0.90, 1.12, 1.24, 1.32,1.41, 1.45,1.49,1.52,1.54,1.56,1.58,1.59 };
/*数据表的结构*/
struct TGrid{
int m;
int n;
int tag[MAXSIZE]; /*关联标记*/
float GArray[MAXSIZE][MAXSIZE]; /*用于存放读入的判断矩阵的数据*/
};
/*用于保存特征向量与权值的数据结构*/
struct TProperty{
float CR; /*一次性比率*/
float CI; /*一致性指标*/
float RI; /*随机一致性指标*/
float max; /*最大特征值λmax*/
float W[MAXSIZE]; /*用来存放权值ω的数组(最多20行或列)*/
int n;
};
/*定位打印*/
void printxy(int x,int y,char s[])
{
gotoxy(x,y);
cprintf("%s",s);
}
void drawbox(int x1,int y1,int x2,int y2)
{ int i,j;
printxy(x1,y1,"┏");
for(i=2;i<=x2-x1-4;i+=2)
printxy(x1+i,y1,"━");
printxy(x2-2,y1,"┓");
for(i=1;i<=y2-y1-1;i++)
{ printxy(x1,y1+i,"┃");
printxy(x2-2,y1+i,"┃");
}
printxy(x1,y2,"┗");
for(i=2;i<=x2-x1-4;i+=2)
printxy(x1+i,y2,"━");
printxy(x2-2,y2,"┛");
}
/****************************************和积法***************************************/
struct TProperty SumMethod(struct TGrid tempG )
{ int i,j;
float tArr[MAXSIZE][MAXSIZE];
float tempS,SumW,CI,RI,CR;
float s[MAXSIZE],b[MAXSIZE];
struct TProperty *p;
p=(struct TProperty *)malloc(sizeof(struct TProperty));
/*按列归一化*/
for(j=0;j<tempG.m;j++)
{ s[j]=0;
for(i=0;i<tempG.m;i++) /*按列求和*/
s[j]=s[j]+tempG.GArray[i][j];
for(i=0;i<tempG.m;i++)
tArr[i][j]=tempG.GArray[i][j]/s[j];
}
/*按行求和*/
for(i=0;i<tempG.m;i++)
{ b[i]=0;
for(j=0;j<tempG.m;j++)
b[i]=b[i]+tArr[i][j];
}
SumW=0;
for(i=0;i<tempG.m;i++)
SumW=SumW+b[i];
/*求ω*/
for(i=0;i<tempG.m;i++)
{ b[i]=b[i]/SumW;
p->W[i]=b[i];
}
/*求矩阵的最大特征根λmax*/
for(tempS=0,i=0;i<tempG.m;i++)
{ for(SumW=0, j=0;j<tempG.m; j++)
SumW=SumW+tempG.GArray[i][j]*b[j];
SumW=SumW/b[i];
tempS=tempS+SumW;
}
tempS=tempS/tempG.m;
p->max=tempS;
for(i=0,j=0;i<tempG.n||j<tempG.m;i++)
{ if(tempG.tag[i])
p->W[i]=b[j++];
else
p->W[i]=0;
}
p->CI=(tempS-tempG.m)/(tempG.m-1);
p->RI=valueRI[tempG.m-1];
p->CR=p->CI/(p->RI==0?eps:p->RI);/*防止除数为0*/
p->n=tempG.n;
return *p;
}
/***************************************幂法***************************************/
struct TProperty PowerMethod(struct TGrid tempG )
{ int i,j,k;
float SumCol,Max,CI,RI,CR;
float U[MAXSIZE],V[MAXSIZE];
float tW[MAXSIZE];
int CycleTimes=20;/*幂法循环次数*/
struct TProperty *p;
p=(struct TProperty *)malloc(sizeof(struct TProperty));
for(i=0;i<tempG.m;i++)
{ U[i]=1;
V[i]=1;
}
for(k=0;k<CycleTimes;k++)
{ for(i=0;i<tempG.m;i++)
{ SumCol=0;
for(j=0;j<tempG.m;j++)
SumCol=SumCol+tempG.GArray[i][j]*U[j]; /*按行求和*/
V[i]=SumCol;
}
/*找出V[]中最大值*/
Max=0;
for(j=0;j<tempG.m;j++)
if(Max<fabs(V[j]))
Max=fabs(V[j]);
/*U[]中每个元素除以最大值*/
for(j=0;j<tempG.m;j++)
U[j]=V[j]/Max;
}
/*按列归一化*/
SumCol=0;
for(i=0;i<tempG.m;i++)
SumCol=SumCol+U[i];
/* 求 W[] */
for(i=0;i<tempG.m;i++)
tW[i]=U[i]/SumCol;
/* 求最大特征值*/
Max=0; /*最大特征值,向量组V中的最大值*/
for(i=0;i<tempG.m;i++)
if(Max<fabs(V[i]) )
Max=fabs(V[i]);
p->max=Max;
for(i=0,j=0;i<tempG.n||j<tempG.m;i++)
if(tempG.tag[i])
p->W[i]=tW[j++];
else
p->W[i]=0;
p->CI=(Max-tempG.m)/(tempG.m-1);
p->RI=valueRI[tempG.m-1];
p->CR=p->CI/(p->RI==0?eps:p->RI);/*防止除数为0*/
p->n=tempG.n;
return *p;
}
/************************************方根法***************************************/
struct TProperty SqrtMethod(struct TGrid tempG )
{ int i,j,k;
float SumCol,Max,CI,RI,CR;
float U[MAXSIZE],Aw[MAXSIZE];
float tW[MAXSIZE];
struct TProperty *p;
p=(struct TProperty *)malloc(sizeof(struct TProperty));
for(i=0;i<tempG.m;i++)
{ U[i]=1;
for(j=0;j<tempG.m;j++)
U[i]=tempG.GArray[i][j]*U[i];
U[i]=exp((1.0/tempG.m)*log(U[i]));
}
/*按列归一化*/
SumCol=0;
for(i=0;i<tempG.m;i++)
SumCol=SumCol+U[i];
/* 求 W[] */
for(i=0;i<tempG.m;i++)
tW[i]=U[i]/SumCol;
/*下面求Aw*/
for(i=0;i<tempG.m;i++)
{ Aw[i]=0;
for(j=0;j<tempG.m;j++)
Aw[i]+=tempG.GArray[i][j]*tW[j];
}
/* 求最大特征值*/
Max=0;
for(i=0;i<tempG.m;i++)
Max=Max+Aw[i]/tW[i];
Max=Max/tempG.m;
p->max=Max;
for(i=0,j=0;i<tempG.n||j<tempG.m;i++)
if(tempG.tag[i])
p->W[i]=tW[j++];
else
p->W[i]=0;
p->CI=(Max-tempG.m)/(tempG.m-1);
p->RI=valueRI[tempG.m-1];
p->CR=p->CI/(p->RI==0?eps:p->RI);/*防止除数为0*/
p->n=tempG.n;
return *p;
}
/*输出层次p总排序w和 总排序一致性检验结果如下*/
void matrixOutPut(struct TProperty array[])
{ struct TProperty * p=NULL;
int i,j;
p->n=array[1].n;
i=0;
while(i < p->n )
{ p->W[i]=0;
i++;
};
p->CI=0;
p->RI=0;
p->CR=0;
i=0;
while(i< p->n)
{ j=0;
while(j<array[0].n)
{ ( p->W[i])= (p->W[i])+array[0].W[j]*array[j+1].W[i];
j++;
}
i++;
}
i=0;
while(i<array[0].n)
{ (p->CI)=(p->CI)+array[0].W[i]*array[i+1].CI;
i++;
}
for(i=0;i<array[0].n;i++)
(p->RI)=(p->RI)+array[0].W[i]*array[i+1].RI;
p->CR=(p->CI)/(p->RI==0?eps:p->RI);/*防止除数为0*/
printf("层次总排序W结果为:\n");
for(i=0;i<array[1].n;i++)
printf(" %f ",p->W[i]);
printf("\n层次总排序的一次性检验如下:\n");
printf("CI=%f, RI=%f, CR=%f",p->CI,p->RI,p->CR);
}
/**主程序**/
void main()
{ FILE *fp;
int i=0,n=0,m=0,j=0,k=0,ch=0,pCount/*保存方案P的个数*/;
struct TGrid matrix_1[TOTALGRIDNUM];
struct TProperty matrix_2[TOTALGRIDNUM];
char fname[FILENAMELEN];
int count=0;
int tx,ty;
clrscr(); /*清屏*/
textcolor(14);
printxy(15,0,"系统工程------层次分析法AHP");
printf("\n");
textcolor(12);
printxy(8,2,"计算机解决方案");
printf("\n");
textcolor(15);
printxy(5,3,"信息005班 ");
textcolor(10);
cprintf("王晓洁\n");
printf("\n");
printxy(0,0,"请输入数据文件名(如:Data.txt):");
gets(fname);
printf("\n");
if(strlen(fname)==0)
{ printf("文件名无效或文件不存在!\n");
exit(0);
}
else
{ fp=fopen(fname,"rb"); /*打开数据文件*/
fscanf(fp,"%d",&pCount); /*读总方案P个数*/
fscanf(fp,"%d",&n); /*读准则C个数*/
n++; /*矩阵个数=C的个数+A的个数*/
textcolor(15);
drawbox(2,6,40,10);
textcolor(7);
tx=9;
ty=7;
printxy(tx,ty,"1.----------------和积法");
ty++;
printxy(tx,ty,"2.----------------方根法");
ty++;
printxy(tx,ty,"3.----------------幂法");
ty++;
printxy(1,ty+1,"请从上面选择所使用的权值的求解方法(1~3):");
scanf("%d",&ch);
printf("\n");
clrscr();
/*从文件读取判断矩阵*/
for(i=0;i<n;i++)
{ fscanf(fp,"%d",&(matrix_1[i].m)); /*读取当前矩阵的维数*/
matrix_1[i].n=pCount; /*关联标记Tag的长度,即为P的个数*/
if (i==0)
matrix_1[i].n=n-1; /*如果是A-C矩阵*/
j=0;
while(j<matrix_1[i].n) /*取各位的关联标记*/
{ fscanf(fp,"%d",&(matrix_1[i].tag[j]));
j++;
}
for(j=0;j<matrix_1[i].m;j++) /*取上三角矩阵中的数据*/
for(k=j;k<matrix_1[i].m;k++)
fscanf(fp,"%f",&(matrix_1[i].GArray[j][k]));
for(j=0;j<matrix_1[i].m;j++) /*对下三角矩阵进行关于对角线取倒数的处理*/
for(k=0;k<j;k++)
{ if(j==k)
matrix_1[i].GArray[j][k]=1; /*对角线为1*/
else
matrix_1[i].GArray[j][k]=1/matrix_1[i].GArray[k][j];
}
/*选择三种不同的算法中的一种来进行计算*/
switch(ch){
case 1: matrix_2[i]=SumMethod(matrix_1[i]);
break;
case 2: matrix_2[i]=SqrtMethod(matrix_1[i]);
break;
case 3: matrix_2[i]=PowerMethod(matrix_1[i]);
break;
default:exit(0);
}
}
fclose(fp); /*关闭已经打开的文件*/
/*输出总目标的层次总排序表*/
clrscr();
textcolor(15);
tx=1;
ty=1;
printxy(tx,ty,"判断矩阵A-C:");
drawbox(1,2,41,7);
textcolor(7);
ty=3;
tx=3;
gotoxy(tx,ty);
printf("最大特征值λmax=%f",matrix_2[m].max);
ty++;
tx=3;
gotoxy(tx,ty);
printf("一致性指标CI=%f",matrix_2[m].CI);
ty++;
tx=3;
gotoxy(tx,ty);
printf("随机一致性指标RI=%f",matrix_2[m].RI);
ty++;
tx=3;
gotoxy(tx,ty);
printf("一次性比率CR=%f",matrix_2[m].CR);
printf("\n\n按任意继续显示...");
getch();
clrscr();
for(m=1;m<n;m++)
{ textcolor(15);
tx=1;
ty=1+(m-1)*7;
gotoxy(tx,ty);
cprintf("判断矩阵C%d-P:",m);
drawbox(1,2+(m-1)*7,41,2+m*7-2);
textcolor(7);
ty=3+(m-1)*7;
tx=3;
gotoxy(tx,ty);
printf("最大特征值λmax=%f",matrix_2[m].max);
ty++;
tx=3;
gotoxy(tx,ty);
printf("一致性指标CI=%f",matrix_2[m].CI);
ty++;
tx=3;
gotoxy(tx,ty);
printf("随机一致性指标RI=%f",matrix_2[m].RI);
ty++;
tx=3;
gotoxy(tx,ty);
printf("一次性比率CR=%f",matrix_2[m].CR);
}
printf("\n\n按任意继续显示...");
getch();
clrscr();
drawbox(1,1,79,10);
textcolor(7);
ty=2;
tx=5;
gotoxy(tx,ty);
for(m=0;m<n-1;m++) /*输出Ci,即汇总表的表头*/
printf("%f ",matrix_2[0].W[m]);
printf("\n");
ty++;
gotoxy(tx-2,ty);
printf("-------------------------------------------------------------- ");
for(i=0;i<pCount;i++)
{ ty++;
gotoxy(tx,ty);
for(j=1;j<n;j++)
printf("%f |",matrix_2[j].W[i]);
printf("\n");
}
gotoxy(1,13);
matrixOutPut(matrix_2);
textcolor(14);
gotoxy(1,20);
cprintf("\n注: ");
cprintf("如果判断矩阵的随机一次性比率CR>0.1,则给定的关联矩阵不符合要求!");
}
}