#!/usr/bin/env python # -*- coding: utf-8 -*- ################################################################## # # Copyright (c) 2023 CICV, Inc. All Rights Reserved # ################################################################## """ @Authors: zhanghaiwen(zhanghaiwen@china-icv.cn), yangzihao(yangzihao@china-icv.cn) @Data: 2024/01/12 @Last Modified: 2024/01/12 @Summary: Weight cal """ import numpy as np from functools import reduce def cal_weight_from_80(score_list): # weight process s_list = [80.1 if x == 80 else x for x in score_list] weight_list = abs((np.array(s_list) - 80) / 100) # normalization weight_list = weight_list / sum(weight_list) return weight_list class AHP: def __init__(self, matrix): self.A = np.array(matrix) self.n = len(matrix) def _get_consistency_ratio(self, w_max): RI = [0, 0, 0.0001, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41, 1.46, 1.49, 1.52, 1.54, 1.56, 1.58, 1.59, 1.5943, 1.6064, 1.6133, 1.6207, 1.6292] CI = (w_max - self.n) / (self.n - 1) CR = CI / RI[self.n] return CR def get_weights(self, method='eigenvalue'): # Check consistency of pairwise comparison matrix w, v = np.linalg.eig(self.A) w_index = np.argmax(w) w_max = np.real(w[w_index]) cr = self._get_consistency_ratio(w_max) if cr > 0.1: raise ValueError('The pairwise comparison matrix is inconsistent.') # Normalize matrix line_sum = [sum(m) for m in zip(*self.A)] D = np.zeros((self.n, self.n)) for i in range(self.n): for j in range(self.n): D[i][j] = self.A[i][j] / line_sum[j] # Calculate weights with selected method if method == 'arithmetic': weights = np.zeros(self.n) for i in range(self.n): weights[i] = np.average(D[i]) elif method == 'geometric': weights = np.zeros(self.n) for i in range(self.n): weights[i] = reduce(lambda x, y: x * y, self.A[i]) weights[i] = pow(weights[i], 1 / self.n) weights = [e / np.sum(weights) for e in weights] elif method == 'eigenvalue': weights = np.zeros(self.n) v_index = np.argmax(v) v_max = np.real(v[:, v_index]) weights = [e / np.sum(v_max) for e in v_max] return weights