Source code for pyifdm.methods.vikor.ifs

# Copyright (c) 2022 Jakub Więckowski

import numpy as np

[docs] def ifs(matrix, weights, types, normalization, distance, v): """ Calculates the alternatives preferences based on Intuitionistic Fuzzy Sets Parameters ---------- matrix : ndarray Decision matrix / alternatives data. Alternatives are in rows and Criteria are in columns. weights : ndarray Vector of criteria weights in a crisp or Intuitionistic Fuzzy form types : ndarray Types of criteria, 1 profit, -1 cost normalization: callable Function used to normalize the decision matrix distance: callable Function used to calculate distance between two IFS v : float Weights for the strategy of maximum group utility Returns ------- ndarray Crisp preferences of alternatives """ # normalized matrix if normalization is not None: nmatrix = normalization(matrix, types) else: nmatrix = matrix.copy() # postive and negative ideal solution pis, nis = np.zeros((nmatrix.shape[1], ), dtype=object), np.zeros((nmatrix.shape[1], ), dtype=object) for j in range(matrix.shape[1]): pis[j] = nmatrix[np.argmax(nmatrix[:, j, 0]), j] nis[j] = nmatrix[np.argmin(nmatrix[:, j, 0]), j] f = 1 if 'normalized' in distance.__name__: f = 1/(2*matrix.shape[1]) # validate data if any([all(p == n) for p, n in zip(pis, nis)]): raise ValueError('Matrix should not contain same values within a single column') # calculation of S and R rankings S, R, Q = np.zeros((nmatrix.shape[0], )), np.zeros((nmatrix.shape[0], )), np.zeros((nmatrix.shape[0], )) for i in range(matrix.shape[0]): if distance.__name__== 'normalized_euclidean_distance': S[i] = np.sum([weights[j] * (np.sqrt(f * distance(pis[j], nmatrix[i, j])) / np.sqrt(f * distance(pis[j], nis[j]))) for j in range(nmatrix.shape[1])]) R[i] = np.max([weights[j] * (np.sqrt(f * distance(pis[j], nmatrix[i, j])) / np.sqrt(f * distance(pis[j], nis[j]))) for j in range(nmatrix.shape[1])]) elif distance.__name__== 'normalized_hamming_distance': S[i] = np.sum([weights[j] * ((f * distance(pis[j], nmatrix[i, j])) / (f * distance(pis[j], nis[j]))) for j in range(nmatrix.shape[1])]) R[i] = np.max([weights[j] * ((f * distance(pis[j], nmatrix[i, j])) / (f * distance(pis[j], nis[j]))) for j in range(nmatrix.shape[1])]) else: S[i] = np.sum([weights[j] * (distance(pis[j], nmatrix[i, j]) / distance(pis[j], nis[j]))for j in range(nmatrix.shape[1])]) R[i] = np.max([weights[j] * (distance(pis[j], nmatrix[i, j]) / distance(pis[j], nis[j]))for j in range(nmatrix.shape[1])]) # calculation of the compromise ranking Q Q = v * ((S - np.min(S)) / (np.max(S) - np.min(S))) + (1 - v) * ((R - np.min(R)) / (np.max(R) - np.min(R))) return np.nan_to_num(S), np.nan_to_num(R), np.nan_to_num(Q)