Metadata-Version: 2.4
Name: mcda-core
Version: 0.2.0
Summary: Foundation data structures and interfaces for the MCDA Python ecosystem
Author-email: Gilles Dejaegere <gilles.dejaegere@ulb.be>
License-Expression: MIT
Project-URL: Repository, https://gitlab.com/code-smg/mcda-core
Keywords: mcda,mcdm,multi-criteria,decision,promethee,electre
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: numpy>=1.25
Requires-Dist: pandas>=2.0
Dynamic: license-file

# mcda-core

Foundation library for the MCDA Python ecosystem. Provides the shared data structures, abstract interfaces, data transformations, and quality indicators that all other libraries in the ecosystem build on.

## Installation

Not yet published on PyPI. Install from source in editable mode:

```bash
git clone https://gitlab.com/code-smg/mcda-core.git
pip install -e mcda-core
```

Python ≥ 3.9, NumPy ≥ 1.25, pandas ≥ 2.0.

## Quick start

```python
import numpy as np
import pandas as pd
from mcda_core import PerformanceTable, minmax, zscore

# Build a performance table from raw values
table = PerformanceTable(
    values=np.array([
        [80.0, 20.0, 10.0],
        [65.0, 35.0, 18.0],
        [90.0, 15.0, 14.0],
    ]),
    alternatives=["A", "B", "C"],
    criteria=["cost", "quality", "CO2"],
    directions=[-1, 1, -1],  # minimise cost and CO2, maximise quality
)

# Or load from a CSV
df = pd.read_csv("data.csv", index_col="alternative")
table = PerformanceTable.from_dataframe(df, directions=[-1, 1, -1])

# Normalise — returns a new (immutable) PerformanceTable
norm = minmax(table)

# Convert minimisation criteria to maximisation before passing to a method
table_max = table.as_maximization()
```

## What's included

### `PerformanceTable`

The central data structure — a frozen dataclass wrapping a `(n_alternatives, n_criteria)` float array together with:

| attribute | type | default |
|-----------|------|---------|
| `values` | `NDArray` shape `(n, m)` | required |
| `alternatives` | `list[str]` | `None` |
| `criteria` | `list[str]` | `None` |
| `criteria_types` | `list[str]` | all `"cardinal"` |
| `directions` | `list[int]` | all `+1` (maximise) |

Key methods: `from_dataframe()`, `as_maximization()`, `to_dataframe()`, `.shape`.

### Interfaces

| class | purpose |
|-------|---------|
| `MCDAMethod[P]` | Abstract base for all MCDA methods — requires `fit()` and `result()` |
| `MCDAParameters` | Abstract base for method parameters |
| `ValuedPreferenceScoringModel` | Protocol for methods that expose both `pairwise_preferences` and `scores` |

`KEY_WEIGHTS` is the shared string constant for the weights key.

### Transformations

All transformations take a `PerformanceTable` and return a new one (metadata preserved):

| function | formula |
|----------|---------|
| `minmax(table)` | `(x − min) / (max − min)` → [0, 1] |
| `zscore(table)` | `(x − μ) / σ` |
| `sum_normalization(table)` | `x / Σx` |
| `max_scaling(table)` | `x / max(|x|)` |
| `invert_criteria(table)` | Flip criteria with `direction = −1`; method: `"range"` (default) or `"sign"` |

All functions accept an optional `criteria` argument (list of column indices) to apply the transformation to a subset of criteria.

### Quality indicators

Operate on any `ValuedPreferenceScoringModel` (e.g. `PrometheeII`):

| function | measures |
|----------|---------|
| `r_squared(model)` | How well scores explain the pairwise preference matrix (rank-1 approximation) |
| `additive_transitivity_index(model)` | Magnitude of additive transitivity violations (0 = perfect) |
| `pairwise_agreement_ratio(model)` | Fraction of pairs where preference order agrees with score order |
| `spectral_rank2_energy_ratio(model)` | Spectral compatibility with a score-based representation |

## Ecosystem

This library is the foundation of a modular MCDA ecosystem:

```
mcda-core          ← you are here
├── mcda-methods   (ELECTRE I, MAUT)
├── promethee      (PROMETHEE I/II/Gamma/Sort — lab-maintained)
└── mcda-viz       (visualisation dashboards)
```

We welcome contributions: new method libraries only need to depend on `mcda-core` and inherit from `MCDAMethod` to be fully compatible with the rest of the ecosystem.

## License

MIT — see [LICENSE](LICENSE).
