层次分析法C语言实现

这里只实现了因素只有一级的情况。

准备工作

1. 头文件、矩阵数组等声明

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define maxResolutionNumber 128 //最大解决方案数
#define maxFactorNumber 128 //最大因素个数
float RI[]={0,0,0.58,0.90,1.12,1.24,1.32,1.41,1.45,1.49};
//三维数组,分别表示矩阵的行,列坐标,和存放的字符串值。
//不能使用char* Matrix[maxYSNumber][maxYSNumber],否则只能存放字符串地址。
//使用字符串形式保存,需要计算时可以使用atof转换为了float型
typedef char Matrix[maxFactorNumber][maxFactorNumber][128];
typedef float NormalizedMatrix[maxFactorNumber][maxFactorNumber];
typedef float weightVector[128];//这里只定义了一个向量,作为过渡使用,直接存入矩阵。
Matrix mCriterionLayer;//准则层次比较矩阵
NormalizedMatrix mmCriterionLayer;
Matrix factors[maxResolutionNumber];//因素比较矩阵集合,最多存放 maxResolutionNumber 个矩阵
NormalizedMatrix nFactors[maxResolutionNumber];
Matrix result;//准则层次比较矩阵

2. 读取Excel文件

 //从cvs文件中读取矩阵信息
//读取文件内容到矩阵m
void readMatrix(char * filePath,Matrix m){
	FILE *fp = NULL;
	char *line,*record;
	char buffer[1024];
	int x=0,y=0,n=0;

	if ((fp=fopen(filePath,"r")) != NULL){
		char delims[] = ",";
		wchar_t *result = NULL;
		//当没有读取到文件末尾时循环继续
		while (line = fgets(buffer, sizeof(buffer), fp)){
			line[strlen(line)-1]='\0';//去除\r\n,无法通过查找\r或\n来处理,但确实先执行\r,将光标移动到第一个字符钱,然后往下一行。可能vc2010对回车的解释看做一个字符?
			record = strtok(line, ",");
			while (record){
				//考虑到小数点以及结束符,自己使用128,而不要用sizeof。
				memcpy(m[x][y],record,128/*sizeof(record)+3*/);
				record = strtok(NULL, ",");	
				y++;
			}
			y=0;
			x++;
		}
		fclose(fp);
		fp = NULL;
	}
}

具体见下面的链接
https://blog.csdn.net/weixin_41958234/article/details/105681204

3. 辅助函数

3.1打印矩阵

//打印矩阵
void printMatrix(Matrix m,int n){
	int i,j;
	for(i=0;i<n;i++){
		for(j=0;j<n;j++){
			if(is_in(m[i][j],'*')!=-1)
				printf("\t");
			else if(atof(m[i][j])>0&&atof(m[i][j])<10)//为了解决精度显示问题
				printf("%.3f \t",atof(m[i][j]));
			else
				printf("%s \t",m[i][j]);
		}
		puts("");
	}
}

3.2判断字符串中是否包含某个字符,并返回它所在的位置

int is_in(char*s, char c){
	int n=0;
	while(*s != '\0'){
		if(*s == c){
			return n;
		}
		else{
			s++;n++;
		}
	}
return -1;
}

4. 阶段成果展示

为了测试方便,把需要用户输入的部分都注释掉,采用了自己赋值的方式。程序有一些规定用户必须准守:

  1. 结果矩阵文件的路径和名称必须为:data/最后计算结果.csv
  2. 准则层矩阵五年级的路径和名称必须为:data/准则层次比较矩阵.csv
  3. csv表格中的,如果表各项没有内容,必须使用*占位。

这样程序使用会比较方便,相应于我们自己定义的一个框架,使用者必须准守,当然也可以改成用户输入的方式。

int main()
{		
	int i,j;
	char MatrixName[120];
	weightVector wv;
	int factorNum=5,solutionNum=3;
	//puts("请输入因素个数:");
	//scanf("%d",&factorNum);
	//puts("请输入方案个数:");
	//scanf("%d",&solutionNum);
	//puts("---------------结果矩阵:----------------");
	readMatrix("data/最后计算结果.csv",result);
	printMatrix(result,11);
	puts("---------------准则层比较矩阵:----------------");
	readMatrix("data/准则层次比较矩阵.csv",mCriterionLayer);
	printMatrix(mCriterionLayer,factorNum+1);

	puts("---------------因素判断矩阵:----------------");
	//for( i=0;i<factorNum;i++)
	//{
	//	printf("请输入矩阵cvs相对路径:");
	//	scanf("%s",MatrixName);
	//	readMatrix(MatrixName,factors[i]);
	//	printMatrix(factors[0],solutionNum+1);
	//    puts("");
	//}
	puts("--景色判断矩阵:");
	readMatrix("data/景色判断矩阵.csv",factors[0]);
	printMatrix(factors[0],solutionNum+1);
	puts("");
	puts("--费用判断矩阵:");
	readMatrix("data/费用判断矩阵.csv",factors[1]);
	printMatrix(factors[1],4);
	puts("");
	puts("--居住判断矩阵:");
	readMatrix("data/居住判断矩阵.csv",factors[2]);
	printMatrix(factors[2],4);
	puts("");
	puts("--饮食判断矩阵:");
	readMatrix("data/饮食判断矩阵.csv",factors[3]);
	printMatrix(factors[3],4);
	puts("");
	puts("--旅途判断矩阵:");
	readMatrix("data/旅途判断矩阵.csv",factors[4]);
	printMatrix(factors[4],4);
	puts("");
}

