【矿大】中国矿业大学 CUMT 信息安全管理与工程2024春季学期 OpenJudge OJ 问题 M: 模糊层次分析法

题目

样例输入

3
1 5 4
0.2 1 2
0.25 0.5 1
3
1 3 4
0.33 1 2
0.25 0.5 1
4
1 4 2 5
0.25 1 0.25 2
0.5 4 1 6
0.2 0.5 0.167 1
3
1 2 0.33
0.5 1 0.2
3 5 1
0 0 4 58 38
3 4 12 47 34
2 7 20 42 29
0 6 27 47 20
4 11 27 38 20
9 11 22 33 25
2 9 20 42 27
0 4 16 42 38
9 16 31 33 11
11 15 36 27 11

样例输出

The judgment matrix has passed the consistency test
1.7911 2.3078 2.6351 2.0009

题解

整个题目还是比较混乱的,图和表的序号标的也是乱七八糟,不过过程讲的还算清晰

输入那里也有说明错误,第一个是第一层矩阵,之后应该都是第二层矩阵

一共分为几大步

1.计算归一化的ω向量

这一步将四个单独的矩阵分开计算,分别求得ω向量,这个向量在下面的步骤中要用到,下面的步骤分为两支,一个是验证一致性,另一个是继续求评分

void FAHP::ComputeOmiga()
{
	for (int b = 0; b < flod_proup.size(); b++)
	{
		for (int i = 0; i < flod_proup.at(b).size(); i++)
		{
			double sum = 0;
			for (int j = 0; j < flod_proup.at(b).size(); j++)
			{
				sum += flod_proup.at(b).at(j).at(i);
			}
			for (int j = 0; j < flod_proup.at(b).size(); j++)
			{
				normal_flod_proup.at(b).at(j).at(i) = flod_proup.at(b).at(j).at(i) / sum;
			}
		}
		vector<double> tem1;
		for (int i = 0; i < flod_proup.at(b).size(); i++)
		{
			double sum = 0;
			for (int j = 0; j < flod_proup.at(b).size(); j++)
			{
				sum += normal_flod_proup.at(b).at(i).at(j);
			}
			tem1.push_back(sum);
		}
		double tem2 = 0;
		for (auto i : tem1)
		{
			tem2 += i;
		}
		for (int i = 0; i < tem1.size(); i++)
		{
			tem1[i] = tem1.at(i) / tem2;
		}
		omiga_group.push_back(tem1);
	}
}

2.验证一致性

这一步讲解的也比较清晰,也许在计算Aω那里不是很清楚,说明一下

A\omega = \begin{bmatrix} 1 & 5 & 4\\ \frac{1}{5} & 1 & 2\\ \frac{1}{4}& \frac{1}{2} & 1 \end{bmatrix}\begin{bmatrix} 0.6768\\ 0.1925\\ 0.1307 \end{bmatrix}=\begin{bmatrix} 2.1622\\ 0.5893\\ 0.3962 \end{bmatrix}

上式经过四舍五入保留四位小数,仅供参考

\lambda = \frac{1}{3}(\frac{2.1622}{0.6768}+\frac{0.5893}{0.1925}+\frac{0.3962}{0.1307})

下面放的是验证代码

void FAHP::ConsistencyTest()
{
	consiste = true;
	for (int i = 0; i < flod_proup.size(); i++)
	{
		vector<double> a_m_moiga = AOmiga(flod_proup.at(i), omiga_group.at(i));
		double tem1 = 0;
		for (int j = 0; j < omiga_group.at(i).size(); j++)
		{
			tem1 += a_m_moiga.at(j) / omiga_group.at(i).at(j);
		}
		tem1 = tem1 / omiga_group.at(i).size();
		double CI = (tem1 - omiga_group.at(i).size()) / (omiga_group.at(i).size() - 1);
		if (CI / n_RI[omiga_group.at(i).size()] > 0.1)
		{
			consiste = false;
		}
	}
}

3.计算分数

这里,输入调查数据要除以100,变成百分数再计算

