Ranking

Alteration

pysensmcda.ranking.alteration.ranking_alteration(weights: ndarray, initial_ranking: ndarray, method: callable, call_kwargs: dict, ranking_descending: bool, step: float = 0.01) list[tuple[int, ndarray, ndarray]][source]

Identify the minimal change in criteria weights that causes an alteration in the ranking of alternatives.

Parameters:

weightsndarray

1D vector with criteria weights used for multi-criteria evaluation.

initial_rankingndarray

1D vector representing the initial ranking of alternatives.

methodcallable

The evaluation function to be used for preference and ranking calculation. Should include matrix and weights as one of the parameters to pass the decision matrix to the assessment process.

call_kwargsdict

Dictionary with keyword arguments to be passed to the evaluation function. Should include matrix and weights as one of the parameters to pass the modified decision matrix to the assessment process.

ranking_descending: bool

Flag determining the direction of alternatives ordering in ranking. By setting the flag to True, greater values will have better positions in ranking.

stepfloat, optional, default = 0.01

Step size for the weights modification.

Returns:

list of tuples

Each tuple contains the index of the modified weight, the new set of weights, and the resulting ranking.

Examples:

Example 1: Ranking alteration analysis with default parameters

>>> weights = np.array([0.4, 0.5, 0.1])
>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> types = np.array([-1, 1, -1])
>>> aras = pymcdm.methods.ARAS()
>>> pref = aras(matrix, weights, types)
>>> initial_ranking = aras.rank(pref)
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> results = ranking_alteration(weights, initial_ranking, aras, call_kwargs, ranking_descending)
>>> for r in results:
...     print(r)

Example 2: Ranking alteration analysis with default parameters with explicitly defined step

>>> weights = np.array([0.4, 0.5, 0.1])
>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> types = np.array([-1, 1, -1])
>>> aras = pymcdm.methods.ARAS()
>>> pref = aras(matrix, weights, types)
>>> initial_ranking = aras.rank(pref)
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> step = 0.05
>>> results = ranking_alteration(weights, initial_ranking, aras, call_kwargs, ranking_descending, step)
>>> for r in results:
...     print(r)

Demotion

pysensmcda.ranking.demotion.ranking_demotion(matrix: ndarray, initial_ranking: ndarray, method: callable, call_kwargs: dict, ranking_descending: bool, direction: ndarray, step: int | float, bounds: None | ndarray = None, positions: None | ndarray = None, return_zeros: bool = True, max_modification: None | int = None) list[tuple[int, int, float, int]][source]

Demote alternatives in a decision matrix by adjusting specific criteria values, considering constraints on rankings. With only required parameters given, the analysis is looking for changes that cause demotion for last position in ranking.

Parameters:

matrixndarray

2D array with a decision matrix containing alternatives in rows and criteria in columns.

initial_rankingndarray

1D vector representing the initial ranking of alternatives.

methodcallable

The evaluation function to be used for preference and ranking calculation. Should include matrix as one of the parameters to pass decision matrix to assessment process.

call_kwargsdict

Dictionary with keyword arguments to be passed to the evaluation function. Should include matrix as one of the parameters to pass modified decision matrix to assessment process.

ranking_descending: bool

Flag determining the direction of alternatives ordering in ranking. By setting the flag to True, greater values will have better positions in ranking.

directionndarray

1D vector specifying the direction of the modification for each column in decision matrix (1 for increase, -1 for decrease).

stepint | float

Step size for the modification.

boundsNone | ndarray, optional, default=None

Bounds representing the size of the modifications for columns in decision matrix. If None, then modifications are introduced in decision matrix until the last position in the ranking is achieved for a given alternative.

positionsNone | ndarray, optional, default=None

Target positions for the alternatives in the ranking after modification. If None, the positions are not constrained and the last position is targeted.

return_zerosbool, optional, default=True

Flag determining whether results without noticed demotion in ranking will be returned.

max_modificationNone | int, optional, default=None

Value determining maximum modification size represented as percent of initial value. Required if bounds parameter is not given.

Returns:

List[Tuple[int, int, float, int]]

A list of tuples containing information about alternative index, criterion index, size of change, and achieved new positions based on demotion analysis.

Examples:

Example 1: Demotion analysis based on the COPRAS method with only required parameters