运行结果如下,这里只是把cvs文件中的内容读取到了我们的数组当中。
在这里插入图片描述
准备工作都做完了下面开始真真进入到计算部分。

计算

1. 矩阵标准化

//矩阵标准化,标准化之后的结果存入新的矩阵。
void normalizeMatrix(Matrix m,NormalizedMatrix nm,int n){
	int i,j;
	float sum;
	for(j=1;j<n;j++){
		sum=0;
		for(i=1;i<n;i++){
			sum+=atof(m[i][j]);
		}
		for(i=1;i<n;i++){
			nm[i-1][j-1]=atof(m[i][j])/sum;
		}
	}
}

2.计算权重

//计算权重,向量相乘
void countWeight(NormalizedMatrix nm,int n, weightVector returnValue){
	int i,j;
	//nm是标准化之后的矩阵,sum为因子的个数,也就是n-1
	float sum=n-1,subSum;
	//求每个因素的子和,小计。然后除以总和sum得到权重值
	for(i=0;i<n;i++){
		subSum=0;
		for(j=1;j<n;j++)
			subSum+=nm[i][j];
		returnValue[i]=subSum/sum;
	}
}

3.将值写入结果矩阵

//将向量值写入结果矩阵。
//col为插入result的第几列,n为weightVector的有效长度
void insertResult(weightVector v,int col, int n){
	int i,j;
	for(i=0;i<n;i++)
		sprintf(result[i+1][col],"%.3f",v[i]);
}

4.阶段成果展示

这里将准则层和因素的判断矩阵分开处理。

int main()
{		
     ... ...
     //准则层:标准化矩阵值、计算准则层权重、将结果插入结果矩阵
    normalizeMatrix(mCriterionLayer,mmCriterionLayer,factorNum+1);
	countWeight(mmCriterionLayer,factorNum,wv);
	insertResult(wv,factorNum+1,factorNum);
	//计算判断因素的权重
	for(i=0;i<factorNum;i++){
		normalizeMatrix(factors[i],nFactors[i],solutionNum+1);
		countWeight(nFactors[i],solutionNum,wv);
		insertResult(wv,i+1,solutionNum);
	}
	puts("---------------计算结果:----------------");
	printMatrix(result,max(factorNum+3,solutionNum+7));
}

在这里插入图片描述

5.计算 λ m a x \lambda_{max} 、CI,CR

float countLambda(Matrix m,weightVector v,int n){
	int i,j;
	float AlambdaDivLambda,sum=0;
	for(i=0;i<n;i++){
		AlambdaDivLambda=0;
		for(j=0;j<n;j++){
			AlambdaDivLambda+=atof(m[i+1][j+1])*v[j];
		}
		sum+=AlambdaDivLambda/v[i];
	}
	return sum/n;
}

float countCI(weightVector v,int n){
	return(v[n]-n)/(n-1);
}

float countCR(weightVector v,int n){
	return(v[n+1])/RI[n-1];//CI/CR
}

6.阶段成果展示

int main(){		
... ...
	//计算判断因素的权重
	for(i=0;i<factorNum;i++){
		... ...
		wv[solutionNum]=countLambda(factors[i],wv,solutionNum);
		wv[solutionNum+1]=countCI(wv,solutionNum);
		wv[solutionNum+2]=RI[solutionNum-1];
		wv[solutionNum+3]=countCR(wv,solutionNum);
		insertResult(wv,i+1,solutionNum+4);
	}
	puts("---------------计算结果:----------------");
	printMatrix(result,max(factorNum+3,solutionNum+7));
}

在这里插入图片描述

7. 计算总排序权重

//nS:方案数,nF:因素数
void countTotalWeight(Matrix m,int nS,int nF,weightVector v){
	int i,j;
	float subsum;
	for(i=0;i<nS;i++){
		subsum=0;
		for(j=0;j<nF;j++)
			subsum+=atof(m[i+1][j+1])*atof(m[j+1][nF+1]);
		v[i]=subsum;
	}
}

8.计算总排序一致性指标