只需要按照公式就可以了

void FAHP::ComputeB()
{
	for (int i = 1; i < omiga_group.size(); i++)
	{
		vector<double> tem1;
		for (int j = 0; j < r_group.at(i - 1).at(0).size(); j++)
		{
			double sum = 0;
			for (int k = 0; k < omiga_group.at(i).size(); k++)
			{
				sum += omiga_group.at(i).at(k) * r_group.at(i - 1).at(k).at(j);
			}
			tem1.push_back(sum / 100);
		}
		b_group.push_back(tem1);
		double tem2 = ComputeS(tem1);
		s_group.push_back(tem2);
	}
	ComputeTotle();
}

void FAHP::ComputeTotle()
{
	vector<double> temS;
	for (int i = 0; i < b_group.at(0).size(); i++)
	{
		double sum = 0;
		for (int j = 0; j < b_group.size(); j++)
		{
			sum += omiga_group.at(0).at(j) * b_group.at(j).at(i);
		}
		temS.push_back(sum);
	}

	totle = ComputeS(temS);
}

double FAHP::ComputeS(vector<double> b)
{
	double sum = 0;
	for (int i = 5; i > 0; i--)
	{
		sum += b.at(5 - i) * i;
	}
	return sum;
}

代码

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

class FAHP
{
public:
	FAHP(vector<vector<vector<double>>> flod, vector<vector<vector<double>>> matrix_proup);

	//读取判断指标
	bool GetConsiste() const;

	void ComputeOmiga();

	//计算综合隶属度
	void ComputeB();

	void ComputeTotle();

	void PrintScore();

private:
	vector<vector<vector<double>>> flod_proup;

	vector<vector<vector<double>>> r_group;

	//执行一致性检验
	void ConsistencyTest();

	bool consiste;

	//归一化后的原矩阵
	vector<vector<vector<double>>> normal_flod_proup;
	//omiga矩阵
	vector<vector<double>> omiga_group;

	vector<double> AOmiga(vector<vector<double>> A, vector<double> omiga_matrix);

	//综合评价集隶属度
	vector<vector<double>> b_group;

	//一致性指标表
	double n_RI[11] = { 0,0,0.58,0.90,1.12,1.24,1.32,1.41,1.45,1.49,1.51 };

	//计算S评分
	double ComputeS(vector<double> b);

	//综合评分
	vector<double> s_group;
	double totle;
};

FAHP::FAHP(vector<vector<vector<double>>> flod, vector<vector<vector<double>>> matrix_proup)
{
	flod_proup = flod;
	r_group = matrix_proup;
	normal_flod_proup = flod_proup;
	ComputeOmiga();
}

bool FAHP::GetConsiste() const
{
	return consiste;
}

void FAHP::ComputeOmiga()
{
	for (int b = 0; b < flod_proup.size(); b++)
	{
		for (int i = 0; i < flod_proup.at(b).size(); i++)
		{
			double sum = 0;
			for (int j = 0; j < flod_proup.at(b).size(); j++)
			{
				sum += flod_proup.at(b).at(j).at(i);
			}
			for (int j = 0; j < flod_proup.at(b).size(); j++)
			{
				normal_flod_proup.at(b).at(j).at(i) = flod_proup.at(b).at(j).at(i) / sum;
			}
		}
		vector<double> tem1;
		for (int i = 0; i < flod_proup.at(b).size(); i++)
		{
			double sum = 0;
			for (int j = 0; j < flod_proup.at(b).size(); j++)
			{
				sum += normal_flod_proup.at(b).at(i).at(j);
			}
			tem1.push_back(sum);
		}
		double tem2 = 0;
		for (auto i : tem1)
		{
			tem2 += i;
		}
		for (int i = 0; i < tem1.size(); i++)
		{
			tem1[i] = tem1.at(i) / tem2;
		}
		omiga_group.push_back(tem1);
	}
	ConsistencyTest();
}

