Scalarization-based methods¶
In DESDEO, scalarization-based methods are implemented in a modular fashion. This means that no method is provided per se, but instead the different components required to build the method are provided. This idea is best illustrated by examples.
Example: The achievement scalarizing function method¶
In the achievement scalarizing function (ASF) method, a scalarization function is solved iteratively with new preference information provided by a decision maker. The preference information consists in this case of a reference point containing aspiration levels.
Suppose we have an instance of Problem defined as problem:
from desdeo.problem.testproblems import dtlz2
# an instance of Problem with three objectives 'f_1', 'f_2', and 'f_3'
problem = dtlz2(n_objectives=3, n_variables=5)
Now, to "implement" the ASF method, we first need preference information
from the decision maker. Here, reference_point is a dictionary of aspiration
levels, one for each objective function.
# a reference point with an aspiration level for each objective function
reference_point = {"f_1": 0.5, "f_2": 0.4, "f_3": 0.3}
The ASF is defined as follows:
$$ S_\text{AS}(F(\mathbf{x}); \mathbf{\bar{z}}, \mathbf{z}^\star, \mathbf{z}^\text{nad}) = \underset{i=1,\ldots,k}{\text{max}} \left[ \frac{f_i(\mathbf{x}) - \bar{z}_i}{z^\text{nad}_i - (z_i^\star - \delta)} \right] + \rho\sum_{i=1}^{k} \frac{f_i(\mathbf{x})}{z_i^\text{nad} - (z_i^\star - \delta)}, $$
where the variables (F(\mathbf{x}) = [f_1(\mathbf{x}),\dots,f_k(\mathbf{x})], \mathbf{z}^\star, \mathbf{z}^\text{nad})
are assumed to be available through the instance of problem. The variable (\mathbf{\bar{z}}) is our reference point,
which is provided by a decision maker.
Now, to create the ASF method, we add the ASF to the instance of problem. We use the
differentiable variant add_asf_diff here:
from desdeo.tools import add_asf_diff
problem_w_asf, target = add_asf_diff(problem, symbol="s_asf", reference_point=reference_point)
In the above example, add_asf_diff creates an instance of the ASF where the variables of the function have been
replaced by the corresponding variables found in the instance of problem. When adding scalarization functions of
any type, at least the problem and a symbol must be supplied. In this example, the reference point is also
needed. The symbol is important because it is used later in solvers to specify
which scalarization function should be optimized. add_asf_diff returns a copy of the problem with the added
scalarization (problem_w_asf) and the symbol of the added scalarization function (target), which here is s_asf.
Note
When adding scalarization functions of any kind, the returned symbol is very important because it is used to specify to solvers which scalarization function should be optimized. The symbol must be unique inside the instance of problem, i.e., no other field of a `problem` should share the same symbol.
To solve the scalarized problem, we use a solver. For instance, PyomoIpoptSolver interfaces with the Ipopt
solver. To solve the problem with it, we do:
from desdeo.tools import PyomoIpoptSolver
solver = PyomoIpoptSolver(problem_w_asf)
result = solver.solve(target)
As mentioned, the target symbol defined previously is now important so that we can tell the solver what
to optimize when solving the scalarized problem. The solver returns a result object from which the optimal
variables, objective values, and other information can be read. This iterative pattern, providing a reference
point, scalarizing, and solving, is the basic building block of scalarization-based interactive methods in DESDEO.