Analytical problem

Defining a problem with an explicit mathematical representation is straightforward.

As an example, consider the following multiobjective optimization problem:

\begin{equation} \begin{aligned} & \underset{\mathbf x}{\text{min}} & & x_1^2 - x_2; x_2^2 - 3x_1 \\ & \text{s.t.} & & x_1 + x_2 \leq 10 \\ & & & \mathbf{x} \; \in S, \\ \end{aligned} \end{equation}

where the feasible region is

\begin{equation} x_i \in \left[-5, 5\right] \; \forall i \;\in \left[1,2\right]. \end{equation}

Begin by importing the necessary classes:

[1]:
from desdeo_problem import Variable, ScalarObjective, ScalarConstraint, ScalarMOProblem

Define the variables:

[2]:
# Args: name, starting value, lower bound, upper bound
x1 = Variable("x_1", 0, -0.5, 0.5)
x2 = Variable("x_2", 0, -0.5, 0.5)

Define the objectives, notice the argument of the callable objective function, it is assumed to be array-like.

[3]:
# Args: name, callable
obj1 = ScalarObjective("f_1", lambda x: x[:,0]**2 - x[:,1])
obj2 = ScalarObjective("f_2", lambda x: x[:,1]**2 - 3*x[:,0])

Define the constraints. Constraint may depend on objective function as well (second argument to the lambda, notice the underscore). In that case, the objectives should not be defined inline, like above, but as their own function definitions. The constraint should be defined so, that when evaluated, it should return a positive value, if the constraint is adhered to, and a negative, if the constraint is breached.

[4]:
# Args: name, n of variables, n of objectives, callable
cons1 = ScalarConstraint("c_1", 2, 2, lambda x, _: 10 - (x[:,0] + x[:,1]))

Finally, put it all together and create the problem.

[5]:
# Args: list of objevtives, variables and constraints
problem = ScalarMOProblem([obj1, obj2]
                         ,[x1, x2]
                         ,[cons1])

Now, the problem is fully specified and can be evaluated and played around with.

[6]:
import numpy as np

print("N of objectives:", problem.n_of_objectives)
print("N of variables:", problem.n_of_variables)
print("N of constraints:", problem.n_of_constraints)

res1 = problem.evaluate(np.array([2, 4]))
res2 = problem.evaluate(np.array([6, 6]))
res3 = problem.evaluate(np.array([[6, 3], [4,3], [7,4]]))

print("Single feasible decision variables:", res1.objectives, "with constraint values", res1.constraints)
print("Single non-feasible decision variables:", res2.objectives, "with constraint values", res2.constraints)
print("Multiple decision variables:", res3.objectives, "with constraint values", res3.constraints)
N of objectives: 2
N of variables: 2
N of constraints: 1
Single feasible decision variables: [[ 0. 10.]] with constraint values [[4.]]
Single non-feasible decision variables: [[30. 18.]] with constraint values [[-2.]]
Multiple decision variables: [[33. -9.]
 [13. -3.]
 [45. -5.]] with constraint values [[ 1.]
 [ 3.]
 [-1.]]
[ ]: