⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ahp.c

📁 层次分析法C语言版
💻 C
字号:
#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,则给定的关联矩阵不符合要求!");
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -