Opricovic于1998年提出了VIKOR决策方法,它是一种折衷排序方法,通过最大化群效用和最小化个体遗憾值对有限决策方案进行折衷排序。VIKOR方法是多准则决策(MCDM)的有效工具,用于以下情形:
VIKOR方法的基本上思想是:确定正理想解(PIS)与负理想解(NIS),然后比较待选方案的评估值,根据其于理想指标值的距离大小择优。其中,正理想解是各评价准则中的最优值,而负理想解则是各评价准则中的最差值。
VIKOR方法基于以下形式的测度: $$ L_{p}=\left\{\sum_{j=1}^{n}\left[\frac{\omega_{j}\left(f_{j}^{*}-f_{j i}\right)}{\left(f_{j}^{*}-f_{j}^{-}\right)}\right]\right\}^{\frac{1}{P}} $$ 其中, $1 \leq P \leq \infty, i=1,2, \cdots, m , \omega_{j}$ 为评价属性权重, $f_{j}^{*}$ 与 $f_{j}^{*}$ 分别表示正理想值与负理想值。
记
标准化处理是为了消除量纲对最终结果的影响,使不同变量具有可比性。决策指标包含效益型指标和成本型指标。效益型指标是正向化指标,数值越大表示决策者对该项越满意;成本型指标属于负向化指标,其数值越大决策者对该指标的满意度越低。
标准化处理公式: 令 $x_{i j}$ 为决策指标, $r_{i j}$ 为指标标准化后的结果, 则: 若 $x_{i j}$ 为效益型指标, $$ r_{i j}=\left(x_{i j}-x_{i j}^{-}\right) /\left(x_{i j}^{*}-x_{i j}^{-}\right) $$ 若 $x_{i j}$ 为成本型指标, $$ r_{i j}=\left(x_{i j}^{*}-x_{i j}\right) /\left(x_{i j}^{*}-x_{i j}^{-}\right) $$ 其中, $\quad x_{i j}^{*}=\max _{1 \leq i \leq m} x_{i j}, \quad x_{i j}^{-}=\min _{1 \leq i \leq m} x_{i j}$ 。
令 $b_{j}^{*}$ 与 $b_{j}^{-}$为标准化矩阵 StandardMatrix 中每列的最大和最小值, 有 $$ \begin{aligned} &b{j}^{}=\max {1 \leq i \leq m} b{i j} \ &b{j}^{-}=\min {1 \leq i \leq m} b{i j} \end{aligned} $$ 计算群体效用值 $S{i}$ 和个体遗憾值 $R{i}$. $$ \begin{gathered} S{i}=\sum{i=1}^{n} \omega{j}\left(b_{j}^{}-b{i j}\right) /\left(b{j}^{}-b{j}^{-}\right) \ R{i}=\max {1 \leq j \leq n}\left[\omega{j}\left(b_{j}^{}-b{i j}\right) /\left(b{j}^{*}-b_{j}^{-}\right)\right] \end{gathered} $$
根据群体效用值与个体遗憾值的结果,在此基础上计算决策指标的值,指标值越小方案越优。
$$ Q_{i}=\frac{v\left(S_{i}-S^{*}\right)}{S^{-}-S^{*}}+\frac{(1-v)\left(R_{i}-R^{*}\right)}{R^{-}-R^{*}} $$其中, $S^{*}=\min _{1 \leq i \leq m} S_{i}, S^{-}=\max _{1 \leq i \leq m} S_{i}, \quad R^{*}=\min _{1 \leq i \leq m} R_{i}, R^{*}=\max _{1 \leq i \leq m} R_{i}$; $v$ 表示为决策机制系数,如果 $v>0.5$ ,则表示根据最大化群体效应决策机制决策; 如果 $v<0.5$ ,则表示根据最小化个体遗憾值的决策机制决策; 如果 $v=0.5$, 则表示根据协商达成最大群体效应和最小个体遗憾值同等重要的决策机制 进行决策。
最终,可以得到各方案的指标值,而指标值越小越好,将指标进行升序排列得到各方案的排序结果。
评价指标体系:
具体论文参考:https://mp.weixin.qq.com/s/ELuH_sT2X74DzU9omcUkrg
from numpy import *
import matplotlib.pyplot as plt
# Step 1: determine the best and worst values for all
# criteria functions
def best_worst_fij(a, b):
"""
a is the array with the performances and b is
the criteria min/max array
"""
f = zeros((b.shape[0], 2))
for i in range(b.shape[0]):
if b[i] == 'max':
f[i, 0] = a.max(0)[i]
f[i, 1] = a.min(0)[i]
elif b[i] == 'min':
f[i, 0] = a.min(0)[i]
f[i, 1] = a.max(0)[i]
return f
# Step 2: compute the values S_i and R_i
def SR(a, b, c):
"""
a is the array with the performances, b is the
array with the best and worst performances, and
c is the criteria min/max array
"""
s = zeros(a.shape[0])
r = zeros(a.shape[0])
for i in range(a.shape[0]):
k = 0
o = 0
for j in range(a.shape[1]):
k = k + c[j] * (b[j, 0] - a[i, j]) \
/ (b[j, 0] - b[j, 1])
u = c[j] * (b[j, 0] - a[i, j]) \
/ (b[j, 0] - b[j, 1])
if u > o:
o = u
r[i] = round(o, 3)
else:
r[i] = round(o, 3)
s[i] = round(k, 3)
return s, r
# Step 3: compute the values Q_i
def Q(s, r, n):
"""
s is the vector with the S_i values, r is
the vector with the R_i values, and n is the
number of criteria
"""
q = zeros(s.shape[0])
for i in range(s.shape[0]):
q[i] = round((((n + 1) / (2 * n)) *
(s[i] - min(s)) / (max(s) - min(s)) +
(1 - (n + 1) / (2 * n)) *
(r[i] - min(r)) / (max(r) - min(r))), 3)
return q
# VIKOR method: it calls the other functions
def vikor(a, b, c, pl):
""" a is the decision matrix, b is the criteria
min/max array, c is the weights matrix, and pl
is 'y' for plotting the results or any other
string for not
"""
s, r = SR(a, best_worst_fij(a, b), c)
q = Q(s, r, len(c))
if pl == 'y':
e = [i + 1 for i in range(a.shape[0])]
plt.plot(e, s, 'p--', color = 'red',
markeredgewidth = 2, markersize = 8)
plt.text(0.02, 0.5, '123', fontsize=14)
plt.plot(e, r, '*--', color = 'blue',
markeredgewidth = 2, markersize=8)
plt.plot(e, q, 'o--', color = 'green',
markeredgewidth = 2, markersize = 8)
# plt.legend(['S', 'R', 'Q'])
plt.xticks(range(a.shape[0] + 2))
plt.axis([0, a.shape[0] + 1, 0,
max(maximum(maximum(s, r), q)) + 0.3])
plt.title("VIKOR results")
text = "Alternatives \n s:{} \n r:{}\n q:{}".format(s,r,q)
plt.xlabel("Alternatives")
plt.legend(['S', 'R', 'Q'])
plt.grid(True)
plt.show()
plt.savefig('test.png')
return s, r, q
# performances of the alternatives
x = array([[8, 7, 2, 1], [5, 3, 7, 5], [7, 5, 6, 4],
[9, 9, 7, 3], [11, 10, 3, 7], [6, 9, 5, 4],[6, 9, 5, 4]])
# weights of the criteria
w = array([0.4, 0.3, 0.1, 0.2])
# criteria max/min
crit_max_min = array(['max', 'max', 'max', 'max'])
# final results
vikor(x, crit_max_min, w, 'n')
s, r, q = vikor(x, crit_max_min, w, 'y')
print("S = ", s)
print("R = ", r)
print("Q = ", q)
参考资料
from numpy import *
import matplotlib.pyplot as plt
# Step 1: determine the best and worst values for all
# criteria functions
def best_worst_fij(a, b):
"""
a is the array with the performances and b is
the criteria min/max array
"""
f = zeros((b.shape[0], 2))
for i in range(b.shape[0]):
if b[i] == 'max':
f[i, 0] = a.max(0)[i]
f[i, 1] = a.min(0)[i]
elif b[i] == 'min':
f[i, 0] = a.min(0)[i]
f[i, 1] = a.max(0)[i]
return f
# Step 2: compute the values S_i and R_i
def SR(a, b, c):
"""
a is the array with the performances, b is the
array with the best and worst performances, and
c is the criteria min/max array
"""
s = zeros(a.shape[0])
r = zeros(a.shape[0])
for i in range(a.shape[0]):
k = 0
o = 0
for j in range(a.shape[1]):
k = k + c[j] * (b[j, 0] - a[i, j]) \
/ (b[j, 0] - b[j, 1])
u = c[j] * (b[j, 0] - a[i, j]) \
/ (b[j, 0] - b[j, 1])
if u > o:
o = u
r[i] = round(o, 3)
else:
r[i] = round(o, 3)
s[i] = round(k, 3)
return s, r
# Step 3: compute the values Q_i
def Q(s, r, n):
"""
s is the vector with the S_i values, r is
the vector with the R_i values, and n is the
number of criteria
"""
q = zeros(s.shape[0])
for i in range(s.shape[0]):
q[i] = round((((n + 1) / (2 * n)) *
(s[i] - min(s)) / (max(s) - min(s)) +
(1 - (n + 1) / (2 * n)) *
(r[i] - min(r)) / (max(r) - min(r))), 3)
return q
# VIKOR method: it calls the other functions
def vikor(a, b, c, pl):
""" a is the decision matrix, b is the criteria
min/max array, c is the weights matrix, and pl
is 'y' for plotting the results or any other
string for not
"""
s, r = SR(a, best_worst_fij(a, b), c)
q = Q(s, r, len(c))
if pl == 'y':
e = [i + 1 for i in range(a.shape[0])]
plt.plot(e, s, 'p--', color = 'red',
markeredgewidth = 2, markersize = 8)
plt.text(0.02, 0.5, '123', fontsize=14)
plt.plot(e, r, '*--', color = 'blue',
markeredgewidth = 2, markersize=8)
plt.plot(e, q, 'o--', color = 'green',
markeredgewidth = 2, markersize = 8)
# plt.legend(['S', 'R', 'Q'])
plt.xticks(range(a.shape[0] + 2))
plt.axis([0, a.shape[0] + 1, 0,
max(maximum(maximum(s, r), q)) + 0.3])
plt.title("VIKOR results")
text = "Alternatives \n s:{} \n r:{}\n q:{}".format(s,r,q)
plt.xlabel("Alternatives")
plt.legend(['S', 'R', 'Q'])
plt.grid(True)
plt.show()
plt.savefig('test.png')
return s, r, q
# performances of the alternatives
x = array([[8, 7, 2, 1], [5, 3, 7, 5], [7, 5, 6, 4],
[9, 9, 7, 3], [11, 10, 3, 7], [6, 9, 5, 4],[6, 9, 5, 4]])
# weights of the criteria
w = array([0.4, 0.3, 0.1, 0.2])
# criteria max/min
crit_max_min = array(['max', 'max', 'max', 'max'])
# final results
vikor(x, crit_max_min, w, 'n')
s, r, q = vikor(x, crit_max_min, w, 'y')
print("S = ", s)
print("R = ", r)
print("Q = ", q)
S = [0.629 0.767 0.601 0.31 0.08 0.516 0.516] R = [0.2 0.4 0.267 0.133 0.08 0.333 0.333] Q = [0.64 1. 0.693 0.271 0. 0.693 0.693]