//nS:方案数,nF:因素数
float countTotalCi(Matrix m,int nS,int nF){
	int i;
	float totalCi=0;
	for(i=0;i<nS;i++)
		totalCi+=atof(m[nS+2][i+1])*atof(m[i+1][nF+1]);
	return totalCi;
}

9.阶段展示

int main{
	......
	countTotalWeight(result,solutionNum,factorNum,wv);
	insertResult(wv,factorNum+2,solutionNum);

	sprintf(result[solutionNum+6][3],"%.3f",RI[solutionNum-1]);
	sprintf(result[solutionNum+6][1],"%.3f",countTotalCi(result,solutionNum,factorNum));
	sprintf(result[solutionNum+6][5],"%.3f",countTotalCi(result,solutionNum,factorNum)/RI[solutionNum-1]);//总排序指标率

	if(countTotalCi(result,solutionNum,factorNum)/RI[solutionNum-1]<0.1)
		sprintf(result[solutionNum+6][7],"%s","通过");
	else
		sprintf(result[solutionNum+6][7],"%s","拒绝");
	puts("---------------计算结果:----------------");
	printMatrix(result,max(factorNum+3,solutionNum+7));

	return 0;
}

在这里插入图片描述

调整main函数,支持用户输入,以便支持不同的需求

int main(){		
	int i,j;
	char MatrixName[120];
	weightVector wv;
	int factorNum=5,solutionNum=3;
	puts("请输入因素个数:");
	scanf("%d",&factorNum);
	puts("请输入方案个数:");
	scanf("%d",&solutionNum);
	//puts("---------------结果矩阵:----------------");
	readMatrix("data/最后计算结果.csv",result);
	printMatrix(result,11);
	puts("---------------准则层比较矩阵:----------------");
	readMatrix("data/准则层次比较矩阵.csv",mCriterionLayer);
	printMatrix(mCriterionLayer,factorNum+1);

	puts("---------------因素判断矩阵:----------------");
	for( i=0;i<factorNum;i++){
		printf("请输入矩阵cvs相对路径:");
		scanf("%s",MatrixName);
		readMatrix(MatrixName,factors[i]);
		printMatrix(factors[0],solutionNum+1);
	    puts("");
	}
	//puts("--景色判断矩阵:");
	//readMatrix("data/景色判断矩阵.csv",factors[0]);
	//printMatrix(factors[0],solutionNum+1);
	//puts("");
	//puts("--费用判断矩阵:");
	//readMatrix("data/费用判断矩阵.csv",factors[1]);
	//printMatrix(factors[1],4);
	//puts("");
	//puts("--居住判断矩阵:");
	//readMatrix("data/居住判断矩阵.csv",factors[2]);
	//printMatrix(factors[2],4);
	//puts("");
	//puts("--饮食判断矩阵:");
	//readMatrix("data/饮食判断矩阵.csv",factors[3]);
	//printMatrix(factors[3],4);
	//puts("");
	//puts("--旅途判断矩阵:");
	//readMatrix("data/旅途判断矩阵.csv",factors[4]);
	//printMatrix(factors[4],4);
	//puts("");
	
	normalizeMatrix(mCriterionLayer,mmCriterionLayer,factorNum+1);
	//printMatrix(mCriterionLayer,6);
	//计算准则层权重
	countWeight(mmCriterionLayer,factorNum,wv);
	insertResult(wv,factorNum+1,factorNum);
	//计算判断因素的权重
	for(i=0;i<factorNum;i++){
		normalizeMatrix(factors[i],nFactors[i],solutionNum+1);
		countWeight(nFactors[i],solutionNum,wv);
		wv[solutionNum]=countLambda(factors[i],wv,solutionNum);
		wv[solutionNum+1]=countCI(wv,solutionNum);
		wv[solutionNum+2]=RI[solutionNum-1];
		wv[solutionNum+3]=countCR(wv,solutionNum);
		insertResult(wv,i+1,solutionNum+4);
	}

	countTotalWeight(result,solutionNum,factorNum,wv);
	insertResult(wv,factorNum+2,solutionNum);

	sprintf(result[solutionNum+6][3],"%.3f",RI[solutionNum-1]);
	sprintf(result[solutionNum+6][1],"%.3f",countTotalCi(result,solutionNum,factorNum));
	sprintf(result[solutionNum+6][5],"%.3f",countTotalCi(result,solutionNum,factorNum)/RI[solutionNum-1]);//总排序指标率

	if(countTotalCi(result,solutionNum,factorNum)/RI[solutionNum-1]<0.1)
		sprintf(result[solutionNum+6][7],"%s","通过");
	else
		sprintf(result[solutionNum+6][7],"%s","拒绝");
	puts("---------------计算结果:----------------");
	printMatrix(result,max(factorNum+3,solutionNum+7));

	return 0;
}

大功告成!

猜你喜欢

转载自blog.csdn.net/weixin_41958234/article/details/105684072