Version: 0.6.1

# Multi-Criteria Decision Making (MCDM)¶

The focus of pymoo is on optimization methods itself. However, some basic multi-criteria decision making methods are available:

## Compromise Programming¶

We can use any scalarization method and use it for post-processing. Let us assume our algorithm has converged to the Pareto-front:

[1]:

from pymoo.problems import get_problem

F = get_problem("zdt1").pareto_front()


Then, we initialize weights and our decomposition function:

[2]:

import numpy as np

from pymoo.decomposition.asf import ASF

weights = np.array([0.5, 0.5])
decomp = ASF()


We apply the decomposition and retrieve the best value (here minimum):

[3]:

I = decomp(F, weights).argmin()
print("Best regarding decomposition: Point %s - %s" % (I, F[I]))

Best regarding decomposition: Point 38 - [0.38383838 0.38045308]


Visualize it:

[4]:

from pymoo.visualization.scatter import Scatter

plot = Scatter()
plot.do()
plot.apply(lambda ax: ax.arrow(0, 0, 0.5, 0.5, color='black',
plot.show()

[4]:

<pymoo.visualization.scatter.Scatter at 0x7f8644b16670>


## Pseudo-Weights¶

A simple way to chose a solution out of a solution set in the context of multi-objective optimization is the pseudo-weight vector approach proposed in [26]. Respectively, the pseudo weight $$w_i$$ for the i-ith objective function can be calculated by:

$$w_i = \frac{(f_i^{max} - f_i {(x)}) \, /\, (f_i^{max} - f_i^{min})}{\sum_{m=1}^M (f_m^{max} - f_m (x)) \, /\, (f_m^{max} - f_m^{min})}$$

This equation calculates the normalized distance to the worst solution regarding each objective $$i$$. Please note that for non-convex Pareto fronts the pseudo weight does not correspond to the result of an optimization using the weighted sum. However, for convex Pareto-fronts the pseudo weights are an indicator of the location in the objective space.

[5]:

from pymoo.mcdm.pseudo_weights import PseudoWeights
from pymoo.util.ref_dirs import get_reference_directions
from pymoo.visualization.petal import Petal

ref_dirs = get_reference_directions("das-dennis", 4, n_partitions=12)
F = get_problem("dtlz1").pareto_front(ref_dirs)

weights = np.array([0.25, 0.25, 0.25, 0.25])
a, pseudo_weights = PseudoWeights(weights).do(F, return_pseudo_weights=True)

weights = np.array([0.4, 0.20, 0.15, 0.25])
b, pseudo_weights = PseudoWeights(weights).do(F, return_pseudo_weights=True)

plot = Petal(bounds=(0, 0.5), reverse=True)
plot.show()

[5]:

<pymoo.visualization.petal.Petal at 0x7f8644b09c70>


Furthermore, high trade-off points are usually of interest. We have implemented the trade-off metric proposed in [28]. An example for 2 and 3 dimensional solution is given below:

[6]:

import os

import numpy as np
from pymoo.visualization.scatter import Scatter

I = dm(pf)

plot = Scatter()
plot.show()

[6]:

<pymoo.visualization.scatter.Scatter at 0x7f86444928e0>

[7]:

pf = np.loadtxt("knee-3d.out")

I = dm(pf)

plot = Scatter(angle=(10, 140))

[7]:

<pymoo.visualization.scatter.Scatter at 0x7f8644eb02b0>