Metadata-Version: 2.4
Name: mcda-methods
Version: 0.1.0
Summary: General-purpose MCDA methods (ELECTRE I, MAUT) built on mcda-core
Author-email: Gilles Dejaegere <gilles.dejaegere@ulb.be>
License-Expression: MIT
Project-URL: Repository, https://gitlab.ulb.be/smg/mcda-methods
Keywords: mcda,mcdm,multi-criteria,decision,electre,maut
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
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.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcda-core>=0.2.1
Requires-Dist: numpy>=1.25
Requires-Dist: pandas>=2.0
Dynamic: license-file

# mcda-methods

General-purpose MCDA methods built on [mcda-core](https://gitlab.ulb.be/smg/mcda-core), maintained by the [SMG](https://cvchercheurs.ulb.ac.be/Site/unite/ULB806.php) research group. Currently provides **ELECTRE I** (choice problems) and **MAUT** (ranking by multi-attribute utility).

This library is a home for methods that do not yet have a dedicated library. When a method grows large enough to warrant its own package, it will be spun off into a separate repository.

## Installation

```bash
pip install mcda-methods
```

Python ≥ 3.10.

## Quick start

### ELECTRE I

Selects a *kernel* — the best alternatives in a choice problem — via concordance and veto.

```python
import numpy as np
from mcda_methods import ElectreI, PerformanceTable, ParametersElectre

table = PerformanceTable(
    values=np.array([
        [8.0, 3.0, 5.0],
        [6.0, 7.0, 4.0],
        [5.0, 6.0, 9.0],
        [7.0, 5.0, 6.0],
    ]),
    alternatives=["A", "B", "C", "D"],
    criteria=["C1", "C2", "C3"],
)

params = ParametersElectre(
    weights=np.array([0.4, 0.3, 0.3]),
    lambda_threshold=0.65,         # concordance threshold for outranking
    veto_thresholds=np.array([]),  # no veto (optional)
)

model = ElectreI(performance_table=table, parameters=params)
model.fit()

print(model.concordance)   # (n, n) concordance matrix
print(model.outranking)    # (n, n) binary outranking matrix
print(model.kernel)        # binary array: 1 = alternative is in the kernel
```

### MAUT

Ranks alternatives via weighted piecewise-linear marginal utility functions.

```python
import numpy as np
from mcda_methods import MAUT, PerformanceTable, ParametersMAUT

table = PerformanceTable(
    values=np.array([[80.0, 20.0], [65.0, 35.0], [90.0, 15.0]]),
    alternatives=["A", "B", "C"],
    criteria=["cost", "quality"],
)

params = ParametersMAUT(
    weights=np.array([0.6, 0.4]),
    breakpoints=[np.array([60.0, 80.0, 100.0]),   # breakpoints per criterion
                 np.array([10.0, 25.0,  40.0])],
    value_functions=[np.array([0.0, 0.5, 1.0]),   # utility at each breakpoint
                     np.array([0.0, 0.7, 1.0])],
)

model = MAUT(performance_table=table, parameters=params)
model.fit()

print(model.utilities)             # weighted utility score per alternative
print(model.ranking)               # indices sorted best → worst
print(model.mono_criterion_scores())  # unweighted marginal utilities (n × m)
```

Parameters can also be loaded from a JSON file:

```python
import json
from mcda_methods import ParametersMAUT

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

Expected JSON keys: `"weights"`, `"breakpoints"`, `"value_functions"`.

## API reference

### `ElectreI`

| attribute / property | description |
|----------------------|-------------|
| `concordance` | `(n, n)` concordance matrix |
| `veto` | `(n, n)` binary veto matrix |
| `outranking` | `(n, n)` binary outranking matrix |
| `kernel` | binary `(n,)` array — `1` = in kernel, or `None` if no kernel exists |
| `result()` | returns `outranking` |
| `is_valid(kernel)` | check whether a given set is a valid kernel |

### `ParametersElectre`

| field | type | description |
|-------|------|-------------|
| `weights` | `ndarray (m,)` | criterion weights |
| `lambda_threshold` | `float` | concordance threshold (typically 0.5–1.0) |
| `veto_thresholds` | `ndarray (m,)` | per-criterion veto threshold (empty = no veto) |

### `MAUT`

| attribute / property | description |
|----------------------|-------------|
| `utilities` | weighted utility score per alternative, shape `(n,)` |
| `scores` | alias for `utilities` |
| `ranking` | indices sorted best → worst |
| `result()` | returns `utilities` |
| `mono_criterion_scores()` | unweighted marginal utilities, shape `(n, m)` |
| `weighted_utility_difference(i, j)` | criterion-wise weighted utility difference, shape `(m,)` |
| `MAUT.from_normalized(maut_norm, pt_raw)` | construct a MAUT that operates on raw (unnormalized) values |

### `ParametersMAUT`

| field | type | description |
|-------|------|-------------|
| `weights` | `ndarray (m,)` | criterion weights |
| `breakpoints` | `list[ndarray]` | breakpoint values per criterion (ascending) |
| `value_functions` | `list[ndarray]` | utility at each breakpoint per criterion |

## 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).
