def test_FilterNonDominated_strict(): dm = skc.mkdm( matrix=[ [7, 5, 35], [5, 4, 26], [5, 6, 28], [1, 7, 30], [5, 8, 30], ], objectives=[max, max, min], weights=[2, 4, 1], alternatives=["PE", "JN", "AA", "MM", "FN"], criteria=["ROE", "CAP", "RI"], ) expected = skc.mkdm( matrix=[ [7, 5, 35], [5, 4, 26], [5, 6, 28], [1, 7, 30], [5, 8, 30], ], objectives=[max, max, min], weights=[2, 4, 1], alternatives=["PE", "JN", "AA", "MM", "FN"], criteria=["ROE", "CAP", "RI"], ) tfm = filters.FilterNonDominated(strict=True) result = tfm.transform(dm) assert result.equals(expected)
def test_StandarScaler_simple_both(): dm = skcriteria.mkdm( matrix=[[1, 2, 3], [4, 5, 6]], objectives=[min, max, min], weights=[1, 2, 3], ) expected = skcriteria.mkdm( matrix=[ [(1 - 2.5) / 1.5, (2 - 3.5) / 1.5, (3 - 4.5) / 1.5], [(4 - 2.5) / 1.5, (5 - 3.5) / 1.5, (6 - 4.5) / 1.5], ], objectives=[min, max, min], weights=[ (1 - 2) / 0.816496580927726, (2 - 2) / 0.816496580927726, (3 - 2) / 0.816496580927726, ], dtypes=[float, float, float], ) scaler = StandarScaler(target="both") result = scaler.transform(dm) assert result.equals(expected)
def test_FullMultiplicativeForm_only_minimize(): dm = skcriteria.mkdm( matrix=[ [1, 2, 3], [4, 5, 6], [7, 8, 9], ], objectives=[min, min, min], ) expected = RankResult( "FullMultiplicativeForm", ["A0", "A1", "A2"], [1, 2, 3], { "score": np.log([398.42074767, 19.92103738, 4.74310414]), }, ) transformer = VectorScaler(target="matrix") dm = transformer.transform(dm) ranker = FullMultiplicativeForm() result = ranker.evaluate(dm) assert result.equals(expected) assert result.method == expected.method assert np.allclose(result.e_.score, expected.e_.score, atol=1e-4)
def test_ELECTRE2_cebrian2009localizacion(): """ Data From: Cebrián, L. I. G., & Porcar, A. M. (2009). Localización empresarial en Aragón: Una aplicación empírica de la ayuda a la decisión multicriterio tipo ELECTRE I y III. Robustez de los resultados obtenidos. Revista de Métodos Cuantitativos para la Economía y la Empresa, (7), 31-56. """ dm = skcriteria.mkdm( matrix=[ [6, 5, 28, 5, 5], [4, 2, 25, 10, 9], [5, 7, 35, 9, 6], [6, 1, 27, 6, 7], [6, 8, 30, 7, 9], [5, 6, 26, 4, 8], ], objectives=[1, 1, -1, 1, 1], weights=[0.25, 0.25, 0.1, 0.2, 0.2], ) scaler = SumScaler("both") dm = scaler.transform(dm) kselector = ELECTRE2() result = kselector.evaluate(dm) assert np.all(result.rank_ == [3, 2, 1, 3, 1, 3]) np.testing.assert_allclose(result.e_.score, [2.0, 1.5, 1.0, 2.0, 1.0, 2.0])
def test_SKCWeighterABC_flow(decision_matrix): dm = decision_matrix(seed=42) expected_weights = np.ones(dm.matrix.shape[1]) * 42 class Foo(SKCWeighterABC): _skcriteria_parameters = [] def _weight_matrix(self, matrix, **kwargs): return expected_weights transformer = Foo() expected = skcriteria.mkdm( matrix=dm.matrix, objectives=dm.objectives, weights=expected_weights, dtypes=dm.dtypes, alternatives=dm.alternatives, criteria=dm.criteria, ) result = transformer.transform(dm) assert result.equals(expected)
def test_SKCByCriteriaFilterABC_missing_criteria(): dm = skc.mkdm( matrix=[ [7, 5, 35], [5, 4, 26], [5, 6, 28], [1, 7, 30], [5, 8, 30], ], objectives=[max, max, min], weights=[2, 4, 1], alternatives=["PE", "JN", "AA", "MM", "FN"], criteria=["ROE", "CAP", "RI"], ) class FooFilter(filters.SKCByCriteriaFilterABC): def _make_mask(self, matrix, criteria, criteria_to_use, criteria_filters): pass def _coerce_filters(self, filters): return list(filters.keys()), list(filters.values()) tfm = FooFilter({"ZARAZA": 1}) with pytest.raises(ValueError): tfm.transform(dm) tfm = FooFilter({"ZARAZA": 1}, ignore_missing_criteria=True) result = tfm.transform(dm) assert result.equals(dm) and result is not dm
def test_SKCByCriteriaFilterABC_not_implemented_make_mask(): dm = skc.mkdm( matrix=[ [7, 5, 35], [5, 4, 26], [5, 6, 28], [1, 7, 30], [5, 8, 30], ], objectives=[max, max, min], weights=[2, 4, 1], alternatives=["PE", "JN", "AA", "MM", "FN"], criteria=["ROE", "CAP", "RI"], ) class FooFilter(filters.SKCByCriteriaFilterABC): def _make_mask(self, matrix, criteria, criteria_to_use, criteria_filters): return super()._make_mask(matrix, criteria, criteria_to_use, criteria_filters) def _coerce_filters(self, filters): return list(filters.keys()), list(filters.values()) tfm = FooFilter({"ROE": 1}) with pytest.raises(NotImplementedError): tfm.transform(dm)
def test_TOPSIS(): dm = skcriteria.mkdm( matrix=[[1, 0, 3], [0, 5, 6]], objectives=[max, max, max], ) expected = RankResult( "TOPSIS", ["A0", "A1"], [2, 1], { "ideal": [1, 5, 6], "anti_ideal": [0, 0, 3], "similarity": [0.14639248, 0.85360752], }, ) ranker = TOPSIS() result = ranker.evaluate(dm) assert result.equals(expected) assert result.method == expected.method assert np.all(result.e_.ideal == expected.e_.ideal) assert np.allclose(result.e_.anti_ideal, expected.e_.anti_ideal) assert np.allclose(result.e_.similarity, expected.e_.similarity)
def test_MaxScaler_both(decision_matrix): dm = decision_matrix( seed=42, min_alternatives=10, max_alternatives=10, min_criteria=20, max_criteria=20, min_objectives_proportion=0.5, ) matrix = dm.matrix.to_numpy() expected = skcriteria.mkdm( matrix=matrix / np.max(matrix, axis=0, keepdims=True), objectives=dm.objectives, weights=dm.weights / np.max(dm.weights), alternatives=dm.alternatives, criteria=dm.criteria, dtypes=dm.dtypes, ) scaler = MaxScaler(target="both") result = scaler.transform(dm) assert result.equals(expected)
def test_MinMaxScaler_matrix(decision_matrix): dm = decision_matrix( seed=42, min_alternatives=10, max_alternatives=10, min_criteria=20, max_criteria=20, min_objectives_proportion=0.5, ) mtx = dm.matrix.to_numpy() mtx_min = np.min(mtx, axis=0, keepdims=True) mtx_max = np.max(mtx, axis=0, keepdims=True) expected = skcriteria.mkdm( matrix=(mtx - mtx_min) / (mtx_max - mtx_min), objectives=dm.objectives, weights=dm.weights, alternatives=dm.alternatives, criteria=dm.criteria, dtypes=dm.dtypes, ) scaler = MinMaxScaler(target="matrix") result = scaler.transform(dm) assert result.equals(expected)
def test_StandarScaler_matrix(decision_matrix): dm = decision_matrix( seed=42, min_alternatives=10, max_alternatives=10, min_criteria=20, max_criteria=20, min_objectives_proportion=0.5, ) matrix = dm.matrix.to_numpy() expected = skcriteria.mkdm( matrix=(matrix - np.mean(matrix, axis=0, keepdims=True)) / np.std(matrix, axis=0, keepdims=True), objectives=dm.objectives, weights=dm.weights, alternatives=dm.alternatives, criteria=dm.criteria, dtypes=dm.dtypes, ) scaler = StandarScaler(target="matrix") result = scaler.transform(dm) assert result.equals(expected)
def test_MinMaxScaler_weights(decision_matrix): dm = decision_matrix( seed=42, min_alternatives=10, max_alternatives=10, min_criteria=20, max_criteria=20, min_objectives_proportion=0.5, ) expected = skcriteria.mkdm( matrix=dm.matrix, objectives=dm.objectives, weights=(dm.weights - np.min(dm.weights)) / (np.max(dm.weights) - np.min(dm.weights)), alternatives=dm.alternatives, criteria=dm.criteria, dtypes=dm.dtypes, ) scaler = MinMaxScaler(target="weights") result = scaler.transform(dm) assert result.equals(expected)
def test_FullMultiplicativeForm_only_maximize(): dm = skcriteria.mkdm( matrix=[ [1, 2, 3], [4, 5, 6], [7, 8, 9], ], objectives=[max, max, max], ) expected = RankResult( "FullMultiplicativeForm", ["A0", "A1", "A2"], [3, 2, 1], { "score": np.log([0.00682264, 0.13645283, 0.57310187]), }, ) transformer = VectorScaler(target="matrix") dm = transformer.transform(dm) ranker = FullMultiplicativeForm() result = ranker.evaluate(dm) assert result.equals(expected) assert result.method == expected.method assert np.allclose(result.e_.score, expected.e_.score, atol=1e-4)
def test_NegateMinimize_50percent_min(decision_matrix): dm = decision_matrix( seed=42, min_alternatives=10, max_alternatives=10, min_criteria=20, max_criteria=20, min_objectives_proportion=0.5, ) minimize_mask = dm.iobjectives == -1 expected_mtx = np.array(dm.matrix, dtype=float) expected_mtx[:, minimize_mask] = -expected_mtx[:, minimize_mask] inv_dtypes = np.where(dm.iobjectives == -1, float, dm.dtypes) expected = skcriteria.mkdm( matrix=expected_mtx, objectives=np.full(20, 1, dtype=int), weights=dm.weights, alternatives=dm.alternatives, criteria=dm.criteria, dtypes=inv_dtypes, ) inv = NegateMinimize() result = inv.transform(dm) assert result.equals(expected)
def test_EntropyWeighter(decision_matrix): dm = decision_matrix( seed=42, min_alternatives=10, max_alternatives=10, min_criteria=20, max_criteria=20, min_objectives_proportion=0.5, ) entropy = scipy.stats.entropy(dm.matrix, axis=0) expected = skcriteria.mkdm( matrix=dm.matrix, objectives=dm.objectives, weights=entropy / np.sum(entropy), alternatives=dm.alternatives, criteria=dm.criteria, dtypes=dm.dtypes, ) weighter = EntropyWeighter() result = weighter.transform(dm) assert result.equals(expected)
def test_StdWeighter(decision_matrix): dm = decision_matrix( seed=42, min_alternatives=10, max_alternatives=10, min_criteria=20, max_criteria=20, min_objectives_proportion=0.5, ) std = np.std(dm.matrix, axis=0) expected = skcriteria.mkdm( matrix=dm.matrix, objectives=dm.objectives, weights=std / np.sum(std), alternatives=dm.alternatives, criteria=dm.criteria, dtypes=dm.dtypes, ) weighter = StdWeighter() result = weighter.transform(dm) assert result.equals(expected)
def test_WeightedProductModel_enwiki_1015567716(): """ Data from: Weighted product model. (n.d.). Retrieved January 07, 2017, from http://en.wikipedia.org/wiki/Weighted_product_model """ dm = skcriteria.mkdm( matrix=[ [25, 20, 15, 30], [10, 30, 20, 30], [30, 10, 30, 10], ], objectives=[max, max, max, max], weights=[20, 15, 40, 25], ) expected = RankResult( "WeightedProductModel", ["A0", "A1", "A2"], [1, 2, 3], {"score": [-0.50128589, -0.50448471, -0.52947246]}, ) transformer = SumScaler(target="both") dm = transformer.transform(dm) ranker = WeightedProductModel() result = ranker.evaluate(dm) assert result.equals(expected) assert result.method == expected.method assert np.allclose(result.e_.score, expected.e_.score)
def test_FullMultiplicativeForm_with0_fail(): dm = skcriteria.mkdm( matrix=[[1, 2, 3], [4, 0, 6]], objectives=[max, max, max], ) ranker = FullMultiplicativeForm() with pytest.raises(ValueError): ranker.evaluate(dm)
def test_EntropyWeighter_simple_matrix(): dm = skcriteria.mkdm( matrix=[[1, 2], [4, 16]], objectives=[min, max], weights=[1, 2], ) expected = skcriteria.mkdm( matrix=[[1, 2], [4, 16]], objectives=[min, max], weights=[0.589239, 0.410761], ) weighter = EntropyWeighter() result = weighter.transform(dm) assert result.aequals(expected, atol=1e-5)
def test_StdWeighter_simple_matrix(): dm = skcriteria.mkdm( matrix=[[1, 2], [4, 16]], objectives=[min, max], weights=[1, 2], ) expected = skcriteria.mkdm( matrix=[[1, 2], [4, 16]], objectives=[min, max], weights=[0.176471, 0.82352], ) weighter = StdWeighter() result = weighter.transform(dm) assert result.aequals(expected, atol=1e-5)
def test_MultiMOORA_with0_fail(): dm = skcriteria.mkdm( matrix=[[1, 2, 3], [4, 0, 6]], objectives=[max, max, max], ) ranker = MultiMOORA() with pytest.raises(ValueError): ranker.evaluate(dm)
def test_ReferencePointMOORA_kracka2010ranking(): """ Data From: KRACKA, M; BRAUERS, W. K. M.; ZAVADSKAS, E. K. Ranking Heating Losses in a Building by Applying the MULTIMOORA . - ISSN 1392 - 2785 Inz """ dm = skcriteria.mkdm( matrix=[ [33.95, 23.78, 11.45, 39.97, 29.44, 167.10, 3.852], [38.9, 4.17, 6.32, 0.01, 4.29, 132.52, 25.184], [37.59, 9.36, 8.23, 4.35, 10.22, 136.71, 10.845], [30.44, 37.59, 13.91, 74.08, 45.10, 198.34, 2.186], [36.21, 14.79, 9.17, 17.77, 17.06, 148.3, 6.610], [37.8, 8.55, 7.97, 2.35, 9.25, 134.83, 11.935], ], objectives=[min, min, min, min, max, min, max], alternatives=["A1", "A2", "A3", "A4", "A5", "A6"], criteria=["x1", "x2", "x3", "x4", "x5", "x6", "x7"], ) expected = RankResult( "ReferencePointMOORA", ["A1", "A2", "A3", "A4", "A5", "A6"], [4, 5, 1, 6, 2, 3], { "score": [ 0.68934931, 0.69986697, 0.59817104, 0.85955696, 0.6002238, 0.61480595, ], "reference_point": [ 0.34587742, 0.08556044, 0.26245184, 0.00011605, 0.77343790, 0.34960423, 0.81382773, ], }, ) transformer = VectorScaler(target="matrix") dm = transformer.transform(dm) ranker = ReferencePointMOORA() result = ranker.evaluate(dm) assert result.equals(expected) assert result.method == expected.method assert np.allclose(result.e_.score, expected.e_.score) assert np.allclose(result.e_.reference_point, expected.e_.reference_point)
def test_AddValueToZero_simple_weights_gt0(): dm = skcriteria.mkdm( matrix=[[1, 2, 3], [4, 5, 6]], objectives=[min, max, min], weights=[1, 2, 3], ) expected = skcriteria.mkdm( matrix=[[1, 2, 3], [4, 5, 6]], objectives=[min, max, min], weights=[1, 2, 3], ) scaler = AddValueToZero(value=0.5, target="weights") result = scaler.transform(dm) assert result.equals(expected)
def test_AddValueToZero_simple_both(): dm = skcriteria.mkdm( matrix=[[1, 0, 3], [0, 5, 6]], objectives=[min, max, min], weights=[1, 2, 0], ) expected = skcriteria.mkdm( matrix=[[1.5, 0.5, 3], [0.5, 5.5, 6]], objectives=[min, max, min], weights=[1.5, 2.5, 0.5], ) scaler = AddValueToZero(value=0.5, target="both") result = scaler.transform(dm) assert result.equals(expected)
def test_CenitDistance_simple_matrix(): dm = skcriteria.mkdm( matrix=[[1, 0, 3], [0, 5, 6]], objectives=[min, max, min], weights=[1, 2, 0], ) expected = skcriteria.mkdm( matrix=[[-0.0, 0.0, 1.0], [1.0, 1.0, -0.0]], objectives=[min, max, min], weights=[1, 2, 0], ) tfm = CenitDistance() result = tfm.transform(dm) assert result.equals(expected)
def test_PushNegatives_simple_weights_ge0(): dm = skcriteria.mkdm( matrix=[[1, 2, 3], [1, 5, 6]], objectives=[min, max, min], weights=[1, 2, 1], ) expected = skcriteria.mkdm( matrix=[[1, 2, 3], [1, 5, 6]], objectives=[min, max, min], weights=[1, 2, 1], ) scaler = PushNegatives(target="weights") result = scaler.transform(dm) assert result.equals(expected)
def test_PushNegatives_simple_both(): dm = skcriteria.mkdm( matrix=[[1, -2, 3], [-1, 5, 6]], objectives=[min, max, min], weights=[1, 2, -1], ) expected = skcriteria.mkdm( matrix=[[2, 0, 3], [0, 7, 6]], objectives=[min, max, min], weights=[2, 3, 0], ) scaler = PushNegatives(target="both") result = scaler.transform(dm) assert result.equals(expected)
def test_EqualWeighter_simple_matrix(): dm = skcriteria.mkdm( matrix=[[1, 2], [4, 5]], objectives=[min, max], weights=[1, 2], ) expected = skcriteria.mkdm( matrix=[[1, 2], [4, 5]], objectives=[min, max], weights=[1, 1], ) weighter = EqualWeighter(base_value=2) result = weighter.transform(dm) assert result.equals(expected)
def test_CenitDistance_diakoulaki1995determining(): """ Data from: Diakoulaki, D., Mavrotas, G., & Papayannakis, L. (1995). Determining objective weights in multiple criteria problems: The critic method. Computers & Operations Research, 22(7), 763-770. """ dm = skcriteria.mkdm( matrix=[ [61, 1.08, 4.33], [20.7, 0.26, 4.34], [16.3, 1.98, 2.53], [9, 3.29, 1.65], [5.4, 2.77, 2.33], [4, 4.12, 1.21], [-6.1, 3.52, 2.10], [-34.6, 3.31, 0.98], ], objectives=[max, max, max], weights=[61, 1.08, 4.33], ) expected = skcriteria.mkdm( matrix=[ [1.0, 0.21243523, 0.99702381], [0.57845188, 0.0, 1.0], [0.53242678, 0.44559585, 0.46130952], [0.45606695, 0.78497409, 0.19940476], [0.41841004, 0.65025907, 0.40178571], [0.40376569, 1.0, 0.06845238], [0.29811715, 0.84455959, 0.33333333], [0.0, 0.79015544, 0.0], ], objectives=[max, max, max], weights=[61, 1.08, 4.33], ) tfm = CenitDistance() result = tfm.transform(dm) assert result.aequals(expected)
def test_Critic_diakoulaki1995determining(): """ Data from: Diakoulaki, D., Mavrotas, G., & Papayannakis, L. (1995). Determining objective weights in multiple criteria problems: The critic method. Computers & Operations Research, 22(7), 763-770. """ dm = skcriteria.mkdm( matrix=[ [61, 1.08, 4.33], [20.7, 0.26, 4.34], [16.3, 1.98, 2.53], [9, 3.29, 1.65], [5.4, 2.77, 2.33], [4, 4.12, 1.21], [-6.1, 3.52, 2.10], [-34.6, 3.31, 0.98], ], objectives=[max, max, max], weights=[61, 1.08, 4.33], ) expected = skcriteria.mkdm( matrix=[ [61, 1.08, 4.33], [20.7, 0.26, 4.34], [16.3, 1.98, 2.53], [9, 3.29, 1.65], [5.4, 2.77, 2.33], [4, 4.12, 1.21], [-6.1, 3.52, 2.10], [-34.6, 3.31, 0.98], ], objectives=[max, max, max], weights=[0.20222554, 0.48090173, 0.31687273], ) weighter = Critic() result = weighter.transform(dm) assert result.aequals(expected)