>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> weights = np.array([0.4, 0.5, 0.1])
>>> types = np.array([-1, 1, -1])
>>> copras = pymcdm.methods.COPRAS()
>>> pref = copras(matrix, weights, types)
>>> initial_ranking = copras.rank(pref)
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> direction = np.array([1, -1, 1])
>>> step = 0.5
>>> max_modification = 100
>>> results = ranking_demotion(matrix, initial_ranking, copras, call_kwargs, ranking_descending, direction, step, max_modification=max_modification)
>>> for r in results:
...     print(r)

Example 2: Demotion analysis based on the COPRAS method with explicitly defined modification bounds

>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> weights = np.array([0.4, 0.5, 0.1])
>>> types = np.array([-1, 1, -1])
>>> copras = pymcdm.methods.COPRAS()
>>> initial_ranking = np.array([2, 3, 1])
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> direction = np.array([1, -1, 1])
>>> step = 0.5
>>> bounds = np.array([15, 0, 20])
>>> results = ranking_demotion(matrix, initial_ranking, copras, call_kwargs, ranking_descending, direction, step, bounds)
>>> for r in results:
...     print(r)

Example 3: Demotion analysis based on the COPRAS method with explicitly defined modification bounds and targeted positions

>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> weights = np.array([0.4, 0.5, 0.1])
>>> types = np.array([-1, 1, -1])
>>> copras = pymcdm.methods.COPRAS()
>>> initial_ranking = np.array([2, 3, 1])
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> direction = types * -1
>>> step = 0.5
>>> bounds = np.array([15, 0, 20])
>>> positions = np.array([3, 3, 1])
>>> results = ranking_demotion(matrix, initial_ranking, copras, call_kwargs, ranking_descending, direction, step, bounds, positions)
>>> for r in results:
...     print(r)

Example 4: Demotion analysis based on the COPRAS method with not returned values without noticed demotion

>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> weights = np.array([0.4, 0.5, 0.1])
>>> types = np.array([-1, 1, -1])
>>> copras = pymcdm.methods.COPRAS()
>>> initial_ranking = np.array([2, 3, 1])
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> direction = types * -1
>>> step = 0.5
>>> max_modification = 10
>>> return_zeros = False
>>> results = ranking_demotion(matrix, initial_ranking, copras, call_kwargs, ranking_descending, direction, step, max_modification=max_modification, return_zeros=return_zeros)
>>> for r in results:
...     print(r)

Fuzzy ranking

pysensmcda.ranking.fuzzy_ranking.fuzzy_ranking(rankings: ndarray, normalization_axis: None | int = None) ndarray[source]

Generate fuzzy ranking matrix based on positional rankings.

Parameters:

rankingsnp.ndarray

2D array with positional rankings, where each row represents a separate positional ranking of alternatives.

normalization_axisint, optional

Specifies the type of fuzzy ranking representation. If 0, it normalizes the obtained fuzzy rankings regarding values in columns (by distribution of positions for alternatives). If 1, it normalizes the obtained fuzzy rankings regarding values in rows (by positions in rankings). If None or not specified, it returns the default fuzzy ranking matrix without data normalization.

Returns:

np.ndarray

Fuzzy ranking matrix based on the specified normalization_axis. Each element represents the membership degree of alternatives and ranking positions.

Example:

>>> rankings = np.array([
...     [1, 2, 3, 4, 5],
...     [2, 1, 5, 3, 4],
...     [4, 3, 2, 5, 1],
...     [3, 2, 1, 4, 5],
... ])
>>> fuzzy_rank = fuzzy_ranking(rankings, normalization_axis=0)
>>> print(fuzzy_rank)

Promotion

pysensmcda.ranking.promotion.ranking_promotion(matrix: ndarray, initial_ranking: ndarray, method: callable, call_kwargs: dict, ranking_descending: bool, direction: ndarray, step: int | float, bounds: None | ndarray = None, positions: None | ndarray = None, return_zeros: bool = True, max_modification: None | int = None) list[tuple[int, int, float, int]][source]

Promote alternatives in a decision matrix by adjusting specific criteria values, considering constraints on rankings. With only required parameters given, the analysis is looking for changes that cause promotion for 1st position in ranking.

Parameters:

matrixndarray

