Metadata-Version: 2.4
Name: mcda-promethee
Version: 0.3.0
Summary: PROMETHEE I/II/Gamma/Sort MCDA methods
Author-email: Gilles Dejaegere <gilles.dejaegere@ulb.be>
License-Expression: MIT
Project-URL: Repository, https://gitlab.ulb.be/smg/promethee
Keywords: mcda,mcdm,multi-criteria,decision,promethee
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcda-core>=0.2.1
Requires-Dist: numpy>=1.25
Dynamic: license-file

# promethee

Python implementation of the **PROMETHEE** family of MCDA (Multi-Criteria Decision Analysis) methods, maintained by the [SMG](https://cvchercheurs.ulb.ac.be/Site/unite/ULB806.php) research group. Built on [mcda-core](https://gitlab.ulb.be/smg/mcda-core).

Implements PROMETHEE I (partial ranking), PROMETHEE II (complete ranking), PROMETHEE Gamma, and PROMETHEE Sort, with all six standard preference functions.

## Installation

```bash
pip install mcda-promethee
```

Python ≥ 3.9.

## Quick start

```python
import numpy as np
from promethee import PrometheeII, PerformanceTable, ParametersPromethee, build_preference_functions

# 4 countries evaluated on 2 indicators
table = PerformanceTable(
    values=np.array([
        [77.2, 0.887],
        [76.5, 0.832],
        [80.1, 0.919],
        [73.4, 0.798],
    ]),
    alternatives=["Country A", "Country B", "Country C", "Country D"],
    criteria=["life_expectancy", "education_index"],
    directions=[1, 1],  # maximise both
)

weights = np.array([0.5, 0.5])
prefs = build_preference_functions([
    ("v_shape_with_indifference", {"p": 5.0, "q": 1.0}),
    ("v_shape_with_indifference", {"p": 0.08, "q": 0.02}),
])

params = ParametersPromethee(weights=weights, preference_functions=prefs)
model = PrometheeII(performance_table=table, parameters=params)
model.fit()

print(model.net_flows)   # φ score per alternative
print(model.ranking)     # indices sorted best → worst
```

Parameters can also be loaded from a JSON file (see `tests/data/epi_parameters.json` for an example):

```python
import json
from promethee import ParametersPromethee

with open("parameters.json") as f:
    params = ParametersPromethee.from_dict(json.load(f))
```

## Preference functions

All six standard PROMETHEE preference functions are available:

| kind string | parameters | description |
|-------------|------------|-------------|
| `"usual"` | — | Full preference for any positive difference |
| `"u_shape"` | `q` | Step at indifference threshold |
| `"v_shape"` | `p` | Linear up to preference threshold |
| `"v_shape_with_indifference"` | `q`, `p` | Linear between indifference and preference thresholds |
| `"level"` | `q`, `p` | Half preference in the intermediate zone |
| `"gaussian"` | `s` | Smooth Gaussian curve (inflection point `s`) |

```python
from promethee import build_preference_functions

prefs = build_preference_functions([
    ("usual", {}),
    ("v_shape_with_indifference", {"q": 2.0, "p": 8.0}),
    ("gaussian", {"s": 3.0}),
])
```

## API reference

### `PrometheeII`

Computes a complete ranking via net flows φ.

| property | description |
|----------|-------------|
| `net_flows` | φ score per alternative, shape `(n,)` |
| `scores` | alias for `net_flows` |
| `pairwise_preferences` | aggregated preference matrix π, shape `(n, n)` |
| `monocriterion_net_flows` | mono-criterion net flows φ_k, shape `(n, m)` |
| `ranking` | indices sorted best → worst |
| `result()` | returns `net_flows` |

All properties trigger `fit()` automatically if not already called.

### `ParametersPromethee`

| field | type | description |
|-------|------|-------------|
| `weights` | `ndarray (m,)` | criterion weights (need not sum to 1) |
| `preference_functions` | `Sequence[PreferenceFunction]` | one per criterion |

Constructors:
- `ParametersPromethee(weights, preference_functions)` — direct
- `ParametersPromethee.from_dict(data)` — from a parameter dictionary
- `ParametersPromethee.from_weights_and_criteria(weights, criteria_types, p, q)` — shorthand using V-shape with indifference

### Quality indicators

`PrometheeII` implements the `ValuedPreferenceScoringModel` protocol, giving access to quality indicators:

```python
from promethee import r_squared, additive_transitivity_index

print(r_squared(model))                   # how well φ explains π
print(additive_transitivity_index(model)) # transitivity violations (0 = perfect)
```

## Other algorithms

| class | description | import path |
|-------|-------------|-------------|
| `PrometheeI` | Partial ranking via positive/negative flows | `promethee.algorithms.promethee1` |
| `PrometheeGamma` | Extends II with γ-based incomparability detection ([Dejaegere & De Smet, 2023](https://onlinelibrary.wiley.com/doi/full/10.1002/mcda.1805)) | `promethee.algorithms.promethee_gamma` |

`PrometheeGamma` uses `ParametersPrometheeGamma`, which extends `ParametersPromethee` with three additional fields: `Pf`, `Ti`, `Tj`.

## Ecosystem

Part of the modular MCDA Python ecosystem. See [mcda-core](https://gitlab.ulb.be/smg/mcda-core) for the full picture.

## License

MIT — see [LICENSE](LICENSE).
