weight.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. ##################################################################
  4. #
  5. # Copyright (c) 2023 CICV, Inc. All Rights Reserved
  6. #
  7. ##################################################################
  8. """
  9. @Authors: zhanghaiwen(zhanghaiwen@china-icv.cn), yangzihao(yangzihao@china-icv.cn)
  10. @Data: 2024/01/12
  11. @Last Modified: 2024/01/12
  12. @Summary: Weight cal
  13. """
  14. import numpy as np
  15. from functools import reduce
  16. def cal_weight_from_80(score_list):
  17. # weight process
  18. s_list = [80.1 if x == 80 else x for x in score_list]
  19. weight_list = abs((np.array(s_list) - 80) / 100)
  20. # normalization
  21. weight_list = weight_list / sum(weight_list)
  22. return weight_list
  23. class AHP:
  24. def __init__(self, matrix):
  25. self.A = np.array(matrix)
  26. self.n = len(matrix)
  27. def _get_consistency_ratio(self, w_max):
  28. RI = [0, 0, 0.0001, 0.52, 0.89, 1.12, 1.26, 1.36,
  29. 1.41, 1.46, 1.49, 1.52, 1.54, 1.56, 1.58, 1.59,
  30. 1.5943, 1.6064, 1.6133, 1.6207, 1.6292]
  31. CI = (w_max - self.n) / (self.n - 1)
  32. CR = CI / RI[self.n]
  33. return CR
  34. def get_weights(self, method='eigenvalue'):
  35. # Check consistency of pairwise comparison matrix
  36. w, v = np.linalg.eig(self.A)
  37. w_index = np.argmax(w)
  38. w_max = np.real(w[w_index])
  39. cr = self._get_consistency_ratio(w_max)
  40. if cr > 0.1:
  41. raise ValueError('The pairwise comparison matrix is inconsistent.')
  42. # Normalize matrix
  43. line_sum = [sum(m) for m in zip(*self.A)]
  44. D = np.zeros((self.n, self.n))
  45. for i in range(self.n):
  46. for j in range(self.n):
  47. D[i][j] = self.A[i][j] / line_sum[j]
  48. # Calculate weights with selected method
  49. if method == 'arithmetic':
  50. weights = np.zeros(self.n)
  51. for i in range(self.n):
  52. weights[i] = np.average(D[i])
  53. elif method == 'geometric':
  54. weights = np.zeros(self.n)
  55. for i in range(self.n):
  56. weights[i] = reduce(lambda x, y: x * y, self.A[i])
  57. weights[i] = pow(weights[i], 1 / self.n)
  58. weights = [e / np.sum(weights) for e in weights]
  59. elif method == 'eigenvalue':
  60. weights = np.zeros(self.n)
  61. v_index = np.argmax(v)
  62. v_max = np.real(v[:, v_index])
  63. weights = [e / np.sum(v_max) for e in v_max]
  64. return weights