Compromise solutions

HQ compromise

pysensmcda.compromise.HQ_compromise.HQ_compromise(rankings: ndarray, max_iters: int = 1000, tol: float = 1e-09) tuple[tuple[float, float], ndarray, ndarray][source]

Perform HQ (Half-Quadratic) compromise on a set of rankings.

Parameters:

rankingsnp.ndarray

2D array representing the rankings. Each row corresponds to an alternative, and each column corresponds to a criterion.

max_itersint, optional, default=1000

Maximum number of iterations for the compromise algorithm.

tolfloat, optional, default=10e-10

Tolerance for convergence.

Returns:

tuple

Tuple that contains (consensus_index, trust_index), weights of rankings, compromised ranking

Examples

Example 1: Calculation with default parameters

>>> rankings = np.array([[2, 2, 2],
>>>                     [3, 4, 5],
>>>                     [1, 1, 4],
>>>                     [4, 3, 1],
>>>                     [7, 5, 7],
>>>                     [8, 8, 8],
>>>                     [5, 6, 3],
>>>                     [6, 7, 6]])
>>> HQ_compromise(rankings)

Example 2: Set tolerance on convergence and change maximum number of iterations

>>> rankings = np.array([[2, 2, 2],
>>>                     [3, 4, 5],
>>>                     [1, 1, 4],
>>>                     [4, 3, 1],
>>>                     [7, 5, 7],
>>>                     [8, 8, 8],
>>>                     [5, 6, 3],
>>>                     [6, 7, 6]])
>>> HQ_compromise(rankings, max_iters=100, tol=10e-6)

ICRA

class pysensmcda.compromise.ICRA.ICRAResults(initial_preferences: ndarray, initial_rankings: ndarray, final_preferences: ndarray, final_rankings: ndarray, iters_number: int, all_preferences: ndarray, all_rankings: ndarray, all_corrs: ndarray)[source]

Bases: object

Class for keeping ICRA results.

all_corrs: ndarray
all_preferences: ndarray
all_rankings: ndarray
final_preferences: ndarray
final_rankings: ndarray
initial_preferences: ndarray
initial_rankings: ndarray
iters_number: int
pysensmcda.compromise.ICRA.iterative_compromise(methods: dict, preferences: ~numpy.ndarray, types, corr_coef: callable = <function weighted_spearman>, max_iters: int = 1000, compromise_weights: ~numpy.ndarray | None = None) ICRAResults[source]

Iterative Compromise Ranking Analysis (ICRA).

The ICRA is an approach that provides decision maker a compromise ranking for specific set of considered rankings using specific multi-criteria decision-making methods ICRA main advantage is using preference values and weights for each expert / decision-making method

Parameters:

methods: array of callable

Array that should contain callable functions or objects for all considered MCDMs. The function or function returned by object should return preference value. The data should be stored in dictionary in following way: >>> { >>> Object: [[parameters for object initialization], >>> [parameters for function initialization]], >>> function: [parameters for function initialization] >>> }

See example preferences: ndarray

Decision matrix consisting of preferences. Alternatives are in rows and Criteria (methods / experts) are in columns

types: ndarray

Array with definitions of method types types: 1 if method ranks in ascending order and -1 if the method ranks in descending order

corr_coef: callable, optional, default=pymcdm.correlations.weighted_spearman

Function which will be used to check similarity of rankings while achieving compromise.

max_iters: int, optional, default=1000

Maximum iterations number to seek compromise.

compromise_weights: ndarray, optional, default=equal weights

Weights of methods / experts in compromise seeking. Sum of the weights should be 1. (e.g. sum(weights) == 1).

Returns:

results: object

ICRAResults object is returned, which consists of: initial_preferences: ndarray initial_rankings: ndarray final_preferences: ndarray final_rankings: ndarray iters_number: int all_preferences: ndarray all_rankings: ndarray all_corrs: ndarray

Example:

>>> ## Initial decision problem evaluation - random problem
>>> decision_matrix = np.random.random((7, 5))
>>>
>>> decision_problem_weights = np.ones(decision_matrix.shape[1])/decision_matrix.shape[1]
>>> decision_problem_types = np.ones(decision_matrix.shape[1])
>>>
>>> comet = COMET(np.vstack((np.min(decision_matrix, axis=0), np.max(decision_matrix, axis=0))).T, MethodExpert(TOPSIS(), decision_problem_weights, decision_problem_types))
>>> topsis = TOPSIS()
>>> vikor = VIKOR()
>>>
>>> comet_pref = comet(decision_matrix)
>>> topsis_pref = topsis(decision_matrix, decision_problem_weights, decision_problem_types)
>>> vikor_pref = vikor(decision_matrix, decision_problem_weights, decision_problem_types)
>>>
>>> ## ICRA variables preparation
>>> methods = {
...     COMET: [['np.vstack((np.min(matrix, axis=0), np.max(matrix, axis=0))).T',
...                     'MethodExpert(TOPSIS(), weights, types)'],
...             ['matrix']],
...     topsis: ['matrix', 'weights', 'types'],
...     vikor: ['matrix', 'weights', 'types']
...     }
>>>
>>> ICRA_matrix = np.array([comet_pref, topsis_pref, vikor_pref]).T
>>> method_types = np.array([1, 1, -1])
>>>
>>> result = iterative_compromise(methods, ICRA_matrix, method_types)
>>> print(result.all_rankings)

Borda

pysensmcda.compromise.borda.borda(rankings: ndarray) ndarray[source]

Calculates compromised ranking using borda voting rule.

Parameters:

rankings: ndarray

Two-dimensional matrix containing different rankings in columns.

Returns:

ndarray

Numpy array containing compromised ranking.

Example:

>>> rankings = np.array([[3, 2, 3],
>>>                     [4, 4, 4],
>>>                     [2, 3, 2],
>>>                     [1, 1, 1]])
>>> compromised_ranking = borda(rankings)

Dominance Directed Graph

pysensmcda.compromise.dominance_directed_graph.dominance_directed_graph(rankings: ndarray) ndarray[source]

Calculates compromised ranking using dominance directed graph.

Parameters:

rankingsndarray

Two-dimensional matrix containing different rankings in columns.

Returns:

ndarray

Numpy array containing compromised ranking.

Example:

>>> rankings = np.array([[3, 2, 3],
>>>                     [4, 4, 4],
>>>                     [2, 3, 2],
>>>                     [1, 1, 1]])
>>> compromised_ranking = dominance_directed_graph(rankings)

Improved Borda

pysensmcda.compromise.improved_borda.improved_borda(preferences: ~numpy.ndarray, preference_types: ~numpy.ndarray | list = [], normalization: callable = <function vector_normalization>, utility_funcs: list[callable] = [], norm_types: ~numpy.ndarray | list = []) ndarray[source]

Improved borda was presented along Probabilistic Linguistic MULTIMOORA, where authors used specific utility functions. This implementation relyes on the concept proposed by author, however it does provide freedom for the user.

Parameters:

preferences: ndarray

Preferences for alternatives in rows that will be further compromised. Columns designates methods / criteria.

preference_types: list | ndarray, optional, default=[]

List of types of methods, changes direction of evaluation: -1 for the ascending ranking, 1 for the descending ranking. Defaults to descending for all.

normalization: callable, optional, default=vector_normalization

Function to normalize utility functions results. See vector_normalization for further information.

utility_funcs: list[callable], optional, default=[]

List of utility functions for each of criterion. If provided, must align with number of criteria in preference matrix.

norm_types: list | ndarray, optional, default=[]

Changes type of normalization if needed, -1 for cost, 1 for profit.

Returns:

ndarray

Compromised ranking.

Example:

>>> matrix = np.random.random((8,5))
>>> criteria_num = matrix.shape[1]
>>> weights = np.ones(criteria_num)/criteria_num
>>> types = np.ones(criteria_num)
>>> preferences = np.array([topsis(matrix, weights, types), vikor(matrix, weights, types)]).T
>>>
>>> compromise_ranking = improved_borda(preferences, [1, -1])
pysensmcda.compromise.improved_borda.vector_normalization(x: ndarray, cost: bool = True) ndarray[source]

Parameters:

x: ndarray

Vector of numbers to be normalized.

cost: bool, optional, cost=True

Type of normalization. If True normalize as cost criterion, if False normalize as profit criterion.

Returns:

ndarray

Normalized vector.

Example:

>>> normalized_matrix = matrix.copy()
>>> for i in range(criteria_number):
>>>     cost = True if types[i] == -1 else False
>>>     normalized_matrix[:, i] = normalization(matrix[:, i], cost)

Rank position

pysensmcda.compromise.rank_position.rank_position(rankings: ndarray) ndarray[source]

Calculates compromised ranking using rank position method.

Parameters:

rankingsndarray

Two-dimensional matrix containing different rankings in columns.

Returns:

ndarray

Vector including compromise ranking.

Example:

>>> rankings = np.array([[3, 2, 3],
>>>                     [4, 4, 4],
>>>                     [2, 3, 2],
>>>                     [1, 1, 1]])
>>> rank = rank_position_method(rankings)