void FAHP::ComputeB()
{
	for (int i = 1; i < omiga_group.size(); i++)
	{
		vector<double> tem1;
		for (int j = 0; j < r_group.at(i - 1).at(0).size(); j++)
		{
			double sum = 0;
			for (int k = 0; k < omiga_group.at(i).size(); k++)
			{
				sum += omiga_group.at(i).at(k) * r_group.at(i - 1).at(k).at(j);
			}
			tem1.push_back(sum / 100);
		}
		b_group.push_back(tem1);
		double tem2 = ComputeS(tem1);
		s_group.push_back(tem2);
	}
	ComputeTotle();
}

void FAHP::ComputeTotle()
{
	vector<double> temS;
	for (int i = 0; i < b_group.at(0).size(); i++)
	{
		double sum = 0;
		for (int j = 0; j < b_group.size(); j++)
		{
			sum += omiga_group.at(0).at(j) * b_group.at(j).at(i);
		}
		temS.push_back(sum);
	}

	totle = ComputeS(temS);
}

void FAHP::PrintScore()
{
	for (int i = 0; i < s_group.size(); i++)
	{
		printf_s("%.4f ", s_group.at(i));
	}
	printf_s("%.4f", totle);
}

void FAHP::ConsistencyTest()
{
	consiste = true;
	for (int i = 0; i < flod_proup.size(); i++)
	{
		vector<double> a_m_moiga = AOmiga(flod_proup.at(i), omiga_group.at(i));
		double tem1 = 0;
		for (int j = 0; j < omiga_group.at(i).size(); j++)
		{
			tem1 += a_m_moiga.at(j) / omiga_group.at(i).at(j);
		}
		tem1 = tem1 / omiga_group.at(i).size();
		double CI = (tem1 - omiga_group.at(i).size()) / (omiga_group.at(i).size() - 1);
		if (CI / n_RI[omiga_group.at(i).size()] > 0.1)
		{
			consiste = false;
		}
	}
}

vector<double> FAHP::AOmiga(vector<vector<double>> A, vector<double> omiga_matrix)
{
	vector<double> res;
	for (int i = 0; i < A.size(); i++)
	{
		double tem = 0;
		for (int j = 0; j < A.size(); j++)
		{
			tem += A.at(i).at(j) * omiga_matrix.at(j);
		}
		res.push_back(tem);
	}
	return res;
}

double FAHP::ComputeS(vector<double> b)
{
	double sum = 0;
	for (int i = 5; i > 0; i--)
	{
		sum += b.at(5 - i) * i;
	}
	return sum;
}

int main()
{
	int n[4];
	vector<vector<vector<double>>> matrix_bag1;

	for (int b = 0; b < 4; b++)
	{
		cin >> n[b];
		if (n[b] == 0)
		{
			cout << "There are judgment matrices that fail the consistency check";
			return 0;
		}
		vector<vector<double>> tem3;
		for (int i = 0; i < n[b]; i++)
		{
			vector<double> tem1;
			for (int j = 0; j < n[b]; j++)
			{
				double tem2;
				cin >> tem2;
				tem1.push_back(tem2);
			}
			tem3.push_back(tem1);
		}
		matrix_bag1.push_back(tem3);
	}

	vector<vector<vector<double>>> matrix_bag2;
	for (int b = 0; b < 3; b++)
	{
		vector<vector<double>> tem3;
		for (int i = 0; i < n[b + 1]; i++)
		{
			vector<double> tem1;
			for (int j = 0; j < 5; j++)
			{
				double tem2;
				cin >> tem2;
				tem1.push_back(tem2);
			}
			tem3.push_back(tem1);
		}
		matrix_bag2.push_back(tem3);
	}

	FAHP* a = new FAHP(matrix_bag1, matrix_bag2);
	if (!a->GetConsiste())
	{
		cout << "There are judgment matrices that fail the consistency check";
		return 0;
	}
	else
	{
		cout << "The judgment matrix has passed the consistency test" << endl;
	}
	a->ComputeB();
	a->PrintScore();

	return 0;
}

这一次写的时候有点不在状态,导致好像重复造轮子了,不过勉强能运行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值