Source code for pyfdm.methods.edas.fuzzy

# Copyright (c) 2022 Jakub Więckowski

import numpy as np

[docs] def fuzzy(matrix, weights, types, defuzzify): """ Calculates the alternatives preferences based on Triangular Fuzzy Number extension 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 form types : ndarray Types of criteria, 1 profit, -1 cost defuzzify: callable Function used to defuzzify the TFN into crisp value Returns ------- ndarray: Crisp preferences of alternatives """ def psi(a): """ Threshold function Parameters ---------- a: ndarray Triangular Fuzzy Number Returns ------- ndarray 0 if defuzzified TFN lower than 0, otherwise TFN """ if defuzzify(a) > 0: return a return [0, 0, 0] # fuzzy average decision matrix av_matrix = np.mean(matrix, axis=0) k = np.array([defuzzify(a) for a in av_matrix]) # positive and negative distances from average pda, nda = np.zeros((matrix.shape)), np.zeros((matrix.shape)) for i in range(matrix.shape[0]): for j in range(matrix.shape[1]): if types[j] == 1: pda[i, j] = psi( matrix[i, j] - av_matrix[j][..., ::-1]) / k[j] nda[i, j] = psi( av_matrix[j] - matrix[i, j][..., ::-1]) / k[j] else: pda[i, j] = psi( av_matrix[j] - matrix[i, j][..., ::-1]) / k[j] nda[i, j] = psi( matrix[i, j] - av_matrix[j][..., ::-1]) / k[j] if weights.ndim == 1: weights = np.repeat(weights, 3).reshape((len(weights), 3)) # fuzzy weighted positive and negative distances sp = np.sum(pda * weights, axis=1) sn = np.sum(nda * weights, axis=1) # fuzzy normalized weighted positive and negative distances nsp = sp / np.max([defuzzify(p) for p in sp]) nsn = 1 - (sn / np.max([defuzzify(n) for n in sn])) # fuzzy appraisal score a = (nsp + nsn) / 2 return np.array([defuzzify(alt) for alt in a])