How to get your multi-objective optimization problem working with DESDEO

This section describes the different ways you can get your data, model or simulation corresponding to a multi-objective optimization problem working with DESDEO. Currently, there are three approaches to adding a new problem: creating the model in Python, importing a list of solutions as data from a CSV, or interfacing to another language via Thrift.

Creating the model in Python

This approach is based around the classes in desdeo.problem.porcelain. This section walks through the process of defining the cylinder problem: desdeo.problem.toy.CylinderProblem. You can work through the cylinder problem notebook to gain familiarity with the cylinder problem.

from desdeo.problem.porcelain import Objective, PorcelainProblem, Variable

class CylinderProblem(PorcelainProblem):
   """
   A description of the problem goes here.
   """

The first step is to import the classes we need and create a new class which inherits from desdeo.problem.porcelain.PorcelainProblem. You should always add a docstring describing the problem so it can be displayed in the notebook interface.

    r = Variable(low=5, high=15, start=10, name="Radius")
    h = Variable(low=5, high=25, start=10, name="Height")

Next, we can define variables using the desdeo.problem.porcelain.Variable class. Here, two variables r and h are defined as the radius and height and given a range of acceptable values, a starting value and a display name.

    @Objective("Volume", maximized=True)
    def volume(r, h):
        return math.pi * r ** 2 * h

Now we define one of the objectives: maximizing the volume of the cylinder. First we define a function that takes all variables r and h in the form we have just named them. The body of the function is the formula for the volume of a cylinder \(\pi r^2 h\), translated to Python code. The function is then decorated with the desdeo.problem.porcelain.Objective class where it is given a display name and the direction (maximized versus minimized) is chosen.

    @Objective("Surface Area", maximized=False)
    def surface_area(r, h):
        return 2 * math.pi * r ** 2 + 2 * math.pi * r * h

    @Objective("Height Difference", maximized=False)
    def height_diff(r, h):
        return abs(h - 15.0)

We now define the other objectives, setting maximized=False to define them as minimization problems.

    class Meta:
        name = "Cylinder Problem"

Lastly, we define the inner class Meta which is where extra settings are stored. Here, we just define the display name for the problem.

Importing a list of solutions as data

In this approach, you start by generating a list of solutions and write out their corresponding objective values to a CSV file <https://en.wikipedia.org/wiki/Comma-separated_values>. DESDEO can then by used to find the row corresponding to the best solution according to some preferences.

The main class involved here is desdeo.problem.PreGeneratedProblem. Usage is simple, just pass in a filename parameter:

PreGeneratedProblem(
   filename="/path/to/my/file.csv")
)

PreGeneratedProblem only works with the desdeo.optimization.PointSearch (single-objective) optimization method. So a full example using ENAUTILUS would look like:

ENAUTILUS(
    PreGeneratedProblem(
        filename="/path/to/my/file.csv"
    ),
    PointSearch,
)

Interfacing to another language via Thrift

In some cases, your multi-objective optimization problem may be defined in terms of simulation software you already have available. In order to transfer information from the simulation to DESDEO, a Thrift interface is provided.

(Coming soon)