Using GDM SCORE bands (consensus reaching phase)¶
Here, we illustrate how to use the SCORE bands based GDM implementation in DESDEO. This method assumes that the analyst has generated a set of Pareto optimal solutions and that the decision makers will choose from among these solutions. No new solutions must be generated.
First, we import the necessary modules and load the data.
from copy import deepcopy as copy
import polars as pl
from desdeo.gdm.score_bands import SCOREBandsGDMConfig, score_bands_gdm
from desdeo.tools.score_bands import KMeansOptions, SCOREBandsConfig, plot_score
# data = pl.read_csv("https://raw.githubusercontent.com/light-weaver/iterative-pareto-representer/refs/heads/main/data/forest.csv")
data = pl.read_csv("../../datasets/dmitry_forest_problem_non_dom_solns.csv")
objs = data.columns
descriptive_names = {
"Rev": "Harvest Revenue",
"HA": "Habitat Availability",
"Carb": "Carbon Storage",
"DW": "Deadwood Volume",
}
units = {"Rev": "million €", "HA": "(unitless)", "Carb": "thousand Mg C", "DW": "thousand m³"}
data.head()
| Rev | HA | Carb | DW |
|---|---|---|---|
| f64 | f64 | f64 | f64 |
| 152.580066 | 20208.082787 | 3879.395281 | 209.184407 |
| 114.740953 | 19197.839047 | 4179.235633 | 218.137467 |
| 134.561958 | 19028.754571 | 4100.362863 | 217.745341 |
| 110.57816 | 17804.39651 | 4397.186981 | 199.641147 |
| 168.399967 | 19569.240864 | 3989.666422 | 212.227667 |
We can now configure the consensus reaching phase of GDM SCORE bands.
We choose to use the K-Means clustering method (with 4 clusters) to classify the solutions into bands. We also modify the distance_parameter and interval_size
from their default values. You can read more details about these parameters in the
documentation of the SCOREBandsConfig and SCOREBandsGDMConfig classes.
Once the configuration is done, we can run the GDM SCORE bands method.
score_config = SCOREBandsGDMConfig(
score_bands_config=SCOREBandsConfig(
dimensions=objs,
clustering_algorithm=KMeansOptions(n_clusters=4),
distance_parameter=0.3,
interval_size=0.9,
descriptive_names=descriptive_names,
units=units,
),
from_iteration=None,
)
# First iteration
state = score_bands_gdm(data=data, config=score_config, state=[], votes=None)
iteration = 1
# Doing this step fixes the parameters like axis positions to the ones
# used in the first iteration.
# Useful when we want to keep the axis positions same across iterations.
score_config.score_bands_config = state[-1].score_bands_result.options
score_config.score_bands_config.axis_positions = state[-1].score_bands_result.axis_positions
# If you want to change clustering options between iterations:
score_config = copy(score_config)
# score_config.score_bands_config.clustering_algorithm = DimensionClusterOptions(n_clusters=n_clusters, dimension_name="Rev")
# score_config.score_bands_config.clustering_algorithm = KMeansOptions(n_clusters=n_clusters)
def plot(iteration):
"""Just a convenience function to plot results from different iterations."""
if iteration > len(state):
raise ValueError(f"Iteration {iteration} has not been computed yet.")
if state[iteration - 1].previous_iteration is None:
text = ", the initial iteration"
else:
text = f", continuing from {state[iteration - 1].previous_iteration}"
print(f"Results from iteration {iteration}{text}:")
return plot_score(
(
data.with_row_index(name="index")
.filter(pl.col("index").is_in(state[iteration - 1].relevant_ids))
.drop("index")
),
state[iteration - 1].score_bands_result,
)
plot(iteration=1).show(renderer="notebook", include_plotlyjs="cdn")
Results from iteration 1, the initial iteration: