pydecision 4.5.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyDecision/__init__.py +1 -0
- pyDecision/algorithm/__init__.py +80 -0
- pyDecision/algorithm/ahp.py +35 -0
- pyDecision/algorithm/aras.py +65 -0
- pyDecision/algorithm/borda.py +51 -0
- pyDecision/algorithm/bwm.py +63 -0
- pyDecision/algorithm/bwm_s.py +32 -0
- pyDecision/algorithm/cilos.py +35 -0
- pyDecision/algorithm/cocoso.py +67 -0
- pyDecision/algorithm/codas.py +65 -0
- pyDecision/algorithm/copeland.py +65 -0
- pyDecision/algorithm/copras.py +61 -0
- pyDecision/algorithm/cradis.py +58 -0
- pyDecision/algorithm/critic.py +29 -0
- pyDecision/algorithm/dematel.py +64 -0
- pyDecision/algorithm/e_i.py +224 -0
- pyDecision/algorithm/e_i_s.py +213 -0
- pyDecision/algorithm/e_i_v.py +223 -0
- pyDecision/algorithm/e_ii.py +404 -0
- pyDecision/algorithm/e_iii.py +289 -0
- pyDecision/algorithm/e_iv.py +295 -0
- pyDecision/algorithm/e_tri_b.py +264 -0
- pyDecision/algorithm/edas.py +64 -0
- pyDecision/algorithm/entropy.py +28 -0
- pyDecision/algorithm/fucom.py +50 -0
- pyDecision/algorithm/fuzzy_ahp.py +44 -0
- pyDecision/algorithm/fuzzy_ahp_ppf.py +70 -0
- pyDecision/algorithm/fuzzy_aras.py +78 -0
- pyDecision/algorithm/fuzzy_bwm.py +133 -0
- pyDecision/algorithm/fuzzy_copras.py +110 -0
- pyDecision/algorithm/fuzzy_critic.py +45 -0
- pyDecision/algorithm/fuzzy_dematel.py +86 -0
- pyDecision/algorithm/fuzzy_edas.py +108 -0
- pyDecision/algorithm/fuzzy_fucom.py +122 -0
- pyDecision/algorithm/fuzzy_merec.py +41 -0
- pyDecision/algorithm/fuzzy_moora.py +83 -0
- pyDecision/algorithm/fuzzy_ocra.py +93 -0
- pyDecision/algorithm/fuzzy_topsis.py +101 -0
- pyDecision/algorithm/fuzzy_vikor.py +129 -0
- pyDecision/algorithm/fuzzy_waspas.py +93 -0
- pyDecision/algorithm/gra.py +54 -0
- pyDecision/algorithm/idocriw.py +60 -0
- pyDecision/algorithm/mabac.py +62 -0
- pyDecision/algorithm/macbeth.py +58 -0
- pyDecision/algorithm/mairca.py +66 -0
- pyDecision/algorithm/mara.py +68 -0
- pyDecision/algorithm/marcos.py +77 -0
- pyDecision/algorithm/maut.py +102 -0
- pyDecision/algorithm/merec.py +31 -0
- pyDecision/algorithm/moora.py +63 -0
- pyDecision/algorithm/moosra.py +63 -0
- pyDecision/algorithm/multimoora.py +90 -0
- pyDecision/algorithm/ocra.py +63 -0
- pyDecision/algorithm/opa.py +117 -0
- pyDecision/algorithm/oreste.py +59 -0
- pyDecision/algorithm/p_ec.py +308 -0
- pyDecision/algorithm/p_i.py +176 -0
- pyDecision/algorithm/p_ii.py +121 -0
- pyDecision/algorithm/p_iii.py +176 -0
- pyDecision/algorithm/p_iv.py +107 -0
- pyDecision/algorithm/p_v.py +145 -0
- pyDecision/algorithm/p_vi.py +160 -0
- pyDecision/algorithm/p_xgaia.py +137 -0
- pyDecision/algorithm/piv.py +53 -0
- pyDecision/algorithm/psi.py +57 -0
- pyDecision/algorithm/psi_m.py +21 -0
- pyDecision/algorithm/rafsi.py +79 -0
- pyDecision/algorithm/regime.py +120 -0
- pyDecision/algorithm/roc.py +30 -0
- pyDecision/algorithm/rov.py +62 -0
- pyDecision/algorithm/rrw.py +31 -0
- pyDecision/algorithm/rsw.py +29 -0
- pyDecision/algorithm/saw.py +53 -0
- pyDecision/algorithm/seca.py +49 -0
- pyDecision/algorithm/smart.py +57 -0
- pyDecision/algorithm/spotis.py +54 -0
- pyDecision/algorithm/todim.py +67 -0
- pyDecision/algorithm/topsis.py +65 -0
- pyDecision/algorithm/vikor.py +85 -0
- pyDecision/algorithm/waspas.py +67 -0
- pyDecision/algorithm/wings.py +58 -0
- pyDecision/algorithm/wisp.py +81 -0
- pyDecision/compare/__init__.py +1 -0
- pyDecision/compare/compare.py +539 -0
- pyDecision/util/LLM.py +171 -0
- pyDecision/util/__init__.py +2 -0
- pyDecision/util/ga.py +124 -0
- pydecision-4.5.9.dist-info/LICENSE +14 -0
- pydecision-4.5.9.dist-info/METADATA +177 -0
- pydecision-4.5.9.dist-info/RECORD +92 -0
- pydecision-4.5.9.dist-info/WHEEL +5 -0
- pydecision-4.5.9.dist-info/top_level.txt +1 -0
pyDecision/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from .ahp import ahp_method
|
|
2
|
+
from .aras import aras_method
|
|
3
|
+
from .borda import borda_method
|
|
4
|
+
from .bwm import bw_method
|
|
5
|
+
from .bwm_s import simplified_bw_method
|
|
6
|
+
from .cilos import cilos_method
|
|
7
|
+
from .cocoso import cocoso_method
|
|
8
|
+
from .codas import codas_method
|
|
9
|
+
from .copeland import copeland_method
|
|
10
|
+
from .copras import copras_method
|
|
11
|
+
from .cradis import cradis_method
|
|
12
|
+
from .critic import critic_method
|
|
13
|
+
from .dematel import dematel_method
|
|
14
|
+
from .e_i import electre_i
|
|
15
|
+
from .e_i_s import electre_i_s
|
|
16
|
+
from .e_i_v import electre_i_v
|
|
17
|
+
from .e_ii import electre_ii
|
|
18
|
+
from .e_iii import electre_iii
|
|
19
|
+
from .e_iv import electre_iv
|
|
20
|
+
from .e_tri_b import electre_tri_b
|
|
21
|
+
from .edas import edas_method
|
|
22
|
+
from .entropy import entropy_method
|
|
23
|
+
from .fucom import fucom_method
|
|
24
|
+
from .fuzzy_ahp import fuzzy_ahp_method
|
|
25
|
+
from .fuzzy_ahp_ppf import ppf_ahp_method
|
|
26
|
+
from .fuzzy_aras import fuzzy_aras_method
|
|
27
|
+
from .fuzzy_bwm import fuzzy_bw_method
|
|
28
|
+
from .fuzzy_copras import fuzzy_copras_method
|
|
29
|
+
from .fuzzy_critic import fuzzy_critic_method
|
|
30
|
+
from .fuzzy_dematel import fuzzy_dematel_method
|
|
31
|
+
from .fuzzy_edas import fuzzy_edas_method
|
|
32
|
+
from .fuzzy_fucom import fuzzy_fucom_method
|
|
33
|
+
from .fuzzy_merec import fuzzy_merec_method
|
|
34
|
+
from .fuzzy_moora import fuzzy_moora_method
|
|
35
|
+
from .fuzzy_ocra import fuzzy_ocra_method
|
|
36
|
+
from .fuzzy_topsis import fuzzy_topsis_method
|
|
37
|
+
from .fuzzy_vikor import fuzzy_vikor_method
|
|
38
|
+
from .fuzzy_waspas import fuzzy_waspas_method
|
|
39
|
+
from .gra import gra_method
|
|
40
|
+
from .idocriw import idocriw_method
|
|
41
|
+
from .mabac import mabac_method
|
|
42
|
+
from .macbeth import macbeth_method
|
|
43
|
+
from .mairca import mairca_method
|
|
44
|
+
from .mara import mara_method
|
|
45
|
+
from .marcos import marcos_method
|
|
46
|
+
from .maut import maut_method
|
|
47
|
+
from .merec import merec_method
|
|
48
|
+
from .moora import moora_method
|
|
49
|
+
from .moosra import moosra_method
|
|
50
|
+
from .multimoora import multimoora_method
|
|
51
|
+
from .ocra import ocra_method
|
|
52
|
+
from .opa import opa_method
|
|
53
|
+
from .oreste import oreste_method
|
|
54
|
+
from .p_ec import ec_promethee, solution_p_ranking, plot_rank_freq, find_column_modes
|
|
55
|
+
from .p_i import promethee_i
|
|
56
|
+
from .p_ii import promethee_ii
|
|
57
|
+
from .p_iii import promethee_iii
|
|
58
|
+
from .p_iv import promethee_iv
|
|
59
|
+
from .p_v import promethee_v
|
|
60
|
+
from .p_vi import promethee_vi
|
|
61
|
+
from .p_xgaia import promethee_gaia
|
|
62
|
+
from .piv import piv_method
|
|
63
|
+
from .psi import psi_method
|
|
64
|
+
from .psi_m import mpsi_method
|
|
65
|
+
from .rafsi import rafsi_method
|
|
66
|
+
from .regime import regime_method
|
|
67
|
+
from .roc import roc_method
|
|
68
|
+
from .rov import rov_method
|
|
69
|
+
from .rrw import rrw_method
|
|
70
|
+
from .rsw import rsw_method
|
|
71
|
+
from .saw import saw_method
|
|
72
|
+
from .seca import seca_method
|
|
73
|
+
from .smart import smart_method
|
|
74
|
+
from .spotis import spotis_method
|
|
75
|
+
from .todim import todim_method
|
|
76
|
+
from .topsis import topsis_method
|
|
77
|
+
from .vikor import vikor_method, ranking
|
|
78
|
+
from .waspas import waspas_method
|
|
79
|
+
from .wisp import wisp_method
|
|
80
|
+
from .wings import wings_method
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import numpy as np
|
|
5
|
+
from functools import reduce
|
|
6
|
+
|
|
7
|
+
###############################################################################
|
|
8
|
+
|
|
9
|
+
# Function: AHP (Analytic Hierarchy Process)
|
|
10
|
+
def ahp_method(dataset, wd = 'm'):
|
|
11
|
+
inc_rat = np.array([0, 0, 0, 0.58, 0.9, 1.12, 1.24, 1.32, 1.41, 1.45, 1.49, 1.51, 1.48, 1.56, 1.57, 1.59])
|
|
12
|
+
X = np.copy(dataset)
|
|
13
|
+
weights = np.zeros(X.shape[1])
|
|
14
|
+
if (wd == 'm' or wd == 'mean'):
|
|
15
|
+
weights = np.mean(X/np.sum(X, axis = 0), axis = 1)
|
|
16
|
+
vector = np.sum(X*weights, axis = 1)/weights
|
|
17
|
+
lamb_max = np.mean(vector)
|
|
18
|
+
elif (wd == 'g' or wd == 'geometric'):
|
|
19
|
+
for i in range (0, X.shape[1]):
|
|
20
|
+
weights[i] = reduce( (lambda x, y: x * y), X[i,:])**(1/X.shape[1])
|
|
21
|
+
weights = weights/np.sum(weights)
|
|
22
|
+
vector = np.sum(X*weights, axis = 1)/weights
|
|
23
|
+
lamb_max = np.mean(vector)
|
|
24
|
+
elif (wd == 'me' or wd == 'max_eigen'):
|
|
25
|
+
eigenvalues, eigenvectors = np.linalg.eig(X)
|
|
26
|
+
eigenvalues_real = np.real(eigenvalues)
|
|
27
|
+
lamb_max_index = np.argmax(eigenvalues_real)
|
|
28
|
+
lamb_max = eigenvalues_real[lamb_max_index]
|
|
29
|
+
principal_eigenvector = np.real(eigenvectors[:, lamb_max_index])
|
|
30
|
+
weights = principal_eigenvector / principal_eigenvector.sum()
|
|
31
|
+
cons_ind = (lamb_max - X.shape[1])/(X.shape[1] - 1)
|
|
32
|
+
rc = cons_ind/inc_rat[X.shape[1]]
|
|
33
|
+
return weights, rc
|
|
34
|
+
|
|
35
|
+
###############################################################################
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
###############################################################################
|
|
8
|
+
|
|
9
|
+
# Function: Rank
|
|
10
|
+
def ranking(flow):
|
|
11
|
+
rank_xy = np.zeros((flow.shape[0], 2))
|
|
12
|
+
for i in range(0, rank_xy.shape[0]):
|
|
13
|
+
rank_xy[i, 0] = 0
|
|
14
|
+
rank_xy[i, 1] = flow.shape[0]-i
|
|
15
|
+
for i in range(0, rank_xy.shape[0]):
|
|
16
|
+
plt.text(rank_xy[i, 0], rank_xy[i, 1], 'a' + str(int(flow[i,0])), size = 12, ha = 'center', va = 'center', bbox = dict(boxstyle = 'round', ec = (0.0, 0.0, 0.0), fc = (0.8, 1.0, 0.8),))
|
|
17
|
+
for i in range(0, rank_xy.shape[0]-1):
|
|
18
|
+
plt.arrow(rank_xy[i, 0], rank_xy[i, 1], rank_xy[i+1, 0] - rank_xy[i, 0], rank_xy[i+1, 1] - rank_xy[i, 1], head_width = 0.01, head_length = 0.2, overhang = 0.0, color = 'black', linewidth = 0.9, length_includes_head = True)
|
|
19
|
+
axes = plt.gca()
|
|
20
|
+
axes.set_xlim([-1, +1])
|
|
21
|
+
ymin = np.amin(rank_xy[:,1])
|
|
22
|
+
ymax = np.amax(rank_xy[:,1])
|
|
23
|
+
if (ymin < ymax):
|
|
24
|
+
axes.set_ylim([ymin, ymax])
|
|
25
|
+
else:
|
|
26
|
+
axes.set_ylim([ymin-1, ymax+1])
|
|
27
|
+
plt.axis('off')
|
|
28
|
+
plt.show()
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
# Function: ARAS (Additive Ratio Assessment)
|
|
32
|
+
def aras_method(dataset, weights, criterion_type, graph = True, verbose = True):
|
|
33
|
+
X = np.copy(dataset)/1.0
|
|
34
|
+
bst = np.zeros(X.shape[1])
|
|
35
|
+
bsm = np.zeros(X.shape[1])
|
|
36
|
+
for j in range(0, X.shape[1]):
|
|
37
|
+
if ( criterion_type[j] == 'max'):
|
|
38
|
+
bst[j] = np.max(X[:, j])
|
|
39
|
+
bsm[j] = bst[j] + np.sum(X[:, j])
|
|
40
|
+
elif ( criterion_type[j] == 'min'):
|
|
41
|
+
bst[j] = 1/np.min(X[:, j])
|
|
42
|
+
X[:,j] = 1/X[:, j]
|
|
43
|
+
bsm[j] = bst[j] + np.sum(X[:, j])
|
|
44
|
+
for j in range(0, X.shape[1]):
|
|
45
|
+
bst[j] = bst[j]/ bsm[j]
|
|
46
|
+
for i in range(0, X.shape[0]):
|
|
47
|
+
X[i, j] = X[i, j]/ bsm[j]
|
|
48
|
+
X = X * weights
|
|
49
|
+
bst = bst * weights
|
|
50
|
+
n_0 = np.sum(bst)
|
|
51
|
+
n_i = np.sum(X, axis = 1)
|
|
52
|
+
k_i = n_i/n_0
|
|
53
|
+
flow = np.copy(k_i)
|
|
54
|
+
flow = np.reshape(flow, (k_i.shape[0], 1))
|
|
55
|
+
flow = np.insert(flow, 0, list(range(1, k_i.shape[0]+1)), axis = 1)
|
|
56
|
+
if (verbose == True):
|
|
57
|
+
for i in range(0, flow.shape[0]):
|
|
58
|
+
print('a' + str(int(flow[i,0])) + ': ' + str(round(flow[i,1], 3)))
|
|
59
|
+
if (graph == True):
|
|
60
|
+
flow = flow[np.argsort(flow[:, 1])]
|
|
61
|
+
flow = flow[::-1]
|
|
62
|
+
ranking(flow)
|
|
63
|
+
return flow
|
|
64
|
+
|
|
65
|
+
###############################################################################
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
###############################################################################
|
|
8
|
+
|
|
9
|
+
# Function: Rank
|
|
10
|
+
def ranking(flow):
|
|
11
|
+
rank_xy = np.zeros((flow.shape[0], 2))
|
|
12
|
+
for i in range(0, rank_xy.shape[0]):
|
|
13
|
+
rank_xy[i, 0] = 0
|
|
14
|
+
rank_xy[i, 1] = flow.shape[0]-i
|
|
15
|
+
for i in range(0, rank_xy.shape[0]):
|
|
16
|
+
plt.text(rank_xy[i, 0], rank_xy[i, 1], 'a' + str(int(flow[i,0])), size = 12, ha = 'center', va = 'center', bbox = dict(boxstyle = 'round', ec = (0.0, 0.0, 0.0), fc = (0.8, 1.0, 0.8),))
|
|
17
|
+
for i in range(0, rank_xy.shape[0]-1):
|
|
18
|
+
plt.arrow(rank_xy[i, 0], rank_xy[i, 1], rank_xy[i+1, 0] - rank_xy[i, 0], rank_xy[i+1, 1] - rank_xy[i, 1], head_width = 0.01, head_length = 0.2, overhang = 0.0, color = 'black', linewidth = 0.9, length_includes_head = True)
|
|
19
|
+
axes = plt.gca()
|
|
20
|
+
axes.set_xlim([-1, +1])
|
|
21
|
+
ymin = np.amin(rank_xy[:,1])
|
|
22
|
+
ymax = np.amax(rank_xy[:,1])
|
|
23
|
+
if (ymin < ymax):
|
|
24
|
+
axes.set_ylim([ymin, ymax])
|
|
25
|
+
else:
|
|
26
|
+
axes.set_ylim([ymin-1, ymax+1])
|
|
27
|
+
plt.axis('off')
|
|
28
|
+
plt.show()
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
# Function: Borda
|
|
32
|
+
def borda_method(dataset, criterion_type, graph = True, verbose = True):
|
|
33
|
+
X = np.zeros((dataset.shape[0], dataset.shape[1]))
|
|
34
|
+
for j in range(0, dataset.shape[1]):
|
|
35
|
+
if (criterion_type[j] == 'max'):
|
|
36
|
+
X[:,j] = np.argsort(np.argsort(-dataset[:,j]))+1
|
|
37
|
+
else:
|
|
38
|
+
X[:,j] = np.argsort(np.argsort(dataset[:,j]))+1
|
|
39
|
+
total = np.sum(X, axis = 1)
|
|
40
|
+
if (verbose == True):
|
|
41
|
+
for i in range(0, total.shape[0]):
|
|
42
|
+
print('a' + str(i+1) + ': ' + str(round(total[i], 2)))
|
|
43
|
+
if ( graph == True):
|
|
44
|
+
flow = np.copy(total)
|
|
45
|
+
flow = np.reshape(flow, (total.shape[0], 1))
|
|
46
|
+
flow = np.insert(flow, 0, list(range(1, total.shape[0]+1)), axis = 1)
|
|
47
|
+
flow = flow[np.argsort(flow[:, 1])]
|
|
48
|
+
ranking(flow)
|
|
49
|
+
return total
|
|
50
|
+
|
|
51
|
+
###############################################################################
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import numpy as np
|
|
5
|
+
import warnings
|
|
6
|
+
warnings.filterwarnings('ignore', message = 'delta_grad == 0.0. Check if the approximated')
|
|
7
|
+
|
|
8
|
+
from scipy.optimize import minimize, Bounds, LinearConstraint
|
|
9
|
+
|
|
10
|
+
###############################################################################
|
|
11
|
+
|
|
12
|
+
# Function: BWM
|
|
13
|
+
def bw_method(mic, lic, eps_penalty = 1, verbose = True):
|
|
14
|
+
cr = []
|
|
15
|
+
mx = np.max(mic)
|
|
16
|
+
if (mx == 1):
|
|
17
|
+
cr = 1
|
|
18
|
+
else:
|
|
19
|
+
for i in range(0, mic.shape[0]):
|
|
20
|
+
cr.append((mic[i] * lic[i] - mx)/(mx**2 - mx))
|
|
21
|
+
cr = np.max(cr)
|
|
22
|
+
threshold = [0, 0, 0, 0.1667, 0.1898, 0.2306, 0.2643, 0.2819, 0.2958, 0.3062]
|
|
23
|
+
if (verbose == True):
|
|
24
|
+
if (cr <= threshold[mx]):
|
|
25
|
+
print('CR:', np.round(cr, 4), '(The Consistency Level is Acceptable)')
|
|
26
|
+
else:
|
|
27
|
+
print('CR:', np.round(cr, 4), '(The Consistency Level is Not Acceptable)')
|
|
28
|
+
|
|
29
|
+
################################################
|
|
30
|
+
def target_function(variables):
|
|
31
|
+
eps = variables[-1]
|
|
32
|
+
wx = variables[np.argmin(mic)]
|
|
33
|
+
wy = variables[np.argmin(lic)]
|
|
34
|
+
cons_1 = []
|
|
35
|
+
cons_2 = []
|
|
36
|
+
penalty = 0
|
|
37
|
+
for i in range(0, mic.shape[0]):
|
|
38
|
+
cons_1.append(wx - mic[i] * variables[i])
|
|
39
|
+
cons_1.extend([-item for item in cons_1])
|
|
40
|
+
for i in range(0, lic.shape[0]):
|
|
41
|
+
cons_2.append(variables[i] - lic[i] * wy)
|
|
42
|
+
cons_2.extend([-item for item in cons_2])
|
|
43
|
+
cons = cons_1 + cons_2
|
|
44
|
+
for item in cons:
|
|
45
|
+
if (item > eps):
|
|
46
|
+
penalty = penalty + (item - eps) * 1
|
|
47
|
+
penalty = penalty + eps * eps_penalty
|
|
48
|
+
return penalty
|
|
49
|
+
################################################
|
|
50
|
+
|
|
51
|
+
np.random.seed(42)
|
|
52
|
+
variables = np.random.uniform(low = 0.001, high = 1.0, size = mic.shape[0])
|
|
53
|
+
variables = variables / np.sum(variables)
|
|
54
|
+
variables = np.append(variables, [0])
|
|
55
|
+
bounds = Bounds([0]*mic.shape[0] + [0], [1]*mic.shape[0] + [1])
|
|
56
|
+
w_cons = LinearConstraint(np.append(np.ones(mic.shape[0]), [0]), [1], [1])
|
|
57
|
+
results = minimize(target_function, variables, method = 'trust-constr', bounds = bounds, constraints = [w_cons])
|
|
58
|
+
weights = results.x[:-1]
|
|
59
|
+
if (verbose == True):
|
|
60
|
+
print('Epsilon Value:', np.round(results.x[-1], 4))
|
|
61
|
+
return weights
|
|
62
|
+
|
|
63
|
+
###############################################################################
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
###############################################################################
|
|
7
|
+
|
|
8
|
+
# Function: Simplified BWM
|
|
9
|
+
def simplified_bw_method(mic, lic, alpha = 0.5,verbose = True):
|
|
10
|
+
ib = np.argmin(mic)
|
|
11
|
+
iw = np.argmin(lic)
|
|
12
|
+
wb = [ 1 for item in mic]
|
|
13
|
+
ww = [ 1 for item in lic]
|
|
14
|
+
div = 0
|
|
15
|
+
for i in range(0, mic.shape[0]):
|
|
16
|
+
a = mic[i]
|
|
17
|
+
div = div + 1/a
|
|
18
|
+
wb[ib] = 1/div
|
|
19
|
+
for i in range(0, mic.shape[0]):
|
|
20
|
+
if (i != ib):
|
|
21
|
+
wb[i] = wb[ib]/mic[i]
|
|
22
|
+
ww[iw] = 1/np.sum(lic)
|
|
23
|
+
for i in range(0, lic.shape[0]):
|
|
24
|
+
if (i != iw):
|
|
25
|
+
ww[i] = lic[i]*ww[iw]
|
|
26
|
+
w = [alpha*wb[i] + (1 - alpha)*ww[i] for i in range(0, mic.shape[0])]
|
|
27
|
+
cr = sum([abs(wb[i] - ww[i]) for i in range(0, mic.shape[0])])
|
|
28
|
+
if (verbose == True):
|
|
29
|
+
print('CR:', np.round(cr, 4))
|
|
30
|
+
return cr, w
|
|
31
|
+
|
|
32
|
+
###############################################################################
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from scipy.linalg import null_space
|
|
7
|
+
|
|
8
|
+
###############################################################################
|
|
9
|
+
|
|
10
|
+
# Function: CILOS (Criterion Impact LOSs)
|
|
11
|
+
def cilos_method(dataset, criterion_type):
|
|
12
|
+
X = np.copy(dataset)/1.0
|
|
13
|
+
for j in range(X.shape[1]):
|
|
14
|
+
divisor = np.min(X[:, j]) if criterion_type[j] == 'max' else np.max(X[:, j])
|
|
15
|
+
if (divisor == 0):
|
|
16
|
+
X[:, j] = 1e-9
|
|
17
|
+
else:
|
|
18
|
+
X[:, j] = X[:, j] / divisor
|
|
19
|
+
sum_X_j = np.sum(X[:, j])
|
|
20
|
+
if (sum_X_j == 0):
|
|
21
|
+
X[:, j] = 1e-9
|
|
22
|
+
else:
|
|
23
|
+
X[:, j] = X[:, j] / sum_X_j
|
|
24
|
+
for j in range(X.shape[1]):
|
|
25
|
+
unique_vals = np.unique(X[:, j])
|
|
26
|
+
if (len(unique_vals) == 1):
|
|
27
|
+
X[:, j] = X[:, j] + np.random.uniform(low=1e-2, high=1e-1, size=X[:, j].shape)
|
|
28
|
+
A = X[np.argmax(X, axis = 0)]
|
|
29
|
+
P = (np.diag(A) - A) / np.diag(A)
|
|
30
|
+
F = P - np.diag(np.sum(P, axis = 0))
|
|
31
|
+
q = null_space(F)
|
|
32
|
+
q = (q / np.sum(q)).flatten()
|
|
33
|
+
return q
|
|
34
|
+
|
|
35
|
+
###############################################################################
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
###############################################################################
|
|
8
|
+
|
|
9
|
+
# Function: Rank
|
|
10
|
+
def ranking(flow):
|
|
11
|
+
rank_xy = np.zeros((flow.shape[0], 2))
|
|
12
|
+
for i in range(0, rank_xy.shape[0]):
|
|
13
|
+
rank_xy[i, 0] = 0
|
|
14
|
+
rank_xy[i, 1] = flow.shape[0]-i
|
|
15
|
+
for i in range(0, rank_xy.shape[0]):
|
|
16
|
+
plt.text(rank_xy[i, 0], rank_xy[i, 1], 'a' + str(int(flow[i,0])), size = 12, ha = 'center', va = 'center', bbox = dict(boxstyle = 'round', ec = (0.0, 0.0, 0.0), fc = (0.8, 1.0, 0.8),))
|
|
17
|
+
for i in range(0, rank_xy.shape[0]-1):
|
|
18
|
+
plt.arrow(rank_xy[i, 0], rank_xy[i, 1], rank_xy[i+1, 0] - rank_xy[i, 0], rank_xy[i+1, 1] - rank_xy[i, 1], head_width = 0.01, head_length = 0.2, overhang = 0.0, color = 'black', linewidth = 0.9, length_includes_head = True)
|
|
19
|
+
axes = plt.gca()
|
|
20
|
+
axes.set_xlim([-1, +1])
|
|
21
|
+
ymin = np.amin(rank_xy[:,1])
|
|
22
|
+
ymax = np.amax(rank_xy[:,1])
|
|
23
|
+
if (ymin < ymax):
|
|
24
|
+
axes.set_ylim([ymin, ymax])
|
|
25
|
+
else:
|
|
26
|
+
axes.set_ylim([ymin-1, ymax+1])
|
|
27
|
+
plt.axis('off')
|
|
28
|
+
plt.show()
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
# Function: COCOSO (COmbined COmpromise SOlution)
|
|
32
|
+
def cocoso_method(dataset, criterion_type, weights, L = 0.5, graph = True, verbose = True):
|
|
33
|
+
X = np.copy(dataset)/1.0
|
|
34
|
+
best = np.zeros(X.shape[1])
|
|
35
|
+
worst = np.zeros(X.shape[1])
|
|
36
|
+
for i in range(0, dataset.shape[1]):
|
|
37
|
+
if (criterion_type[i] == 'max'):
|
|
38
|
+
best[i] = np.max(X[:, i])
|
|
39
|
+
worst[i] = np.min(X[:, i])
|
|
40
|
+
else:
|
|
41
|
+
best[i] = np.min(X[:, i])
|
|
42
|
+
worst[i] = np.max(X[:, i])
|
|
43
|
+
for j in range(0, X.shape[1]):
|
|
44
|
+
X[:,j] = ( X[:,j] - worst[j] ) / ( best[j] - worst[j] + 0.0000000000000001)
|
|
45
|
+
S = np.sum(X * weights, axis = 1)
|
|
46
|
+
P = np.sum(X ** weights, axis = 1)
|
|
47
|
+
if (np.min(S) == 0):
|
|
48
|
+
S = S + 1
|
|
49
|
+
if (np.min(P) == 0):
|
|
50
|
+
P = P + 1
|
|
51
|
+
ksi_a = (P + S) / np.sum(P + S, axis = 0)
|
|
52
|
+
ksi_b = (S / np.min(S)) + (P / np.min(P))
|
|
53
|
+
ksi_c = (L * S + (1 - L) * P) / (L * np.max(S) + (1 - L) * np.max(P))
|
|
54
|
+
ksi = np.power(ksi_a * ksi_b * ksi_c, 1/3) + 1/3 * (ksi_a + ksi_b + ksi_c)
|
|
55
|
+
if (verbose == True):
|
|
56
|
+
for i in range(0, ksi.shape[0]):
|
|
57
|
+
print('a' + str(i+1) + ': ' + str(round(ksi[i], 2)))
|
|
58
|
+
if ( graph == True):
|
|
59
|
+
flow = np.copy(ksi)
|
|
60
|
+
flow = np.reshape(flow, (ksi.shape[0], 1))
|
|
61
|
+
flow = np.insert(flow, 0, list(range(1, ksi.shape[0]+1)), axis = 1)
|
|
62
|
+
flow = flow[np.argsort(flow[:, 1])]
|
|
63
|
+
flow = flow[::-1]
|
|
64
|
+
ranking(flow)
|
|
65
|
+
return ksi
|
|
66
|
+
|
|
67
|
+
###############################################################################
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
###############################################################################
|
|
8
|
+
|
|
9
|
+
# Function: Rank
|
|
10
|
+
def ranking(flow):
|
|
11
|
+
rank_xy = np.zeros((flow.shape[0], 2))
|
|
12
|
+
for i in range(0, rank_xy.shape[0]):
|
|
13
|
+
rank_xy[i, 0] = 0
|
|
14
|
+
rank_xy[i, 1] = flow.shape[0]-i
|
|
15
|
+
for i in range(0, rank_xy.shape[0]):
|
|
16
|
+
plt.text(rank_xy[i, 0], rank_xy[i, 1], 'a' + str(int(flow[i,0])), size = 12, ha = 'center', va = 'center', bbox = dict(boxstyle = 'round', ec = (0.0, 0.0, 0.0), fc = (0.8, 1.0, 0.8),))
|
|
17
|
+
for i in range(0, rank_xy.shape[0]-1):
|
|
18
|
+
plt.arrow(rank_xy[i, 0], rank_xy[i, 1], rank_xy[i+1, 0] - rank_xy[i, 0], rank_xy[i+1, 1] - rank_xy[i, 1], head_width = 0.01, head_length = 0.2, overhang = 0.0, color = 'black', linewidth = 0.9, length_includes_head = True)
|
|
19
|
+
axes = plt.gca()
|
|
20
|
+
axes.set_xlim([-1, +1])
|
|
21
|
+
ymin = np.amin(rank_xy[:,1])
|
|
22
|
+
ymax = np.amax(rank_xy[:,1])
|
|
23
|
+
if (ymin < ymax):
|
|
24
|
+
axes.set_ylim([ymin, ymax])
|
|
25
|
+
else:
|
|
26
|
+
axes.set_ylim([ymin-1, ymax+1])
|
|
27
|
+
plt.axis('off')
|
|
28
|
+
plt.show()
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
# Function: CODAS (Combinative Distance-based Assessment)
|
|
32
|
+
def codas_method(dataset, weights, criterion_type, lmbd = 0.02, graph = True, verbose = True):
|
|
33
|
+
X = np.copy(dataset)/1.0
|
|
34
|
+
bst = np.zeros(X.shape[1])
|
|
35
|
+
r_m = np.zeros((X.shape[0], X.shape[0]))
|
|
36
|
+
for j in range(0, X.shape[1]):
|
|
37
|
+
if ( criterion_type[j] == 'max'):
|
|
38
|
+
bst[j] = np.max(X[:, j])
|
|
39
|
+
elif ( criterion_type[j] == 'min'):
|
|
40
|
+
bst[j] = np.min(X[:, j])
|
|
41
|
+
for j in range(0, X.shape[1]):
|
|
42
|
+
for i in range(0, X.shape[0]):
|
|
43
|
+
if ( criterion_type[j] == 'max'):
|
|
44
|
+
X[i, j] = X[i, j]/bst[j]
|
|
45
|
+
elif ( criterion_type[j] == 'min'):
|
|
46
|
+
X[i, j] = bst[j]/X[i, j]
|
|
47
|
+
X = X * weights
|
|
48
|
+
n_i = np.min(X, axis = 0)
|
|
49
|
+
e_i = np.sum( (X - n_i)**2, axis = 1)**(1/2)
|
|
50
|
+
t_i = np.sum( abs(X - n_i), axis = 1)
|
|
51
|
+
for j in range(0, r_m.shape[1]):
|
|
52
|
+
for i in range(0, r_m.shape[0]):
|
|
53
|
+
r_m[i, j] = (e_i[i] - e_i[j]) + lmbd*( (e_i[i] - e_i[j]) * (t_i[i] - t_i[j]) )
|
|
54
|
+
h_i = np.sum(r_m, axis = 1)
|
|
55
|
+
flow = np.copy(h_i)
|
|
56
|
+
flow = np.reshape(flow, (h_i.shape[0], 1))
|
|
57
|
+
flow = np.insert(flow, 0, list(range(1, h_i.shape[0]+1)), axis = 1)
|
|
58
|
+
if (verbose == True):
|
|
59
|
+
for i in range(0, flow.shape[0]):
|
|
60
|
+
print('a' + str(int(flow[i,0])) + ': ' + str(round(flow[i,1], 3)))
|
|
61
|
+
if (graph == True):
|
|
62
|
+
flow = flow[np.argsort(flow[:, 1])]
|
|
63
|
+
flow = flow[::-1]
|
|
64
|
+
ranking(flow)
|
|
65
|
+
return flow
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
###############################################################################
|
|
8
|
+
|
|
9
|
+
# Function: Rank
|
|
10
|
+
def ranking(flow):
|
|
11
|
+
rank_xy = np.zeros((flow.shape[0], 2))
|
|
12
|
+
for i in range(0, rank_xy.shape[0]):
|
|
13
|
+
rank_xy[i, 0] = 0
|
|
14
|
+
rank_xy[i, 1] = flow.shape[0]-i
|
|
15
|
+
for i in range(0, rank_xy.shape[0]):
|
|
16
|
+
plt.text(rank_xy[i, 0], rank_xy[i, 1], 'a' + str(int(flow[i,0])), size = 12, ha = 'center', va = 'center', bbox = dict(boxstyle = 'round', ec = (0.0, 0.0, 0.0), fc = (0.8, 1.0, 0.8),))
|
|
17
|
+
for i in range(0, rank_xy.shape[0]-1):
|
|
18
|
+
plt.arrow(rank_xy[i, 0], rank_xy[i, 1], rank_xy[i+1, 0] - rank_xy[i, 0], rank_xy[i+1, 1] - rank_xy[i, 1], head_width = 0.01, head_length = 0.2, overhang = 0.0, color = 'black', linewidth = 0.9, length_includes_head = True)
|
|
19
|
+
axes = plt.gca()
|
|
20
|
+
axes.set_xlim([-1, +1])
|
|
21
|
+
ymin = np.amin(rank_xy[:,1])
|
|
22
|
+
ymax = np.amax(rank_xy[:,1])
|
|
23
|
+
if (ymin < ymax):
|
|
24
|
+
axes.set_ylim([ymin, ymax])
|
|
25
|
+
else:
|
|
26
|
+
axes.set_ylim([ymin-1, ymax+1])
|
|
27
|
+
plt.axis('off')
|
|
28
|
+
plt.show()
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
# Function: Copeland
|
|
32
|
+
def copeland_method(dataset, criterion_type, graph = True, verbose = True):
|
|
33
|
+
X = np.zeros((dataset.shape[0], dataset.shape[0]))
|
|
34
|
+
for i in range(0, dataset.shape[0]):
|
|
35
|
+
for k in range(0, dataset.shape[0]):
|
|
36
|
+
if (i != k):
|
|
37
|
+
for j in range(0, dataset.shape[1]):
|
|
38
|
+
if (criterion_type[j] == 'max'):
|
|
39
|
+
if (dataset[i, j] > dataset[k, j]):
|
|
40
|
+
X[i,k] = X[i,k] + 1
|
|
41
|
+
if (dataset[i, j] == dataset[k, j]):
|
|
42
|
+
X[i,k] = X[i,k] + 0
|
|
43
|
+
if (dataset[i, j] < dataset[k, j]):
|
|
44
|
+
X[i,k] = X[i,k] - 1
|
|
45
|
+
else:
|
|
46
|
+
if (dataset[i, j] > dataset[k, j]):
|
|
47
|
+
X[i,k] = X[i,k] - 1
|
|
48
|
+
if (dataset[i, j] == dataset[k, j]):
|
|
49
|
+
X[i,k] = X[i,k] + 0
|
|
50
|
+
if (dataset[i, j] < dataset[k, j]):
|
|
51
|
+
X[i,k] = X[i,k] + 1
|
|
52
|
+
total = np.sum(X, axis = 1)
|
|
53
|
+
if (verbose == True):
|
|
54
|
+
for i in range(0, total.shape[0]):
|
|
55
|
+
print('a' + str(i+1) + ': ' + str(round(total[i], 2)))
|
|
56
|
+
if ( graph == True):
|
|
57
|
+
flow = np.copy(total)
|
|
58
|
+
flow = np.reshape(flow, (total.shape[0], 1))
|
|
59
|
+
flow = np.insert(flow, 0, list(range(1, total.shape[0]+1)), axis = 1)
|
|
60
|
+
flow = flow[np.argsort(flow[:, 1])]
|
|
61
|
+
flow = flow[::-1]
|
|
62
|
+
ranking(flow)
|
|
63
|
+
return total
|
|
64
|
+
|
|
65
|
+
###############################################################################
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
|
|
3
|
+
# Required Libraries
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
###############################################################################
|
|
8
|
+
|
|
9
|
+
# Function: Rank
|
|
10
|
+
def ranking(flow):
|
|
11
|
+
rank_xy = np.zeros((flow.shape[0], 2))
|
|
12
|
+
for i in range(0, rank_xy.shape[0]):
|
|
13
|
+
rank_xy[i, 0] = 0
|
|
14
|
+
rank_xy[i, 1] = flow.shape[0]-i
|
|
15
|
+
for i in range(0, rank_xy.shape[0]):
|
|
16
|
+
plt.text(rank_xy[i, 0], rank_xy[i, 1], 'a' + str(int(flow[i,0])), size = 12, ha = 'center', va = 'center', bbox = dict(boxstyle = 'round', ec = (0.0, 0.0, 0.0), fc = (0.8, 1.0, 0.8),))
|
|
17
|
+
for i in range(0, rank_xy.shape[0]-1):
|
|
18
|
+
plt.arrow(rank_xy[i, 0], rank_xy[i, 1], rank_xy[i+1, 0] - rank_xy[i, 0], rank_xy[i+1, 1] - rank_xy[i, 1], head_width = 0.01, head_length = 0.2, overhang = 0.0, color = 'black', linewidth = 0.9, length_includes_head = True)
|
|
19
|
+
axes = plt.gca()
|
|
20
|
+
axes.set_xlim([-1, +1])
|
|
21
|
+
ymin = np.amin(rank_xy[:,1])
|
|
22
|
+
ymax = np.amax(rank_xy[:,1])
|
|
23
|
+
if (ymin < ymax):
|
|
24
|
+
axes.set_ylim([ymin, ymax])
|
|
25
|
+
else:
|
|
26
|
+
axes.set_ylim([ymin-1, ymax+1])
|
|
27
|
+
plt.axis('off')
|
|
28
|
+
plt.show()
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
# Function: COPRAS (Complex Proportional Assessment)
|
|
32
|
+
def copras_method(dataset, weights, criterion_type, graph = True, verbose = True):
|
|
33
|
+
X = np.copy(dataset)/1.0
|
|
34
|
+
X = X/np.sum(X, axis = 0)
|
|
35
|
+
X = X*weights
|
|
36
|
+
s_p = np.zeros(X.shape[0])
|
|
37
|
+
s_m = np.zeros(X.shape[0])
|
|
38
|
+
s_d = np.zeros(X.shape[0])
|
|
39
|
+
q_i = np.zeros(X.shape[0])
|
|
40
|
+
u_i = np.zeros(X.shape[0])
|
|
41
|
+
id1 = [i for i, j in enumerate(criterion_type) if j == 'max']
|
|
42
|
+
id2 = [i for i, j in enumerate(criterion_type) if j == 'min']
|
|
43
|
+
if (len(id1) > 0):
|
|
44
|
+
s_p = np.sum(X[:,id1], axis = 1)
|
|
45
|
+
q_i = s_p
|
|
46
|
+
if (len(id2) > 0):
|
|
47
|
+
s_m = np.sum(X[:,id2], axis = 1)
|
|
48
|
+
s_d = np.min(s_m)/s_m
|
|
49
|
+
q_i = s_p + (np.min(s_m)*np.sum(s_m))/(s_m*np.sum(s_d))
|
|
50
|
+
u_i = q_i/np.max(q_i)
|
|
51
|
+
flow = np.copy(u_i)
|
|
52
|
+
flow = np.reshape(flow, (u_i.shape[0], 1))
|
|
53
|
+
flow = np.insert(flow, 0, list(range(1, u_i.shape[0]+1)), axis = 1)
|
|
54
|
+
if (verbose == True):
|
|
55
|
+
for i in range(0, flow.shape[0]):
|
|
56
|
+
print('a' + str(int(flow[i,0])) + ': ' + str(round(flow[i,1], 3)))
|
|
57
|
+
if (graph == True):
|
|
58
|
+
flow = flow[np.argsort(flow[:, 1])]
|
|
59
|
+
flow = flow[::-1]
|
|
60
|
+
ranking(flow)
|
|
61
|
+
return flow
|