Criteria
Relevance identification
- pysensmcda.criteria.identification.relevance_identification(method: callable, call_kwargs: dict, ranking_descending: bool, excluded_criteria: int = 1, return_all: bool = False, corr_coef: ~typing.Callable | ~typing.List[~typing.Callable] = <function weighted_spearman>, precision: int = 6) list[tuple[tuple[int] | int, tuple[float] | float, float, ndarray]][source]
The core idea behind this method is to iteratively exclude a specified number of criteria and evaluate the impact on the ranking of alternatives. By systematically excluding different criteria and analyzing the resulting changes in the ranking, the function aims to identify which criteria significantly influence the final decision.
Parameters:
- methodcallable
The evaluation function to be used for preference and ranking calculation. Should include matrix, weights, and types as one of the parameters to pass modified input data to the assessment process.
- call_kwargsdict
Dictionary with keyword arguments to be passed to the evaluation function. Should include matrix, weights, and types as one of the parameters to pass modified input data 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 the ranking.
- excluded_criteria: int, optional, default=1
Number of criteria to be excluded in each iteration.
- return_all: bool, optional, default=False
Flag determining if the returned results include all data in criteria identification process If True, all data is return for each iteration of relevance identification. If False, only the least relevant criterion for each iteration is returned.
- corr_coef: callable | list, optional, default=pymcdm.correlations.weighted_spearman
Function which will be used to check similarity of rankings while achieving compromise. If callable, then correlation calculated for given coefficient. If list of callables, then correlation calculated for multiple coefficients.
- precision: int, optional, default=6
Precision for rounding the results.
Returns:
- list
List of tuples containing information about the relevance identification process. Each tuple includes the excluded criteria indices, correlation coefficient values, distance calculated as the sum of the Euclidean distance between preferences, and the modified matrix.
Examples:
Example 1: Identify relevant criteria in a custom matrix using TOPSIS method
>>> matrix = np.array([ ... [4, 3, 5, 7], ... [7, 4, 2, 4], ... [9, 5, 7, 3], ... [3, 5, 6, 3] ... ]) >>> criteria_types = np.array([1, 1, -1, 1]) >>> weights = equal_weights(matrix) >>> topsis = pm.TOPSIS(normalization_function=norm.vector_normalization) >>> call_kwargs = { ... 'matrix': matrix, ... 'weights': weights, ... 'types': criteria_types ... } >>> results = relevance_identification(topsis, call_kwargs, ranking_descending=True) >>> for r in results: ... print(r)
Example 2: Identify relevant criteria in using TOPSIS method and excluding 3 criteria in the problem
>>> matrix = np.array([ ... [106.78, 6.75, 2. , 220. , 6. , 1. , 52. , 455.5 , 8.9 , 36.8 ], ... [ 86.37, 7.12, 3. , 400. , 10. , 0. , 20. , 336.5 , 7.2 , 29.8 ], ... [104.85, 6.95, 60. , 220. , 7. , 1. , 60. , 416. , 8.7 , 36.2 ], ... [ 46.6 , 6.04, 1. , 220. , 3. , 0. , 50. , 277. , 3.9 , 16. ], ... [ 69.18, 7.05, 33.16, 220. , 8. , 0. , 35.49, 364.79, 5.39, 33.71], ... [ 66.48, 6.06, 26.32, 220. , 6.53, 0. , 34.82, 304.02, 4.67, 27.07], ... [ 74.48, 6.61, 48.25, 400. , 4.76, 1. , 44.19, 349.45, 4.93, 28.89], ... [ 73.67, 6.06, 19.54, 400. , 3.19, 0. , 46.41, 354.65, 8.01, 21.09], ... [100.58, 6.37, 39.27, 220. , 8.43, 1. , 22.07, 449.42, 7.89, 17.62], ... [ 94.81, 6.13, 50.58, 220. , 4.18, 1. , 21.14, 450.88, 5.12, 17.3 ], ... [ 48.93, 7.12, 21.48, 220. , 5.47, 1. , 55.72, 454.71, 8.39, 19.16], ... [ 74.75, 6.58, 7.08, 400. , 9.9 , 1. , 26.01, 455.17, 4.78, 18.44] ... ]) >>> criteria_types = np.array([1, 1, -1, 1, -1, -1, 1, -1, -1, 1]) >>> weights = equal_weights(matrix) >>> topsis = pm.TOPSIS(normalization_function=norm.vector_normalization) >>> call_kwargs = { ... 'matrix': matrix, ... 'weights': weights, ... 'types': criteria_types ... } >>> results = relevance_identification(topsis, call_kwargs, corr_coef=[pymcdm.correlations.rw, pymcdm.correlations.ws, pymcdm.correlations.rs], ranking_descending=True, excluded_criteria=3) >>> for r in results: ... print(r)
Example 3: Identify relevant criteria in using TOPSIS method and excluding 3 criteria in the problem, and return all partial results for identification process
>>> matrix = np.array([ ... [106.78, 6.75, 2. , 220. , 6. , 1. , 52. , 455.5 , 8.9 , 36.8 ], ... [ 86.37, 7.12, 3. , 400. , 10. , 0. , 20. , 336.5 , 7.2 , 29.8 ], ... [104.85, 6.95, 60. , 220. , 7. , 1. , 60. , 416. , 8.7 , 36.2 ], ... [ 46.6 , 6.04, 1. , 220. , 3. , 0. , 50. , 277. , 3.9 , 16. ], ... [ 69.18, 7.05, 33.16, 220. , 8. , 0. , 35.49, 364.79, 5.39, 33.71], ... [ 66.48, 6.06, 26.32, 220. , 6.53, 0. , 34.82, 304.02, 4.67, 27.07], ... [ 74.48, 6.61, 48.25, 400. , 4.76, 1. , 44.19, 349.45, 4.93, 28.89], ... [ 73.67, 6.06, 19.54, 400. , 3.19, 0. , 46.41, 354.65, 8.01, 21.09], ... [100.58, 6.37, 39.27, 220. , 8.43, 1. , 22.07, 449.42, 7.89, 17.62], ... [ 94.81, 6.13, 50.58, 220. , 4.18, 1. , 21.14, 450.88, 5.12, 17.3 ], ... [ 48.93, 7.12, 21.48, 220. , 5.47, 1. , 55.72, 454.71, 8.39, 19.16], ... [ 74.75, 6.58, 7.08, 400. , 9.9 , 1. , 26.01, 455.17, 4.78, 18.44] ... ]) >>> criteria_types = np.array([1, 1, -1, 1, -1, -1, 1, -1, -1, 1]) >>> weights = equal_weights(matrix) >>> topsis = pm.TOPSIS(normalization_function=norm.vector_normalization) >>> call_kwargs = { ... 'matrix': matrix, ... 'weights': weights, ... 'types': criteria_types ... } >>> results = relevance_identification(topsis, call_kwargs, corr_coef=[pymcdm.correlations.rw, pymcdm.correlations.ws, pymcdm.correlations.rs], ranking_descending=True, excluded_criteria=3, return_all=True) >>> for result in results: >>> for res in result: ... print(r)
Percentage modification
- pysensmcda.criteria.percentage.percentage_modification(weights: ndarray, percentages: int | ndarray, direction: None | ndarray = None, indexes: None | ndarray = None, step: int | float = 1) list[tuple[int | tuple[int], tuple[float], ndarray]][source]
Modify a set of criteria weights based on specified percentage changes, directions, and indexes.
Parameters:
- weightsndarray
1D array representing the initial criteria weights. Should sum up to 1.
- percentagesint | ndarray
Percentage changes to be applied to the criteria weights. If int, the same percentage change is applied to all criteria. If ndarray, it specifies the percentage change for each criterion individually.
- directionNone | ndarray, optional, default=None
Direction of the modification for each criterion. If None, both increase and decrease directions are considered. If ndarray, it specifies the direction (1 for increase, -1 for decrease) for each criterion individually.
- indexesNone | ndarray, optional, default=None
Indexes of the criteria to be modified. If None, all criteria are considered subsequently. If ndarray, it specifies the indexes or combinations of indexes for the criteria to be modified.
- stepint | float, optional, default=1
Step size for the percentage change.
Returns:
- List[Tuple[int | tuple, tuple, ndarray]]
A list of tuples containing information about the modified criteria index, percentage change, and the resulting criteria weights.
Examples:
Example 1: Modify weights with a single percentage change
>>> weights = np.array([0.3, 0.3, 0.4]) >>> percentage = 5 >>> results = percentage_modification(weights, percentage) >>> for r in results: ... print(r)
Example 2: Modify weights with percentages, specific indexes, and step size
>>> weights = np.array([0.3, 0.3, 0.4]) >>> percentages = np.array([5, 5, 5]) >>> indexes = np.array([[0, 1], 2], dtype='object') >>> results = percentage_modification(weights, percentages, indexes=indexes) >>> for r in results: ... print(r)
Example 3: Modify weights with percentages and specific direction for each criterion
>>> weights = np.array([0.3, 0.3, 0.4]) >>> percentages = np.array([6, 4, 5]) >>> direction = np.array([-1, 1, -1]) >>> results = percentage_modification(weights, percentages, direction=direction) >>> for r in results: ... print(r)
Example 4: Modify weights with percentages, specific indexes, and individual step sizes
>>> weights = np.array([0.3, 0.3, 0.4]) >>> percentages = np.array([6, 4, 8]) >>> indexes = np.array([0, 2]) >>> step = 2 >>> results = percentage_modification(weights, percentages, indexes=indexes, step=step) >>> for r in results: ... print(r)
Range modification
- pysensmcda.criteria.range.range_modification(weights: ndarray, range_values: ndarray, indexes: None | ndarray = None, step: float = 0.01) list[tuple[int, float | tuple[float], ndarray]][source]
Modify a set of criteria weights based on specified range values, directions, and indexes.
Parameters:
- weightsndarray
1D array representing the initial criteria weights. Should sum up to 1.
- range_valuesndarray
Range of values for each criterion specifying the allowed changes. Should be given as a two-dimensional array where each row represents a criterion, and the columns represent the lower and upper bounds of the allowed range.
- indexesNone | ndarray, optional, default=None
Indexes of the criteria to be modified. If None, all criteria are considered subsequently. If ndarray, it specifies the indexes or combinations of indexes for the criteria to be modified.
- stepfloat, optional, default=0.01
Step size for the change in given range.
Returns:
- List[Tuple[int, Union[float, Tuple[float, …]], ndarray]]
A list of tuples containing information about the modified criteria index, range change, and the resulting criteria weights.
Examples:
Example 1: Modify weights with a single range change
>>> weights = np.array([0.3, 0.3, 0.4]) >>> range_values = np.array([[0.25, 0.3], [0.3, 0.35], [0.37, 0.43]]) >>> results = range_modification(weights, range_values) >>> for r in results: ... print(r)
Example 2: Modify weights with range values, specific indexes, and step size
>>> weights = np.array([0.3, 0.3, 0.4]) >>> indexes = np.array([[0, 1], 2], dtype='object') >>> range_values = np.array([[0.25, 0.3], [0.3, 0.35], [0.37, 0.43]]) >>> results = range_modification(weights, range_values, indexes=indexes) >>> for r in results: ... print(r)
Example 3: Modify weights with range values and individual step sizes
>>> weights = np.array([0.3, 0.3, 0.4]) >>> range_values = np.array([[0.25, 0.3], [0.3, 0.35], [0.37, 0.43]]) >>> step = 0.02 >>> results = range_modification(weights, range_values, step=step) >>> for r in results: ... print(r)
Criteria removal
- pysensmcda.criteria.removal.remove_criteria(matrix: ndarray, weights: ndarray, indexes: None | int | ndarray = None) list[tuple[int, ndarray, ndarray]][source]
Remove one or more criteria from a decision matrix and adjust corresponding criteria weights.
Parameters:
- matrixndarray
2D array with decision matrix containing multiple criteria and alternatives.
- weightsndarray
1D vector of initial criteria weights.
- indexesNone | int | ndarray, optional, default=None
Index or array of indexes specifying which criteria to remove. If None, one criterion will be removed by default
Returns:
- List[Tuple[int, ndarray, ndarray]]
A list of tuples containing information about the removed criteria, new decision matrix, and adjusted criteria weights.
Examples:
Example 1: no indexes given
>>> matrix = np.array([ ... [1, 2, 3, 4, 4], ... [1, 2, 3, 4, 4], ... [4, 3, 2, 1, 4] ... ]) >>> weights = np.array([0.25, 0.25, 0.2, 0.2, 0.1]) >>> results = remove_criteria(matrix, weights) >>> for result in results: ... print(result)
Example 2: int index given
>>> matrix = np.array([ ... [1, 2, 3, 4, 4], ... [1, 2, 3, 4, 4], ... [4, 3, 2, 1, 4] ... ]) >>> weights = np.array([0.25, 0.25, 0.2, 0.2, 0.1]) >>> results = remove_criteria(matrix, weights, 3) >>> for result in results: ... print(result)
Example 3: array indexes given, one-dimensional
>>> matrix = np.array([ ... [1, 2, 3, 4, 4], ... [1, 2, 3, 4, 4], ... [4, 3, 2, 1, 4] ... ]) >>> weights = np.array([0.25, 0.25, 0.2, 0.2, 0.1]) >>> results = remove_criteria(matrix, weights, np.array([1, 2, 3])) >>> for result in results: ... print(result)
Example 4: array indexes given, elements of array as list
>>> matrix = np.array([ ... [1, 2, 3, 4, 4], ... [1, 2, 3, 4, 4], ... [4, 3, 2, 1, 4] ... ]) >>> weights = np.array([0.25, 0.25, 0.2, 0.2, 0.1]) >>> results = remove_criteria(matrix, weights, np.array([[0, 4], 2, 3], dtype='object')) >>> for result in results: ... print(result)
Weights scenarios
- pysensmcda.criteria.scenarios.generate_weights_scenarios(crit_num: int, step: float, precision: int = 4, cores_num: int | None = None, file_name: str | None = None, return_array: bool = False, sequential: bool = False, save_zeros: bool = True) list | None[source]
Generate scenarios for examining criteria weights based on given criteria number and step of weights space exploration
Parameters:
- crit_numint
The number of criteria.
- stepfloat
The step size used for generating criteria weights.
- precisionint, optional, default=4
The number of decimal places to round the generated criteria weights.
- cores_numint or None, optional, default=None
If provided, the generated scenarios will be generated with given number of processes. If None, all available CPU cores will be used.
- filenamestr or None, optional, default=None or ‘out’
Using parallel version files are always created. Temporary for subsequent processes and main file that contains all results. Temporary files are deleted after completion. If provided, the generated scenarios will be saved to the specified file. If None, scenarios will be returned as a list.
- return_arraybool, optional, default=False
Returns results in a format of nd.array (numpy)
- sequential: bool, optional, default=False
If True code will be run sequentially. Progressbar will be shown and non temporary files created.
- save_zeros: bool, optional, default=True
If True saves weights vectors where zeros are present.
Returns:
- list or None
Depending on return_array parameter, None or nd.array will be returned.
Examples:
Example 1: parallel without array return
>>> generate_weights_scenarios(4, 0.1, 3) >>> # results will be saved to 'out.npy'
Example 2: parallel with array return
>>> scenarios = generate_weights_scenarios(4, 0.1, 3, return_array=True) >>> print(scenarios) >>> [(0.9, 0.1, 0.0, 0.0), (0.8, 0.2, 0.0, 0.0), ...] >>> # results will be saved to 'out.npy'
Example 3: parallel with custom file name
>>> generate_weights_scenarios(4, 0.1, 3, file_name='4crit_0.1') >>> # results will be saved to '4crit_0.1.npy'
Example 3: sequential
>>> generate_weights_scenarios(4, 0.1, 3, sequential=True) >>> print(scenarios) >>> [(0.9, 0.1, 0.0, 0.0), (0.8, 0.2, 0.0, 0.0), ...] >>> # results will not be saved
Example 4: sequential with saving to file
>>> generate_weights_scenarios(4, 0.1, 3, sequential=True, file_name='4crit_0.1') >>> print(scenarios) >>> [(0.9, 0.1, 0.0, 0.0), (0.8, 0.2, 0.0, 0.0), ...] >>> # results will be saved to '4crit_0.1.npy'