2D array with a decision matrix containing alternatives in rows and criteria in columns.

initial_rankingndarray

1D vector representing the initial ranking of alternatives.

methodcallable

The evaluation function to be used for preference and ranking calculation. Should include matrix as one of the parameters to pass decision matrix to assessment process.

call_kwargsdict

Dictionary with keyword arguments to be passed to the evaluation function. Should include matrix as one of the parameters to pass modified decision matrix to assessment process.

ranking_descending: bool

Flag determining the direction of alternatives ordering in ranking. By setting the flag to True, greater values will have better positions in ranking.

directionndarray

1D vector specifying the direction of the modification for each column in decision matrix (1 for increase, -1 for decrease).

stepint | float

Step size for the modification.

boundsNone | ndarray, optional, default=None

Bounds representing the size of the modifications for columns in decision matrix. If None, then modifications are introduced in decision matrix until the 1st position in the ranking is achieved for a given alternative.

positionsNone | ndarray, optional, default=None

Target positions for the alternatives in the ranking after modification. If None, the positions are not constrained and the 1st position is targeted.

return_zerosbool, optional, default=True

Flag determining whether results without noticed promotion in ranking will be returned.

max_modificationNone | int, optional, default=None

Value determining maximum modification size represented as percent of initial value. Required if bounds parameter is not given.

Returns:

List[Tuple[int, int, float, int]]

A list of tuples containing information about alternative index, criterion index, size of change, and achieved new positions based on promotion analysis.

Examples:

Example 1: Promotion analysis based on the COPRAS method with only required parameters

>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> weights = np.array([0.4, 0.5, 0.1])
>>> types = np.array([-1, 1, -1])
>>> copras = pymcdm.methods.COPRAS()
>>> pref = copras(matrix, weights, types)
>>> initial_ranking = copras.rank(pref)
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> direction = np.array([-1, 1, -1])
>>> step = 0.5
>>> max_modification = 1000
>>> results = ranking_promotion(matrix, initial_ranking, copras, call_kwargs, ranking_descending, direction, step, max_modification=max_modification)
>>> for r in results:
...     print(r)

Example 2: Promotion analysis based on the COPRAS method with explicitly defined modification bounds

>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> weights = np.array([0.4, 0.5, 0.1])
>>> types = np.array([-1, 1, -1])
>>> copras = pymcdm.methods.COPRAS()
>>> initial_ranking = np.array([2, 3, 1])
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> direction = np.array([-1, 1, -1])
>>> step = 0.5
>>> bounds = np.array([1, 15, 0])
>>> results = ranking_promotion(matrix, initial_ranking, copras, call_kwargs, ranking_descending, direction, step, bounds)
>>> for r in results:
...     print(r)

Example 3: Promotion analysis based on the COPRAS method with explicitly defined modification bounds and targeted positions

>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> weights = np.array([0.4, 0.5, 0.1])
>>> types = np.array([-1, 1, -1])
>>> copras = pymcdm.methods.COPRAS()
>>> initial_ranking = np.array([2, 3, 1])
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> direction = np.array([-1, 1, -1])
>>> step = 0.5
>>> bounds = np.array([1, 15, 0])
>>> positions = np.array([1, 2, 1])
>>> results = ranking_promotion(matrix, initial_ranking, copras, call_kwargs, ranking_descending, direction, step, bounds, positions)
>>> for r in results:
...     print(r)

Example 4: Promotion analysis based on the COPRAS method with not returned values without noticed promotion

>>> matrix = np.array([
...     [4, 2, 6],
...     [7, 3, 2],
...     [9, 6, 8]
... ])
>>> weights = np.array([0.4, 0.5, 0.1])
>>> types = np.array([-1, 1, -1])
>>> copras = pymcdm.methods.COPRAS()
>>> initial_ranking = np.array([2, 3, 1])
>>> call_kwargs = {
...     "matrix": matrix,
...     "weights": weights,
...     "types": types
... }
>>> ranking_descending = True
>>> direction = np.array([-1, 1, -1])
>>> step = 0.5
>>> max_modification = 50
>>> return_zeros = False
>>> results = ranking_promotion(matrix, initial_ranking, copras, call_kwargs, ranking_descending, direction, step, max_modification=max_modification, return_zeros=return_zeros)
>>> for r in results:
...     print(r)