The Scenario Modeller library is designed to natively support MCDA and AHP (Analytic Hierarchy Process) through its Prioritise stage. This guide explains how to leverage the built-in multi-criteria plugin to rank any spatial unit (buildings, parcels, H3 cells) based on weighted stakeholder preferences.
In a simulation, MCDA typically operates at the Prioritise stage. While Filter determines who is eligible (binary), Prioritise determines the order of merit (ranking).
- Analytic Hierarchy Process (AHP): A method to derive weights from pairwise comparisons of criteria.
- Weighted Sum Model (WSM): The actual math applied to each entity using those weights to calculate a "Priority Score."
The library provides a specialized plugin createMultiCriteriaPrioritiserPlugin designed for generality. It does not assume specific field names, making it compatible with any data schema.
import { createMultiCriteriaPrioritiserPlugin } from 'interactive-scenario-modeller/plugins/optimization';
const prioritiser = createMultiCriteriaPrioritiserPlugin({
criteria: [
{
name: 'carbon',
weight: 0.5, // Derived from AHP
getValue: (e) => e.carbonPotential,
direction: 1 // Higher is better
},
{
name: 'cost',
weight: 0.3,
getValue: (e) => e.estimatedCost,
direction: -1 // Lower cost is better
}
],
// Optional: property name to store the final calculated priority score back on the entity
scoreProperty: 'priority_score'
});
const intervention = new Intervention('AHP-Driven Rollout', {
prioritise: prioritiser.prioritise,
// ...
});One of the library's strengths is the ability to adjust weights mid-simulation. By default, the plugin looks at context.state.mcdaWeights.
Scenario managers can shift priorities over time (e.g., focusing on early carbon wins, then shifting to equity later):
const intervention = new Intervention('Steered Rollout', {
prioritise: prioritiser.prioritise,
initYear: (year, context) => {
if (year >= 2030) {
// Shift priority to equity after 2030
context.state.mcdaWeights = {
carbon: 0.2,
cost: 0.2,
equity: 0.6
};
}
}
});Rank parcels for green infrastructure, balancing flood risk reduction, air quality improvement, and land cost.
- Criteria:
floodMitigation(max),pm25Reduction(max),landValue(min).
Rank neighborhoods for health program rollout, balancing infection rates and accessibility.
- Criteria:
prevalenceRate(max),distToClinic(min),avgAge(max).
Rank hexagonal cells for EV charging hubs based on proximity to main roads and existing grid headroom.
- Criteria:
distanceToA_Road(min),availableCapacity(max),trafficFlow(max).
- Generality: Always use functional
getValuegetters. Avoid hardcoding properties likeentity.cost. - Normalization: The standard Weighted Sum Model works best when values are on similar scales (e.g., 0-1 or 0-100). If your data units are drastically different (e.g., £Millions vs 0.1 Carbon), pre-normalize your data in the
FacetAdapteror inside thegetValuefunction. - Performance: The plugin uses standard JavaScript
sort(). For very large datasets (50k+ entities), ensure yourgetValuefunctions are optimized (e.g., O(1) property lookups).
This document reflects the implementation as of version 0.1.0.