Skip to content

desdeo-problem

Test problems

desdeo.problem.testproblems

Pre-defined multiobjective optimization problems.

Pre-defined problems for, e.g., testing and illustration purposed are defined here.

binh_and_korn

binh_and_korn(maximize: tuple[bool] = (False, False)) -> Problem

Create a pydantic dataclass representation of the Binh and Korn problem.

The function has two objective functions, two variables, and two constraint functions. For testing purposes, it can be chosen whether the firs and second objective should be maximized instead.

Parameters:

Name Type Description Default
maximize tuple[bool]

whether the first or second objective should be maximized or not. Defaults to (False, False).

(False, False)
References

Binh T. and Korn U. (1997) MOBES: A Multiobjective Evolution Strategy for Constrained Optimization Problems. In: Proceedings of the Third International Conference on Genetic Algorithms. Czech Republic. pp. 176-182.

Source code in desdeo/problem/testproblems.py
def binh_and_korn(maximize: tuple[bool] = (False, False)) -> Problem:
    """Create a pydantic dataclass representation of the Binh and Korn problem.

    The function has two objective functions, two variables, and two constraint functions.
    For testing purposes, it can be chosen whether the firs and second objective should
    be maximized instead.

    Arguments:
        maximize (tuple[bool]): whether the first or second objective should be
            maximized or not. Defaults to (False, False).

    References:
        Binh T. and Korn U. (1997) MOBES: A Multiobjective Evolution Strategy for Constrained Optimization Problems.
            In: Proceedings of the Third International Conference on Genetic Algorithms. Czech Republic. pp. 176-182.
    """
    # These constants are for demonstrative purposes.
    constant_1 = Constant(name="Four", symbol="c_1", value=4)
    constant_2 = Constant(name="Five", symbol="c_2", value=5)

    variable_1 = Variable(
        name="The first variable", symbol="x_1", variable_type="real", lowerbound=0, upperbound=5, initial_value=2.5
    )
    variable_2 = Variable(
        name="The second variable", symbol="x_2", variable_type="real", lowerbound=0, upperbound=3, initial_value=1.5
    )

    objective_1 = Objective(
        name="Objective 1",
        symbol="f_1",
        func=f"{'-' if maximize[0] else ''}(c_1 * x_1**2 + c_1*x_2**2)",
        # func=["Add", ["Multiply", "c_1", ["Square", "x_1"]], ["Multiply", "c_1", ["Square", "x_2"]]],
        maximize=maximize[0],
        ideal=0,
        nadir=140 if not maximize[0] else -140,
        is_linear=False,
        is_convex=True,
        is_twice_differentiable=True,
    )
    objective_2 = Objective(
        name="Objective 2",
        symbol="f_2",
        # func=["Add", ["Square", ["Subtract", "x_1", "c_2"]], ["Square", ["Subtract", "x_2", "c_2"]]],
        func=f"{'-' if maximize[1] else ''}((x_1 - c_2)**2 + (x_2 - c_2)**2)",
        maximize=maximize[1],
        ideal=0,
        nadir=50 if not maximize[0] else -50,
        is_linear=False,
        is_convex=True,
        is_twice_differentiable=True,
    )

    constraint_1 = Constraint(
        name="Constraint 1",
        symbol="g_1",
        cons_type="<=",
        func=["Add", ["Square", ["Subtract", "x_1", "c_2"]], ["Square", "x_2"], -25],
        is_linear=False,
        is_convex=True,
        is_twice_differentiable=True,
    )

    constraint_2 = Constraint(
        name="Constraint 2",
        symbol="g_2",
        cons_type="<=",
        func=["Add", ["Negate", ["Square", ["Subtract", "x_1", 8]]], ["Negate", ["Square", ["Add", "x_2", 3]]], 7.7],
        is_linear=False,
        is_convex=True,
        is_twice_differentiable=True,
    )

    return Problem(
        name="The Binh and Korn function",
        description="The two-objective problem used in the paper by Binh and Korn.",
        constants=[constant_1, constant_2],
        variables=[variable_1, variable_2],
        objectives=[objective_1, objective_2],
        constraints=[constraint_1, constraint_2],
        is_twice_differentiable=True,
    )

dtlz2

dtlz2(n_variables: int, n_objectives: int) -> Problem

Defines the DTLZ2 test problem.

The objective functions for DTLZ2 are defined as follows, for \(i = 1\) to \(M\):

\[\begin{equation} \underset{\mathbf{x}}{\operatorname{min}} f_i(\mathbf{x}) = (1+g(\mathbf{x}_M)) \prod_{j=1}^{M-i} \cos\left(x_j \frac{\pi}{2}\right) \times \begin{cases} 1 & \text{if } i=1 \\ \sin\left(x_{(M-i+1)}\frac{\pi}{2}\right) & \text{otherwise}, \end{cases} \end{equation}\]

where

\[\begin{equation} g(\mathbf{x}_M) = \sum_{x_i \in \mathbf{x}_M} \left( x_i - 0.5 \right)^2, \end{equation}\]

and \(\mathbf{x}_M\) represents the last \(n-k\) dimensions of the decision vector. Pareto optimal solutions to the DTLZ2 problem consist of \(x_i = 0.5\) for all \(x_i \in\mathbf{x}_{M}\), and \(\sum{i=1}^{M} f_i^2 = 1\).

Parameters:

Name Type Description Default
n_variables int

number of variables.

required
n_objectives int

number of objective functions.

required

Returns:

Name Type Description
Problem Problem

an instance of the DTLZ2 problem with n_variables variables and n_objectives objective functions.

References

Deb, K., Thiele, L., Laumanns, M., Zitzler, E. (2005). Scalable Test Problems for Evolutionary Multiobjective Optimization. In: Abraham, A., Jain, L., Goldberg, R. (eds) Evolutionary Multiobjective Optimization. Advanced Information and Knowledge Processing. Springer.

Source code in desdeo/problem/testproblems.py
def dtlz2(n_variables: int, n_objectives: int) -> Problem:
    r"""Defines the DTLZ2 test problem.

    The objective functions for DTLZ2 are defined as follows, for $i = 1$ to $M$:

    \begin{equation}
        \underset{\mathbf{x}}{\operatorname{min}}
        f_i(\mathbf{x}) = (1+g(\mathbf{x}_M)) \prod_{j=1}^{M-i} \cos\left(x_j \frac{\pi}{2}\right) \times
        \begin{cases}
        1 & \text{if } i=1 \\
        \sin\left(x_{(M-i+1)}\frac{\pi}{2}\right) & \text{otherwise},
        \end{cases}
    \end{equation}

    where

    \begin{equation}
    g(\mathbf{x}_M) = \sum_{x_i \in \mathbf{x}_M} \left( x_i - 0.5 \right)^2,
    \end{equation}

    and $\mathbf{x}_M$ represents the last $n-k$ dimensions of the decision vector.
    Pareto optimal solutions to the DTLZ2 problem consist of $x_i = 0.5$ for
    all $x_i \in\mathbf{x}_{M}$, and $\sum{i=1}^{M} f_i^2 = 1$.

    Args:
        n_variables (int): number of variables.
        n_objectives (int): number of objective functions.

    Returns:
        Problem: an instance of the DTLZ2 problem with `n_variables` variables and `n_objectives` objective
            functions.

    References:
        Deb, K., Thiele, L., Laumanns, M., Zitzler, E. (2005). Scalable Test
            Problems for Evolutionary Multiobjective Optimization. In: Abraham, A.,
            Jain, L., Goldberg, R. (eds) Evolutionary Multiobjective Optimization.
            Advanced Information and Knowledge Processing. Springer.
    """
    # function g
    g_symbol = "g"
    g_expr = " + ".join([f"(x_{i} - 0.5)**2" for i in range(n_objectives, n_variables + 1)])
    g_expr = "1 + " + g_expr

    objectives = []
    for m in range(1, n_objectives + 1):
        # function f_m
        prod_expr = " * ".join([f"Cos(0.5 * {np.pi} * x_{i})" for i in range(1, n_objectives - m + 1)])
        if m > 1:
            prod_expr += f"{' * ' if prod_expr != "" else ""}Sin(0.5 * {np.pi} * x_{n_objectives - m + 1})"
        if prod_expr == "":
            prod_expr = "1"  # When m == n_objectives, the product is empty, implying f_M = g.
        f_m_expr = f"({g_symbol}) * ({prod_expr})"

        objectives.append(
            Objective(
                name=f"f_{m}",
                symbol=f"f_{m}",
                func=f_m_expr,
                maximize=False,
                ideal=0,
                nadir=1,  # Assuming the range of g and the trigonometric functions
                is_convex=False,
                is_linear=False,
                is_twice_differentiable=True,
            )
        )

    variables = [
        Variable(
            name=f"x_{i}",
            symbol=f"x_{i}",
            variable_type=VariableTypeEnum.real,
            lowerbound=0,
            upperbound=1,
            initial_value=1.0,
        )
        for i in range(1, n_variables + 1)
    ]

    extras = [
        ExtraFunction(
            name="g", symbol=g_symbol, func=g_expr, is_convex=False, is_linear=False, is_twice_differentiable=True
        ),
    ]

    return Problem(
        name="dtlz2",
        description="The DTLZ2 test problem.",
        variables=variables,
        objectives=objectives,
        extra_funcs=extras,
    )

forest_problem

forest_problem(simulation_results: str, treatment_key: str, holding: int = 1, comparing: bool = False) -> Problem

Defines a test forest problem that has TensorConstants and TensorVariables.

The problem has TensorConstants V, W and P as vectors taking values from a data file and TensorVariables X_n, where n is the number of units in the data, as vectors matching the constants in shape. The variables are binary and each variable vector X_i has one variable with the value 1 while others have value 0. The variable with the value 1 for each vector X_i represents the optimal plan for the corresponding unit i. The three objective functions f_1, f_2, f_3 represent the net present value, wood volume at the end of the planning period, and the profit from harvesting. All of the objective functions are to be maximized. The problem is defined as follows:

\[\begin{align} \max_{\mathbf{x}} & \quad \sum_{j=1}^N\sum_{i \in I_j} v_{ij} x_{ij} & \\ & \quad \sum_{j=1}^N\sum_{i \in I_j} w_{ij} x_{ij} & \\ & \quad \sum_{j=1}^N\sum_{i \in I_j} p_{ij} x_{ij} & \\ \text{s.t.} & \quad \sum\limits_{i \in I_j} x_{ij} = 1, & \forall j = 1 \ldots N \\ & \quad x_{ij}\in \{0,1\}& \forall j = 1 \ldots N, ~\forall i\in I_j, \end{align}\]

where \(x_{ij}\) are decision variables representing the choice of implementing management plan \(i\) in stand \(j\), and \(I_j\) is the set of available management plans for stand \(j\). For each plan \(i\) in stand \(j\) the net present value, wood volume at the end of the planning period, and the profit from harvesting are represented by \(v_{ij}\), \(w_{ij}\), and \(p_{ij}\) respectively.

Parameters:

Name Type Description Default
simulation_results str

Location of the simulation results file.

required
treatment_key str

Location of the file with the treatment information.

required
holding int

The number of the holding to be optimized. Defaults to 1.

1
comparing bool

Determines if solutions are to be compared to those from the rahti app. Defaults to False.

False

Returns:

Name Type Description
Problem Problem

An instance of the test forest problem.

Source code in desdeo/problem/testproblems.py
def forest_problem(simulation_results: str, treatment_key: str, holding: int = 1, comparing: bool = False) -> Problem:
    r"""Defines a test forest problem that has TensorConstants and TensorVariables.

    The problem has TensorConstants V, W and P as vectors taking values from a data file and
    TensorVariables X_n, where n is the number of units in the data, as vectors matching the constants in shape.
    The variables are binary and each variable vector X_i has one variable with the value 1 while others have value 0.
    The variable with the value 1 for each vector X_i represents the optimal plan for the corresponding unit i.
    The three objective functions f_1, f_2, f_3 represent the net present value, wood volume at the end of
    the planning period, and the profit from harvesting.
    All of the objective functions are to be maximized.
    The problem is defined as follows:

    \begin{align}
        \max_{\mathbf{x}} & \quad \sum_{j=1}^N\sum_{i \in I_j} v_{ij} x_{ij} & \\
        & \quad \sum_{j=1}^N\sum_{i \in I_j} w_{ij} x_{ij} & \\
        & \quad \sum_{j=1}^N\sum_{i \in I_j} p_{ij} x_{ij} & \\
        \text{s.t.} & \quad \sum\limits_{i \in I_j} x_{ij} = 1, & \forall j = 1 \ldots N \\
        & \quad x_{ij}\in \{0,1\}& \forall j = 1 \ldots N, ~\forall i\in I_j,
    \end{align}

    where $x_{ij}$ are decision variables representing the choice of implementing management plan $i$ in stand $j$,
    and $I_j$ is the set of available management plans for stand $j$. For each plan $i$ in stand $j$
    the net present value, wood volume at the end of the planning period, and the profit from harvesting
    are represented by $v_{ij}$, $w_{ij}$, and $p_{ij}$ respectively.

    Args:
        simulation_results (str): Location of the simulation results file.
        treatment_key (str): Location of the file with the treatment information.
        holding (int, optional): The number of the holding to be optimized. Defaults to 1.
        comparing (bool, optional): Determines if solutions are to be compared to those from the rahti app.
            Defaults to False.

    Returns:
        Problem: An instance of the test forest problem.
    """
    df = pl.read_csv(simulation_results, schema_overrides={"unit": pl.Float64})
    df_key = pl.read_csv(treatment_key, schema_overrides={"unit": pl.Float64})

    selected_df_v = df.filter(pl.col("holding") == holding).select(["unit", "schedule", "npv_5_percent"])
    unique_units = selected_df_v.unique(["unit"], maintain_order=True).get_column("unit")
    selected_df_v.group_by(["unit", "schedule"])
    rows_by_key = selected_df_v.rows_by_key(key=["unit", "schedule"])
    v_array = np.zeros((selected_df_v["unit"].n_unique(), selected_df_v["schedule"].n_unique()))
    for i in range(np.shape(v_array)[0]):
        for j in range(np.shape(v_array)[1]):
            if (unique_units[i], j) in rows_by_key:
                v_array[i][j] = rows_by_key[(unique_units[i], j)][0][0]

    # determine whether the results are to be compared to those from the rahti app (for testing purposes)
    # if compared, the stock values are calculated by substacting the value after 2025 period from
    # the value after the 2035 period (in other words, last value - first value)
    if comparing:
        selected_df_w = df.filter(pl.col("holding") == holding).select(["unit", "schedule", "stock_2025", "stock_2035"])
        selected_df_w.group_by(["unit", "schedule"])
        rows_by_key = selected_df_w.rows_by_key(key=["unit", "schedule"])
        selected_df_key_w = df_key.select(["unit", "schedule", "treatment"])
        selected_df_key_w.group_by(["unit", "schedule"])
        rows_by_key_df_key = selected_df_key_w.rows_by_key(key=["unit", "schedule"])
        w_array = np.zeros((selected_df_w["unit"].n_unique(), selected_df_w["schedule"].n_unique()))
        for i in range(np.shape(w_array)[0]):
            for j in range(np.shape(w_array)[1]):
                if len(rows_by_key_df_key[(unique_units[i], j)]) == 0:
                    continue
                if (unique_units[i], j) in rows_by_key:
                    w_array[i][j] = rows_by_key[(unique_units[i], j)][0][1] - rows_by_key[(unique_units[i], j)][0][0]
    else:
        selected_df_w = df.filter(pl.col("holding") == holding).select(["unit", "schedule", "stock_2035"])
        selected_df_w.group_by(["unit", "schedule"])
        rows_by_key = selected_df_w.rows_by_key(key=["unit", "schedule"])
        selected_df_key_w = df_key.select(["unit", "schedule", "treatment"])
        selected_df_key_w.group_by(["unit", "schedule"])
        rows_by_key_df_key = selected_df_key_w.rows_by_key(key=["unit", "schedule"])
        w_array = np.zeros((selected_df_w["unit"].n_unique(), selected_df_w["schedule"].n_unique()))
        for i in range(np.shape(w_array)[0]):
            for j in range(np.shape(w_array)[1]):
                if len(rows_by_key_df_key[(unique_units[i], j)]) == 0:
                    continue
                if (unique_units[i], j) in rows_by_key:
                    w_array[i][j] = rows_by_key[(unique_units[i], j)][0][0]

    selected_df_p = df.filter(pl.col("holding") == holding).select(
        ["unit", "schedule", "harvest_value_period_2025", "harvest_value_period_2030", "harvest_value_period_2035"]
    )
    selected_df_p.group_by(["unit", "schedule"])
    rows_by_key = selected_df_p.rows_by_key(key=["unit", "schedule"])
    p_array = np.zeros((selected_df_p["unit"].n_unique(), selected_df_p["schedule"].n_unique()))
    for i in range(np.shape(p_array)[0]):
        for j in range(np.shape(p_array)[1]):
            if (unique_units[i], j) in rows_by_key:
                p_array[i][j] = sum(rows_by_key[(unique_units[i], j)][0])

    constants = []
    variables = []
    constraints = []
    f_1_func = []
    f_2_func = []
    f_3_func = []
    # define the constants V, W and P, decision variable X, constraints, and objective function expressions in one loop
    for i in range(np.shape(v_array)[0]):
        # Constants V, W and P
        v = TensorConstant(
            name=f"V_{i+1}",
            symbol=f"V_{i+1}",
            shape=[np.shape(v_array)[1]],  # NOTE: vectors have to be of form [2] instead of [2,1] or [1,2]
            values=v_array[i].tolist(),
        )
        constants.append(v)
        w = TensorConstant(
            name=f"W_{i+1}",
            symbol=f"W_{i+1}",
            shape=[np.shape(w_array)[1]],  # NOTE: vectors have to be of form [2] instead of [2,1] or [1,2]
            values=w_array[i].tolist(),
        )
        constants.append(w)
        p = TensorConstant(
            name=f"P_{i+1}",
            symbol=f"P_{i+1}",
            shape=[np.shape(p_array)[1]],  # NOTE: vectors have to be of form [2] instead of [2,1] or [1,2]
            values=p_array[i].tolist(),
        )

        # Decision variable X
        constants.append(p)
        x = TensorVariable(
            name=f"X_{i+1}",
            symbol=f"X_{i+1}",
            variable_type=VariableTypeEnum.binary,
            shape=[np.shape(v_array)[1]],  # NOTE: vectors have to be of form [2] instead of [2,1] or [1,2]
            lowerbounds=np.shape(v_array)[1] * [0],
            upperbounds=np.shape(v_array)[1] * [1],
            initial_values=np.shape(v_array)[1] * [0],
        )
        variables.append(x)

        # Constraints
        con = Constraint(
            name=f"x_con_{i+1}",
            symbol=f"x_con_{i+1}",
            cons_type=ConstraintTypeEnum.EQ,
            func=f"Sum(X_{i+1}) - 1",
            is_linear=True,
            is_convex=False,  # not checked
            is_twice_differentiable=True,
        )
        constraints.append(con)

        # Objective function expressions
        exprs = f"V_{i+1}@X_{i+1}"
        f_1_func.append(exprs)

        exprs = f"W_{i+1}@X_{i+1}"
        f_2_func.append(exprs)

        exprs = f"P_{i+1}@X_{i+1}"
        f_3_func.append(exprs)

    # form the objective function sums
    f_1_func = " + ".join(f_1_func)
    f_2_func = " + ".join(f_2_func)
    f_3_func = " + ".join(f_3_func)

    f_1 = Objective(
        name="Net present value",
        symbol="f_1",
        func=f_1_func,
        maximize=True,
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=True,
        is_convex=False,  # not checked
        is_twice_differentiable=True,
    )

    f_2 = Objective(
        name="Wood stock volume",
        symbol="f_2",
        func=f_2_func,
        maximize=True,
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=True,
        is_convex=False,  # not checked
        is_twice_differentiable=True,
    )

    f_3 = Objective(
        name="Harvest value",
        symbol="f_3",
        func=f_3_func,
        maximize=True,
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=True,
        is_convex=False,  # not checked
        is_twice_differentiable=True,
    )

    return Problem(
        name="Forest problem",
        description="A test forest problem.",
        constants=constants,
        variables=variables,
        objectives=[f_1, f_2, f_3],
        constraints=constraints,
    )

forest_problem_discrete

forest_problem_discrete() -> Problem

Implements the forest problem using Pareto front representation.

Returns:

Name Type Description
Problem Problem

A problem instance representing the forest problem.

Source code in desdeo/problem/testproblems.py
def forest_problem_discrete() -> Problem:
    """Implements the forest problem using Pareto front representation.

    Returns:
        Problem: A problem instance representing the forest problem.
    """
    filename = "datasets/forest_holding_4.csv"

    path = Path(__file__).parent.parent.parent / filename

    obj_names = ["stock", "harvest_value", "npv"]

    var_name = "index"

    data = pl.read_csv(
        path, has_header=True, columns=["stock", "harvest_value", "npv"], separator=";", decimal_comma=True
    )

    variables = [
        Variable(
            name=var_name,
            symbol=var_name,
            variable_type=VariableTypeEnum.integer,
            lowerbound=0,
            upperbound=len(data) - 1,
            initial_value=0,
        )
    ]

    objectives = [
        Objective(
            name=obj_name,
            symbol=obj_name,
            objective_type=ObjectiveTypeEnum.data_based,
            ideal=data[obj_name].max(),
            nadir=data[obj_name].min(),
            maximize=True,
        )
        for obj_name in obj_names
    ]

    discrete_def = DiscreteRepresentation(
        variable_values={"index": list(range(len(data)))},
        objective_values=data[[obj.symbol for obj in objectives]].to_dict(),
    )

    return Problem(
        name="Finnish Forest Problem (Discrete)",
        description="Defines a forest problem with three objectives: stock, harvest value, and net present value.",
        variables=variables,
        objectives=objectives,
        discrete_representation=discrete_def,
    )

momip_ti2

momip_ti2() -> Problem

Defines the mixed-integer multiobjective optimization problem test instance 2 (TI2).

The problem has four variables, two continuous and two integer. The Pareto optimal solutions hold for solutions with x_1^2 + x_^2 = 0.25 and (x_3, x_4) = {(0, -1), (-1, 0)}.

References

Eichfelder, G., Gerlach, T., & Warnow, L. (n.d.). Test Instances for Multiobjective Mixed-Integer Nonlinear Optimization.

Source code in desdeo/problem/testproblems.py
def momip_ti2() -> Problem:
    """Defines the mixed-integer multiobjective optimization problem test instance 2 (TI2).

    The problem has four variables, two continuous and two integer. The Pareto optimal solutions
    hold for solutions with x_1^2 + x_^2 = 0.25 and (x_3, x_4) = {(0, -1), (-1, 0)}.

    References:
        Eichfelder, G., Gerlach, T., & Warnow, L. (n.d.). Test Instances for
            Multiobjective Mixed-Integer Nonlinear Optimization.
    """
    x_1 = Variable(name="x_1", symbol="x_1", variable_type=VariableTypeEnum.real)
    x_2 = Variable(name="x_2", symbol="x_2", variable_type=VariableTypeEnum.real)
    x_3 = Variable(name="x_3", symbol="x_3", variable_type=VariableTypeEnum.integer)
    x_4 = Variable(name="x_4", symbol="x_4", variable_type=VariableTypeEnum.integer)

    f_1 = Objective(
        name="f_1",
        symbol="f_1",
        func="x_1 + x_3",
        objective_type=ObjectiveTypeEnum.analytical,
        maximize=False,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )
    f_2 = Objective(
        name="f_2",
        symbol="f_2",
        func="x_2 + x_4",
        objective_type=ObjectiveTypeEnum.analytical,
        maximize=False,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )

    con_1 = Constraint(
        name="g_1",
        symbol="g_1",
        cons_type=ConstraintTypeEnum.LTE,
        func="x_1**2 + x_2**2 - 0.25",
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )
    con_2 = Constraint(
        name="g_2",
        symbol="g_2",
        cons_type=ConstraintTypeEnum.LTE,
        func="x_3**2 + x_4**2 - 1",
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    return Problem(
        name="MOMIP Test Instance 2",
        description="Test instance 2",
        variables=[x_1, x_2, x_3, x_4],
        constraints=[con_1, con_2],
        objectives=[f_1, f_2],
    )

momip_ti7

momip_ti7() -> Problem

Defines the mixed-integer multiobjective optimization problem test instance 7 (T7).

The problem is defined as follows:

\[\begin{align} &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = x_1 + x_4 \\ &\max_{\mathbf{x}} & f_2(\mathbf{x}) & = -(x_2 + x_5) \\ &\min_{\mathbf{x}} & f_3(\mathbf{x}) & = x_3 + x_6 \\ &\text{s.t.,} & x_1^2 +x_2^2 + x_3^2 & \leq 1,\\ & & x_4^2 + x_5^2 + x_6^2 & \leq 1,\\ & & -1 \leq x_i \leq 1&\;\text{for}\;i=\{1,2,3\},\\ & & x_i \in \{-1, 0, 1\}&\;\text{for}\;i=\{4, 5, 6\}. \end{align}\]

In the problem, \(x_1, x_2, x_3\) are real-valued and \(x_4, x_5, x_6\) are integer-valued. The problem is convex and differentiable.

The Pareto optimal integer assignments are \((x_4, x_5, x_6) \in {(0,0,-1), (0, -1, 0), (-1,0,0)}\), and the real-valued assignments are \(\{x_1, x_2, x_3 \in \mathbb{R}^3 | x_1^2 + x_2^2 + x_3^2 = 1, x_1 \leq 0, x_2 \leq 0, x_3 \leq 0\}\). Unlike in the original definition, \(f_2\) is formulated to be maximized instead of minimized.

References

Eichfelder, G., Gerlach, T., & Warnow, L. (n.d.). Test Instances for Multiobjective Mixed-Integer Nonlinear Optimization.

Source code in desdeo/problem/testproblems.py
def momip_ti7() -> Problem:
    r"""Defines the mixed-integer multiobjective optimization problem test instance 7 (T7).

    The problem is defined as follows:

    \begin{align}
        &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = x_1 + x_4 \\
        &\max_{\mathbf{x}} & f_2(\mathbf{x}) & = -(x_2 + x_5) \\
        &\min_{\mathbf{x}} & f_3(\mathbf{x}) & = x_3 + x_6 \\
        &\text{s.t.,}   & x_1^2 +x_2^2 + x_3^2 & \leq 1,\\
        &               & x_4^2 + x_5^2 + x_6^2 & \leq 1,\\
        &               & -1 \leq x_i \leq 1&\;\text{for}\;i=\{1,2,3\},\\
        &               & x_i \in \{-1, 0, 1\}&\;\text{for}\;i=\{4, 5, 6\}.
    \end{align}

    In the problem, $x_1, x_2, x_3$ are real-valued and $x_4, x_5, x_6$ are integer-valued. The problem
    is convex and differentiable.

    The Pareto optimal integer assignments are $(x_4, x_5, x_6) \in {(0,0,-1), (0, -1, 0), (-1,0,0)}$,
    and the real-valued assignments are $\{x_1, x_2, x_3 \in \mathbb{R}^3 |
    x_1^2 + x_2^2 + x_3^2 = 1, x_1 \leq 0, x_2 \leq 0, x_3 \leq 0\}$. Unlike in the original definition,
    $f_2$ is formulated to be maximized instead of minimized.

    References:
        Eichfelder, G., Gerlach, T., & Warnow, L. (n.d.). Test Instances for
            Multiobjective Mixed-Integer Nonlinear Optimization.
    """
    x_1 = Variable(name="x_1", symbol="x_1", variable_type=VariableTypeEnum.real)
    x_2 = Variable(name="x_2", symbol="x_2", variable_type=VariableTypeEnum.real)
    x_3 = Variable(name="x_3", symbol="x_3", variable_type=VariableTypeEnum.real)
    x_4 = Variable(name="x_4", symbol="x_4", variable_type=VariableTypeEnum.integer, lowerbound=-1, upperbound=1)
    x_5 = Variable(name="x_5", symbol="x_5", variable_type=VariableTypeEnum.integer, lowerbound=-1, upperbound=1)
    x_6 = Variable(name="x_6", symbol="x_6", variable_type=VariableTypeEnum.integer, lowerbound=-1, upperbound=1)

    f_1 = Objective(
        name="f_1",
        symbol="f_1",
        func="x_1 + x_4",
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=-3,
        nadir=3,
        maximize=False,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )
    f_2 = Objective(
        name="f_2",
        symbol="f_2",
        func="-(x_2 + x_5)",
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=3,
        nadir=-3,
        maximize=True,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )
    f_3 = Objective(
        name="f_3",
        symbol="f_3",
        func="x_3 + x_6",
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=-3,
        nadir=3,
        maximize=False,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )

    con_1 = Constraint(
        name="g_1",
        symbol="g_1",
        cons_type=ConstraintTypeEnum.LTE,
        func="x_1**2 + x_2**2 + x_3**2 - 1",
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )
    con_2 = Constraint(
        name="g_2",
        symbol="g_2",
        cons_type=ConstraintTypeEnum.LTE,
        func="x_4**2 + x_5**2 + x_6**2 - 1",
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    return Problem(
        name="MOMIP Test Instance 7",
        description="Test instance 17",
        variables=[x_1, x_2, x_3, x_4, x_5, x_6],
        constraints=[con_1, con_2],
        objectives=[f_1, f_2, f_3],
    )

nimbus_test_problem

nimbus_test_problem() -> Problem

Defines the test problem utilized in the article describing Synchronous NIMBUS.

Defines the following multiobjective optimization problem:

\[\begin{align} &\max_{\mathbf{x}} & f_1(\mathbf{x}) &= x_1 x_2\\ &\min_{\mathbf{x}} & f_2(\mathbf{x}) &= (x_1 - 4)^2 + x_2^2\\ &\min_{\mathbf{x}} & f_3(\mathbf{x}) &= -x_1 - x_2\\ &\min_{\mathbf{x}} & f_4(\mathbf{x}) &= x_1 - x_2\\ &\min_{\mathbf{x}} & f_5(\mathbf{x}) &= 50 x_1^4 + 10 x_2^4 \\ &\min_{\mathbf{x}} & f_6(\mathbf{x}) &= 30 (x_1 - 5)^4 + 100 (x_2 - 3)^4\\ &\text{s.t.,} && 1 \leq x_i \leq 3\quad i=\{1,2\}, \end{align}\]

with the following ideal point \(\mathbf{z}^\star = \left[9.0, 2.0, -6.0, -2.0, 60.0, 480.0 \right]\) and nadir point \(\mathbf{z}^\text{nad} = \left[ 1.0, 18.0, -2.0, 2.0, 4860.0, 9280.0 \right]\).

References

Miettinen, K., & Mäkelä, M. M. (2006). Synchronous approach in interactive multiobjective optimization. European Journal of Operational Research, 170(3), 909–922. https://doi.org/10.1016/j.ejor.2004.07.052

Returns:

Name Type Description
Problem Problem

the NIMBUS test problem.

Source code in desdeo/problem/testproblems.py
def nimbus_test_problem() -> Problem:
    r"""Defines the test problem utilized in the article describing Synchronous NIMBUS.

    Defines the following multiobjective optimization problem:

    \begin{align}
        &\max_{\mathbf{x}} & f_1(\mathbf{x}) &= x_1 x_2\\
        &\min_{\mathbf{x}} & f_2(\mathbf{x}) &= (x_1 - 4)^2 + x_2^2\\
        &\min_{\mathbf{x}} & f_3(\mathbf{x}) &= -x_1 - x_2\\
        &\min_{\mathbf{x}} & f_4(\mathbf{x}) &= x_1 - x_2\\
        &\min_{\mathbf{x}} & f_5(\mathbf{x}) &= 50 x_1^4 + 10 x_2^4 \\
        &\min_{\mathbf{x}} & f_6(\mathbf{x}) &= 30 (x_1 - 5)^4 + 100 (x_2 - 3)^4\\
        &\text{s.t.,}     && 1 \leq x_i \leq 3\quad i=\{1,2\},
    \end{align}

    with the following ideal point
    $\mathbf{z}^\star = \left[9.0, 2.0, -6.0, -2.0, 60.0, 480.0 \right]$ and nadir point
    $\mathbf{z}^\text{nad} = \left[ 1.0, 18.0, -2.0, 2.0, 4860.0, 9280.0 \right]$.

    References:
        Miettinen, K., & Mäkelä, M. M. (2006). Synchronous approach in
            interactive multiobjective optimization. European Journal of Operational
            Research, 170(3), 909–922. https://doi.org/10.1016/j.ejor.2004.07.052


    Returns:
        Problem: the NIMBUS test problem.
    """
    variables = [
        Variable(
            name="x_1",
            symbol="x_1",
            variable_type=VariableTypeEnum.real,
            initial_value=1.0,
            lowerbound=1.0,
            upperbound=3.0,
        ),
        Variable(
            name="x_2",
            symbol="x_2",
            variable_type=VariableTypeEnum.real,
            initial_value=1.0,
            lowerbound=1.0,
            upperbound=3.0,
        ),
    ]

    f_1_expr = "x_1 * x_2"
    f_2_expr = "(x_1 - 4)**2 + x_2**2"
    f_3_expr = "-x_1 - x_2"
    f_4_expr = "x_1 - x_2"
    f_5_expr = "50 * x_1**4 + 10 * x_2**4"
    f_6_expr = "30 * (x_1 - 5)**4 + 100*(x_2 - 3)**4"

    objectives = [
        Objective(
            name="Objective 1",
            symbol="f_1",
            func=f_1_expr,
            maximize=True,
            objective_type=ObjectiveTypeEnum.analytical,
            ideal=9.0,
            nadir=1.0,
            is_convex=False,
            is_linear=False,
            is_twice_differentiable=True,
        ),
        Objective(
            name="Objective 2",
            symbol="f_2",
            func=f_2_expr,
            maximize=False,
            objective_type=ObjectiveTypeEnum.analytical,
            ideal=2.0,
            nadir=18.0,
            is_convex=False,
            is_linear=False,
            is_twice_differentiable=True,
        ),
        Objective(
            name="Objective 3",
            symbol="f_3",
            func=f_3_expr,
            maximize=False,
            objective_type=ObjectiveTypeEnum.analytical,
            ideal=-6.0,
            nadir=-2.0,
            is_convex=True,
            is_linear=True,
            is_twice_differentiable=True,
        ),
        Objective(
            name="Objective 4",
            symbol="f_4",
            func=f_4_expr,
            maximize=False,
            objective_type=ObjectiveTypeEnum.analytical,
            ideal=-2.0,
            nadir=2.0,
            is_convex=True,
            is_linear=True,
            is_twice_differentiable=True,
        ),
        Objective(
            name="Objective 5",
            symbol="f_5",
            func=f_5_expr,
            maximize=False,
            objective_type=ObjectiveTypeEnum.analytical,
            ideal=60.0,
            nadir=4860.0,
            is_convex=False,
            is_linear=False,
            is_twice_differentiable=True,
        ),
        Objective(
            name="Objective 6",
            symbol="f_6",
            func=f_6_expr,
            maximize=False,
            objective_type=ObjectiveTypeEnum.analytical,
            ideal=480.0,
            nadir=9280.0,
            is_convex=False,
            is_linear=False,
            is_twice_differentiable=True,
        ),
    ]

    return Problem(
        name="NIMBUS test problem",
        description="The test problem used in the Synchronous NIMBUS article",
        variables=variables,
        objectives=objectives,
    )

pareto_navigator_test_problem

pareto_navigator_test_problem() -> Problem

Defines the problem utilized in the (convex) Pareto navigator article.

The problem is defined as follows:

\[\begin{align} &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = -x_1 - x_2 + 5 \\ &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = 0.2(x_1^2 -10x_1 + x_2^2 - 4x_2 + 11) \\ &\min_{\mathbf{x}} & f_3(\mathbf{x}) & = (5 - x_1)(x_2 - 11)\\ &\text{s.t.,} & 3x_1 + x_2 - 12 & \leq 0,\\ & & 2x_1 + x_2 - 9 & \leq 0,\\ & & x_1 + 2x_2 - 12 & \leq 0,\\ & & 0 \leq x_1 & \leq 4,\\ & & 0 \leq x_2 & \leq 6. \end{align}\]

The problem comes with seven pre-defined Pareto optimal solutions that were utilized in the original article as well. From these, the ideal and nadir points of the problem are approximated also.

References

Eskelinen, P., Miettinen, K., Klamroth, K., & Hakanen, J. (2010). Pareto navigator for interactive nonlinear multiobjective optimization. OR Spectrum, 32(1), 211-227.

Source code in desdeo/problem/testproblems.py
def pareto_navigator_test_problem() -> Problem:
    r"""Defines the problem utilized in the (convex) Pareto navigator article.

    The problem is defined as follows:

    \begin{align}
        &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = -x_1 - x_2 + 5 \\
        &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = 0.2(x_1^2 -10x_1 + x_2^2 - 4x_2 + 11) \\
        &\min_{\mathbf{x}} & f_3(\mathbf{x}) & = (5 - x_1)(x_2 - 11)\\
        &\text{s.t.,}   & 3x_1 + x_2 - 12 & \leq 0,\\
        &               & 2x_1 + x_2 - 9 & \leq 0,\\
        &               & x_1 + 2x_2 - 12 & \leq 0,\\
        &               & 0 \leq x_1 & \leq 4,\\
        &               & 0 \leq x_2 & \leq 6.
    \end{align}

    The problem comes with seven pre-defined Pareto optimal solutions that were
    utilized in the original article as well. From these, the ideal and nadir
    points of the problem are approximated also.

    References:
        Eskelinen, P., Miettinen, K., Klamroth, K., & Hakanen, J. (2010). Pareto
            navigator for interactive nonlinear multiobjective optimization. OR
            Spectrum, 32(1), 211-227.
    """
    x_1 = Variable(name="x_1", symbol="x_1", variable_type=VariableTypeEnum.real, lowerbound=0, upperbound=4)
    x_2 = Variable(name="x_2", symbol="x_2", variable_type=VariableTypeEnum.real, lowerbound=0, upperbound=6)

    f_1 = Objective(
        name="f_1",
        symbol="f_1",
        func="-x_1 - x_2 + 5",
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=-2.0,
        nadir=5.0,
        maximize=False,
    )
    f_2 = Objective(
        name="f_2",
        symbol="f_2",
        func="0.2*(x_1**2 - 10*x_1 + x_2**2 - 4*x_2 + 11)",
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=-3.1,
        nadir=4.60,
        maximize=False,
    )
    f_3 = Objective(
        name="f_3",
        symbol="f_3",
        func="(5 - x_1) * (x_2 - 11)",
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=-55.0,
        nadir=-14.25,
        maximize=False,
    )

    con_1 = Constraint(name="g_1", symbol="g_1", func="3*x_1 + x_2 - 12", cons_type=ConstraintTypeEnum.LTE)
    con_2 = Constraint(name="g_2", symbol="g_2", func="2*x_1 + x_2 - 9", cons_type=ConstraintTypeEnum.LTE)
    con_3 = Constraint(name="g_3", symbol="g_3", func="x_1 + 2*x_2 - 12", cons_type=ConstraintTypeEnum.LTE)

    representation = DiscreteRepresentation(
        variable_values={"x_1": [0, 0, 0, 0, 0, 0, 0], "x_2": [0, 0, 0, 0, 0, 0, 0]},
        objective_values={
            "f_1": [-2.0, -1.0, 0.0, 1.38, 1.73, 2.48, 5.0],
            "f_2": [0.0, 4.6, -3.1, 0.62, 1.72, 1.45, 2.2],
            "f_3": [-18.0, -25.0, -14.25, -35.33, -38.64, -42.41, -55.0],
        },
        non_dominated=True,
    )

    return Problem(
        name="The (convex) Pareto navigator problem.",
        description="The test problem used in the (convex) Pareto navigator paper.",
        variables=[x_1, x_2],
        objectives=[f_1, f_2, f_3],
        constraints=[con_1, con_2, con_3],
        discrete_representation=representation,
    )

re21

re21(f: float = 10.0, sigma: float = 10.0, e: float = 2.0 * 100000.0, l: float = 200.0) -> Problem

Defines the four bar truss design problem.

The objective functions and constraints for the four bar truss design problem are defined as follows:

\[\begin{align} &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = L(2x_1 + \sqrt{2}x_2 + \sqrt{x_3} + x_4) \\ &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = \frac{FL}{E}\left(\frac{2}{x_1} + \frac{2\sqrt{2}}{x_2} - \frac{2\sqrt{2}}{x_3} + \frac{2}{x_4}\right) \\ &\text{s.t.,} & \frac{F}{\sigma} \leq x_1 & \leq 3\frac{F}{\sigma},\\ & & \sqrt{2}\frac{F}{\sigma} \leq x_2 & \leq 3\frac{F}{\sigma},\\ & & \sqrt{2}\frac{F}{\sigma} \leq x_3 & \leq 3\frac{F}{\sigma},\\ & & \frac{F}{\sigma} \leq x_4 & \leq 3\frac{F}{\sigma}, \end{align}\]

where \(x_1, x_4 \in [a, 3a]\), \(x_2, x_3 \in [\sqrt{2}a, 3a]\), and \(a = F/\sigma\). The parameters are defined as \(F = 10\) \(kN\), \(E = 2e^5\) \(kN/cm^2\), \(L = 200\) \(cm\), and \(\sigma = 10\) \(kN/cm^2\).

References

Cheng, F. Y., & Li, X. S. (1999). Generalized center method for multiobjective engineering optimization. Engineering Optimization, 31(5), 641-661.

Tanabe, R. & Ishibuchi, H. (2020). An easy-to-use real-world multi-objective optimization problem suite. Applied soft computing, 89, 106078. https://doi.org/10.1016/j.asoc.2020.106078.

https://github.com/ryojitanabe/reproblems/blob/master/reproblem_python_ver/reproblem.py

Parameters:

Name Type Description Default
f float

Force (kN). Defaults to 10.0.

10.0
sigma optional

Stress (kN/cm^2). Defaults to 10.0.

10.0
e float

Young modulus? (kN/cm^2). Defaults to 2.0 * 1e5.

2.0 * 100000.0
l float

Length (cm). Defaults to 200.0.

200.0

Returns:

Name Type Description
Problem Problem

an instance of the four bar truss design problem.

Source code in desdeo/problem/testproblems.py
def re21(f: float = 10.0, sigma: float = 10.0, e: float = 2.0 * 1e5, l: float = 200.0) -> Problem:
    r"""Defines the four bar truss design problem.

    The objective functions and constraints for the four bar truss design problem are defined as follows:

    \begin{align}
        &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = L(2x_1 + \sqrt{2}x_2 + \sqrt{x_3} + x_4) \\
        &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = \frac{FL}{E}\left(\frac{2}{x_1} + \frac{2\sqrt{2}}{x_2}
        - \frac{2\sqrt{2}}{x_3} + \frac{2}{x_4}\right) \\
        &\text{s.t.,}   & \frac{F}{\sigma} \leq x_1 & \leq 3\frac{F}{\sigma},\\
        & & \sqrt{2}\frac{F}{\sigma} \leq x_2 & \leq 3\frac{F}{\sigma},\\
        & & \sqrt{2}\frac{F}{\sigma} \leq x_3 & \leq 3\frac{F}{\sigma},\\
        & & \frac{F}{\sigma} \leq x_4 & \leq 3\frac{F}{\sigma},
    \end{align}

    where $x_1, x_4 \in [a, 3a]$, $x_2, x_3 \in [\sqrt{2}a, 3a]$, and $a = F/\sigma$.
    The parameters are defined as $F = 10$ $kN$, $E = 2e^5$ $kN/cm^2$, $L = 200$ $cm$, and $\sigma = 10$ $kN/cm^2$.

    References:
        Cheng, F. Y., & Li, X. S. (1999). Generalized center method for multiobjective engineering optimization.
            Engineering Optimization, 31(5), 641-661.

        Tanabe, R. & Ishibuchi, H. (2020). An easy-to-use real-world multi-objective
            optimization problem suite. Applied soft computing, 89, 106078.
            https://doi.org/10.1016/j.asoc.2020.106078.

        https://github.com/ryojitanabe/reproblems/blob/master/reproblem_python_ver/reproblem.py

    Args:
        f (float, optional): Force (kN). Defaults to 10.0.
        sigma (float. optional): Stress (kN/cm^2). Defaults to 10.0.
        e (float, optional): Young modulus? (kN/cm^2). Defaults to 2.0 * 1e5.
        l (float, optional): Length (cm). Defaults to 200.0.

    Returns:
        Problem: an instance of the four bar truss design problem.
    """
    a = f / sigma

    x_1 = Variable(
        name="x_1",
        symbol="x_1",
        variable_type=VariableTypeEnum.real,
        lowerbound=a,
        upperbound=3 * a,
        initial_value=2 * a,
    )
    x_2 = Variable(
        name="x_2",
        symbol="x_2",
        variable_type=VariableTypeEnum.real,
        lowerbound=np.sqrt(2.0) * a,
        upperbound=3 * a,
        initial_value=2 * a,
    )
    x_3 = Variable(
        name="x_3",
        symbol="x_3",
        variable_type=VariableTypeEnum.real,
        lowerbound=np.sqrt(2.0) * a,
        upperbound=3 * a,
        initial_value=2 * a,
    )
    x_4 = Variable(
        name="x_4",
        symbol="x_4",
        variable_type=VariableTypeEnum.real,
        lowerbound=a,
        upperbound=3 * a,
        initial_value=2 * a,
    )

    f_1 = Objective(
        name="f_1",
        symbol="f_1",
        func=f"{l} * ((2 * x_1) + {np.sqrt(2.0)} * x_2 + Sqrt(x_3) + x_4)",
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    f_2 = Objective(
        name="f_2",
        symbol="f_2",
        func=f"({(f * l) / e} * ((2.0 / x_1) + (2.0 * {np.sqrt(2.0)} / x_2) - (2.0 * {np.sqrt(2.0)} / x_3) + (2.0 / x_4)))",
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )

    return Problem(
        name="RE21",
        description="the four bar truss design problem",
        variables=[x_1, x_2, x_3, x_4],
        objectives=[f_1, f_2],
    )

re22

re22() -> Problem

The reinforced concrete beam design problem.

The objective functions and constraints for the reinforced concrete beam design problem are defined as follows:

\[\begin{align} &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = 29.4x_1 + 0.6x_2x_3 \\ &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = \sum_{i=1}^2 \max\{g_i(\mathbf{x}), 0\} \\ &\text{s.t.,} & g_1(\mathbf{x}) & = x_1x_3 - 7.735\frac{x_1^2}{x_2} - 180 \geq 0,\\ & & g_2(\mathbf{x}) & = 4 - \frac{x_3}{x_2} \geq 0. \end{align}\]
References

Amir, H. M., & Hasegawa, T. (1989). Nonlinear mixed-discrete structural optimization. Journal of Structural Engineering, 115(3), 626-646.

Tanabe, R. & Ishibuchi, H. (2020). An easy-to-use real-world multi-objective optimization problem suite. Applied soft computing, 89, 106078. https://doi.org/10.1016/j.asoc.2020.106078.

https://github.com/ryojitanabe/reproblems/blob/master/reproblem_python_ver/reproblem.py

Returns:

Name Type Description
Problem Problem

an instance of the reinforced concrete beam design problem.

Source code in desdeo/problem/testproblems.py
def re22() -> Problem:
    r"""The reinforced concrete beam design problem.

    The objective functions and constraints for the reinforced concrete beam design problem are defined as follows:

    \begin{align}
        &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = 29.4x_1 + 0.6x_2x_3 \\
        &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = \sum_{i=1}^2 \max\{g_i(\mathbf{x}), 0\} \\
        &\text{s.t.,}   & g_1(\mathbf{x}) & = x_1x_3 - 7.735\frac{x_1^2}{x_2} - 180 \geq 0,\\
        & & g_2(\mathbf{x}) & = 4 - \frac{x_3}{x_2} \geq 0.
    \end{align}

    References:
        Amir, H. M., & Hasegawa, T. (1989). Nonlinear mixed-discrete structural optimization.
            Journal of Structural Engineering, 115(3), 626-646.

        Tanabe, R. & Ishibuchi, H. (2020). An easy-to-use real-world multi-objective
            optimization problem suite. Applied soft computing, 89, 106078.
            https://doi.org/10.1016/j.asoc.2020.106078.

        https://github.com/ryojitanabe/reproblems/blob/master/reproblem_python_ver/reproblem.py

    Returns:
        Problem: an instance of the reinforced concrete beam design problem.
    """
    x_2 = Variable(
        name="x_2", symbol="x_2", variable_type=VariableTypeEnum.real, lowerbound=0, upperbound=20, initial_value=10
    )
    x_3 = Variable(
        name="x_3", symbol="x_3", variable_type=VariableTypeEnum.real, lowerbound=0, upperbound=40, initial_value=20
    )

    # x_1 pre-defined discrete values
    feasible_values = np.array(
        [
            0.20,
            0.31,
            0.40,
            0.44,
            0.60,
            0.62,
            0.79,
            0.80,
            0.88,
            0.93,
            1.0,
            1.20,
            1.24,
            1.32,
            1.40,
            1.55,
            1.58,
            1.60,
            1.76,
            1.80,
            1.86,
            2.0,
            2.17,
            2.20,
            2.37,
            2.40,
            2.48,
            2.60,
            2.64,
            2.79,
            2.80,
            3.0,
            3.08,
            3.10,
            3.16,
            3.41,
            3.52,
            3.60,
            3.72,
            3.95,
            3.96,
            4.0,
            4.03,
            4.20,
            4.34,
            4.40,
            4.65,
            4.74,
            4.80,
            4.84,
            5.0,
            5.28,
            5.40,
            5.53,
            5.72,
            6.0,
            6.16,
            6.32,
            6.60,
            7.11,
            7.20,
            7.80,
            7.90,
            8.0,
            8.40,
            8.69,
            9.0,
            9.48,
            10.27,
            11.0,
            11.06,
            11.85,
            12.0,
            13.0,
            14.0,
            15.0,
        ]
    )

    variables = [x_2, x_3]

    # forming a set of variables and a constraint to make sure x_1 is from the set of feasible values
    x_1_eprs = []
    for i in range(len(feasible_values)):
        x = Variable(
            name=f"x_1_{i}", symbol=f"x_1_{i}", variable_type=VariableTypeEnum.binary, lowerbound=0, upperbound=1
        )
        variables.append(x)
        expr = f"x_1_{i} * {feasible_values[i]}"
        x_1_eprs.append(expr)
    x_1_eprs = " + ".join(x_1_eprs)

    sum_expr = [f"x_1_{i}" for i in range(len(feasible_values))]
    sum_expr = " + ".join(sum_expr) + " - 1"

    x_1_con = Constraint(
        name="x_1_con", symbol="x_1_con", cons_type=ConstraintTypeEnum.EQ, func=sum_expr, is_linear=True
    )

    g_1 = Constraint(
        name="g_1",
        symbol="g_1",
        cons_type=ConstraintTypeEnum.LTE,
        func=f"- (({x_1_eprs}) * x_3 - 7.735 * (({x_1_eprs})**2 / x_2) - 180)",
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    g_2 = Constraint(
        name="g_2",
        symbol="g_2",
        cons_type=ConstraintTypeEnum.LTE,
        func="-(4 - x_3 / x_2)",
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )

    f_1 = Objective(
        name="f_1",
        symbol="f_1",
        func=f"29.4 * ({x_1_eprs}) + 0.6 * x_2 * x_3",
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    f_2 = Objective(
        name="f_2",
        symbol="f_2",
        func=f"Max(({x_1_eprs}) * x_3 - 7.735 * (({x_1_eprs})**2 / x_2) - 180, 0) + Max(4 - x_3 / x_2, 0)",
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=False,
    )
    return Problem(
        name="re22",
        description="The reinforced concrete beam design problem",
        variables=variables,
        objectives=[f_1, f_2],
        constraints=[g_1, g_2, x_1_con],
    )

re23

re23() -> Problem

The pressure vessel design problem.

The objective functions and constraints for the pressure vessel design problem are defined as follows:

\[\begin{align} &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = 0.6224x_1x_3x_4 + 1.7781x_2x_3^2 + 3.1661x_1^2x_4 + 19.84x_1^2x_3 \\ &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = \sum_{i=1}^3 \max\{g_i(\mathbf{x}), 0\} \\ &\text{s.t.,} & g_1(\mathbf{x}) & = -x_1 + 0.0193x_3 \leq 0,\\ & & g_2(\mathbf{x}) & = -x_2 + 0.00954x_3 \leq 0, \\ & & g_3(\mathbf{x}) & = -\pi x_3^2x_4 - \frac{4}{3}\pi x_3^3 + 1\,296\,000 \leq 0. \end{align}\]
References

Kannan, B. K., & Kramer, S. N. (1994). An augmented Lagrange multiplier based method for mixed integer discrete continuous optimization and its applications to mechanical design.

Tanabe, R. & Ishibuchi, H. (2020). An easy-to-use real-world multi-objective optimization problem suite. Applied soft computing, 89, 106078. https://doi.org/10.1016/j.asoc.2020.106078.

https://github.com/ryojitanabe/reproblems/blob/master/reproblem_python_ver/reproblem.py

Returns:

Name Type Description
Problem Problem

an instance of the pressure vessel design problem.

Source code in desdeo/problem/testproblems.py
def re23() -> Problem:
    r"""The pressure vessel design problem.

    The objective functions and constraints for the pressure vessel design problem are defined as follows:

    \begin{align}
        &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = 0.6224x_1x_3x_4 + 1.7781x_2x_3^2 + 3.1661x_1^2x_4 + 19.84x_1^2x_3 \\
        &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = \sum_{i=1}^3 \max\{g_i(\mathbf{x}), 0\} \\
        &\text{s.t.,}   & g_1(\mathbf{x}) & = -x_1 + 0.0193x_3 \leq 0,\\
        & & g_2(\mathbf{x}) & = -x_2 + 0.00954x_3 \leq 0, \\
        & & g_3(\mathbf{x}) & = -\pi x_3^2x_4 - \frac{4}{3}\pi x_3^3 + 1\,296\,000 \leq 0.
    \end{align}

    References:
        Kannan, B. K., & Kramer, S. N. (1994). An augmented Lagrange multiplier based method
            for mixed integer discrete continuous optimization and its applications to mechanical design.

        Tanabe, R. & Ishibuchi, H. (2020). An easy-to-use real-world multi-objective
            optimization problem suite. Applied soft computing, 89, 106078.
            https://doi.org/10.1016/j.asoc.2020.106078.

        https://github.com/ryojitanabe/reproblems/blob/master/reproblem_python_ver/reproblem.py

    Returns:
        Problem: an instance of the pressure vessel design problem.
    """
    x_1 = Variable(name="x_1", symbol="x_1", variable_type=VariableTypeEnum.integer, lowerbound=1, upperbound=100)
    x_2 = Variable(name="x_2", symbol="x_2", variable_type=VariableTypeEnum.integer, lowerbound=1, upperbound=100)
    x_3 = Variable(name="x_3", symbol="x_3", variable_type=VariableTypeEnum.real, lowerbound=10, upperbound=200)
    x_4 = Variable(name="x_4", symbol="x_4", variable_type=VariableTypeEnum.real, lowerbound=10, upperbound=240)

    # variables x_1 and x_2 are integer multiples of 0.0625
    x_1_exprs = "(0.0625 * x_1)"
    x_2_exprs = "(0.0625 * x_2)"

    g_1 = Constraint(
        name="g_1",
        symbol="g_1",
        cons_type=ConstraintTypeEnum.LTE,
        func=f"-({x_1_exprs} - 0.0193 * x_3)",
        is_linear=True,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    g_2 = Constraint(
        name="g_2",
        symbol="g_2",
        cons_type=ConstraintTypeEnum.LTE,
        func=f"-({x_2_exprs} - 0.00954 * x_3)",
        is_linear=True,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    g_3 = Constraint(
        name="g_3",
        symbol="g_3",
        cons_type=ConstraintTypeEnum.LTE,
        func=f"-({np.pi} * x_3**2 * x_4 + (4/3) * {np.pi} * x_3**3 - 1296000)",
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )

    f_1 = Objective(
        name="f_1",
        symbol="f_1",
        func=f"0.6224 * {x_1_exprs} * x_3 * x_4 + (1.7781 * {x_2_exprs} * x_3**2) + (3.1661 * {x_1_exprs}**2 * x_4) + (19.84 * {x_1_exprs}**2 * x_3)",
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    f_2 = Objective(
        name="f_2",
        symbol="f_2",
        func=f"Max({x_1_exprs} - 0.0193 * x_3, 0) + Max({x_2_exprs} - 0.00954 * x_3, 0) + Max({np.pi} * x_3**2 * x_4 + (4/3) * {np.pi} * x_3**3 - 1296000, 0)",
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=False,
    )
    return Problem(
        name="re23",
        description="The pressure vessel design problem",
        variables=[x_1, x_2, x_3, x_4],
        objectives=[f_1, f_2],
        constraints=[g_1, g_2, g_3],
    )

re24

re24() -> Problem

The hatch cover design problem.

The objective functions and constraints for the hatch cover design problem are defined as follows:

\[\begin{align} &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = x_1 + 120x_2 \\ &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = \sum_{i=1}^4 \max\{g_i(\mathbf{x}), 0\} \\ &\text{s.t.,} & g_1(\mathbf{x}) & = 1.0 - \frac{\sigma_b}{\sigma_{b,max}} \geq 0,\\ & & g_2(\mathbf{x}) & = 1.0 - \frac{\tau}{\tau_{max}} \geq 0, \\ & & g_3(\mathbf{x}) & = 1.0 - \frac{\delta}{\delta_{max}} \geq 0, \\ & & g_4(\mathbf{x}) & = 1.0 - \frac{\sigma_b}{\sigma_{k}} \geq 0, \end{align}\]

where \(x_1 \in [0.5, 4]\) and \(x_2 \in [4, 50]\). The parameters are defined as \(\sigma_{b,max} = 700 kg/cm^2\), \(\tau_{max} = 450 kg/cm\), \(\delta_{max} = 1.5 cm\), \(\sigma_k = Ex_1^2/100 kg/cm^2\), \(\sigma_b = 4500/(x_1x_2) kg/cm^2\), \(\tau = 1800/x_2 kg/cm^2\), \(\delta = 56.2 \times 10^4/(Ex_1x_2^2)\), and \(E = 700\,000 kg/cm^2\).

References

Amir, H. M., & Hasegawa, T. (1989). Nonlinear mixed-discrete structural optimization. Journal of Structural Engineering, 115(3), 626-646.

Tanabe, R. & Ishibuchi, H. (2020). An easy-to-use real-world multi-objective optimization problem suite. Applied soft computing, 89, 106078. https://doi.org/10.1016/j.asoc.2020.106078.

https://github.com/ryojitanabe/reproblems/blob/master/reproblem_python_ver/reproblem.py

Returns:

Name Type Description
Problem Problem

an instance of the hatch cover design problem.

Source code in desdeo/problem/testproblems.py
def re24() -> Problem:
    r"""The hatch cover design problem.

    The objective functions and constraints for the hatch cover design problem are defined as follows:

    \begin{align}
        &\min_{\mathbf{x}} & f_1(\mathbf{x}) & = x_1 + 120x_2 \\
        &\min_{\mathbf{x}} & f_2(\mathbf{x}) & = \sum_{i=1}^4 \max\{g_i(\mathbf{x}), 0\} \\
        &\text{s.t.,}   & g_1(\mathbf{x}) & = 1.0 - \frac{\sigma_b}{\sigma_{b,max}} \geq 0,\\
        & & g_2(\mathbf{x}) & = 1.0 - \frac{\tau}{\tau_{max}} \geq 0, \\
        & & g_3(\mathbf{x}) & = 1.0 - \frac{\delta}{\delta_{max}} \geq 0, \\
        & & g_4(\mathbf{x}) & = 1.0 - \frac{\sigma_b}{\sigma_{k}} \geq 0,
    \end{align}

    where $x_1 \in [0.5, 4]$ and $x_2 \in [4, 50]$. The parameters are defined as $\sigma_{b,max} = 700 kg/cm^2$,
    $\tau_{max} = 450 kg/cm$, $\delta_{max} = 1.5 cm$, $\sigma_k = Ex_1^2/100 kg/cm^2$,
    $\sigma_b = 4500/(x_1x_2) kg/cm^2$, $\tau = 1800/x_2 kg/cm^2$, $\delta = 56.2 \times 10^4/(Ex_1x_2^2)$,
    and $E = 700\,000 kg/cm^2$.

    References:
        Amir, H. M., & Hasegawa, T. (1989). Nonlinear mixed-discrete structural optimization.
            Journal of Structural Engineering, 115(3), 626-646.

        Tanabe, R. & Ishibuchi, H. (2020). An easy-to-use real-world multi-objective
            optimization problem suite. Applied soft computing, 89, 106078.
            https://doi.org/10.1016/j.asoc.2020.106078.

        https://github.com/ryojitanabe/reproblems/blob/master/reproblem_python_ver/reproblem.py

    Returns:
        Problem: an instance of the hatch cover design problem.
    """
    x_1 = Variable(name="x_1", symbol="x_1", variable_type=VariableTypeEnum.real, lowerbound=0.5, upperbound=4)
    x_2 = Variable(name="x_2", symbol="x_2", variable_type=VariableTypeEnum.real, lowerbound=4, upperbound=50)

    sigma_b = "(4500 / (x_1 * x_2))"
    sigma_k = "((700000 * x_1**2) / 100)"
    tau = "(1800 / x_2)"
    delta = "(56.2 * 10**4 / (700000 * x_1 * x_2**2))"

    g_1 = Constraint(
        name="g_1",
        symbol="g_1",
        cons_type=ConstraintTypeEnum.LTE,
        func=f"-(1 - {sigma_b} / 700)",
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    g_2 = Constraint(
        name="g_2",
        symbol="g_2",
        cons_type=ConstraintTypeEnum.LTE,
        func=f"-(1 - {tau} / 450)",
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    g_3 = Constraint(
        name="g_3",
        symbol="g_3",
        cons_type=ConstraintTypeEnum.LTE,
        func=f"-(1 - {delta} / 1.5)",
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    g_4 = Constraint(
        name="g_4",
        symbol="g_4",
        cons_type=ConstraintTypeEnum.LTE,
        func=f"-(1 - {sigma_b} / {sigma_k})",
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )

    f_1 = Objective(
        name="f_1",
        symbol="f_1",
        func="x_1 + 120 * x_2",
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=True,
        is_convex=False,  # Not checked
        is_twice_differentiable=True,
    )
    f_2 = Objective(
        name="f_2",
        symbol="f_2",
        func=f"Max(-(1 - {sigma_b} / 700), 0) + Max(-(1 - {tau} / 450), 0) + Max(-(1 - {delta} / 1.5), 0) + Max(-(1 - {sigma_b} / {sigma_k}), 0)",
        objective_type=ObjectiveTypeEnum.analytical,
        is_linear=False,
        is_convex=False,  # Not checked
        is_twice_differentiable=False,
    )
    return Problem(
        name="re24",
        description="The hatch cover design problem",
        variables=[x_1, x_2],
        objectives=[f_1, f_2],
        constraints=[g_1, g_2, g_3, g_4],
    )

river_pollution_problem

river_pollution_problem(*, five_objective_variant: bool = True) -> Problem

Create a pydantic dataclass representation of the river pollution problem with either five or four variables.

The objective functions "DO city" (\(f_1\)), "DO municipality" (\(f_2), and "ROI fishery" (\)f_3\() and "ROI city" (\)f_4\() are to be maximized. If the four variant problem is used, the the "BOD deviation" objective function (\)f_5$) is not present, but if it is, it is to be minimized. The problem is defined as follows:

\[\begin{align*} \max f_1(x) &= 4.07 + 2.27 x_1 \\ \max f_2(x) &= 2.60 + 0.03 x_1 + 0.02 x_2 + \frac{0.01}{1.39 - x_1^2} + \frac{0.30}{1.39 - x_2^2} \\ \max f_3(x) &= 8.21 - \frac{0.71}{1.09 - x_1^2} \\ \max f_4(x) &= 0.96 - \frac{0.96}{1.09 - x_2^2} \\ \min f_5(x) &= \max(|x_1 - 0.65|, |x_2 - 0.65|) \\ \text{s.t.}\quad & 0.3 \leq x_1 \leq 1.0,\\ & 0.3 \leq x_2 \leq 1.0,\\ \end{align*}\]

where the fifth objective is part of the problem definition only if five_objective_variant = True.

Parameters:

Name Type Description Default
five_objective_variant bool

Whether to use to five objective function variant of the problem or not. Defaults to True.

True

Returns:

Name Type Description
Problem Problem

the river pollution problem.

References

Narula, Subhash C., and HRoland Weistroffer. "A flexible method for nonlinear multicriteria decision-making problems." IEEE Transactions on Systems, Man, and Cybernetics 19.4 (1989): 883-887.

Miettinen, Kaisa, and Marko M. Mäkelä. "Interactive method NIMBUS for nondifferentiable multiobjective optimization problems." Multicriteria Analysis: Proceedings of the XIth International Conference on MCDM, 1-6 August 1994, Coimbra, Portugal. Berlin, Heidelberg: Springer Berlin Heidelberg, 1997.

Source code in desdeo/problem/testproblems.py
def river_pollution_problem(*, five_objective_variant: bool = True) -> Problem:
    r"""Create a pydantic dataclass representation of the river pollution problem with either five or four variables.

    The objective functions "DO city" ($f_1$), "DO municipality" ($f_2), and
    "ROI fishery" ($f_3$) and "ROI city" ($f_4$) are to be
    maximized. If the four variant problem is used, the the "BOD deviation" objective
    function ($f_5$) is not present, but if it is, it is to be minimized.
    The problem is defined as follows:

    \begin{align*}
    \max f_1(x) &= 4.07 + 2.27 x_1 \\
    \max f_2(x) &= 2.60 + 0.03 x_1 + 0.02 x_2 + \frac{0.01}{1.39 - x_1^2} + \frac{0.30}{1.39 - x_2^2} \\
    \max f_3(x) &= 8.21 - \frac{0.71}{1.09 - x_1^2} \\
    \max f_4(x) &= 0.96 - \frac{0.96}{1.09 - x_2^2} \\
    \min f_5(x) &= \max(|x_1 - 0.65|, |x_2 - 0.65|) \\
    \text{s.t.}\quad    & 0.3 \leq x_1 \leq 1.0,\\
                        & 0.3 \leq x_2 \leq 1.0,\\
    \end{align*}

    where the fifth objective is part of the problem definition only if
    `five_objective_variant = True`.

    Args:
        five_objective_variant (bool, optional): Whether to use to five
            objective function variant of the problem or not. Defaults to True.

    Returns:
        Problem: the river pollution problem.

    References:
        Narula, Subhash C., and HRoland Weistroffer. "A flexible method for
            nonlinear multicriteria decision-making problems." IEEE Transactions on
            Systems, Man, and Cybernetics 19.4 (1989): 883-887.

        Miettinen, Kaisa, and Marko M. Mäkelä. "Interactive method NIMBUS for
            nondifferentiable multiobjective optimization problems." Multicriteria
            Analysis: Proceedings of the XIth International Conference on MCDM, 1-6
            August 1994, Coimbra, Portugal. Berlin, Heidelberg: Springer Berlin
            Heidelberg, 1997.
    """
    variable_1 = Variable(
        name="BOD", symbol="x_1", variable_type="real", lowerbound=0.3, upperbound=1.0, initial_value=0.65
    )
    variable_2 = Variable(
        name="DO", symbol="x_2", variable_type="real", lowerbound=0.3, upperbound=1.0, initial_value=0.65
    )

    f_1 = "4.07 + 2.27 * x_1"
    f_2 = "2.60 + 0.03 * x_1 + 0.02 * x_2 + 0.01 / (1.39 - x_1**2) + 0.30 / (1.39 - x_2**2)"
    f_3 = "8.21 - 0.71 / (1.09 - x_1**2)"
    f_4 = "0.96 - 0.96 / (1.09 - x_2**2)"
    f_5 = "Max(Abs(x_1 - 0.65), Abs(x_2 - 0.65))"

    objective_1 = Objective(
        name="DO city",
        symbol="f_1",
        func=f_1,
        maximize=True,
        ideal=6.34,
        nadir=4.75,
        is_convex=True,
        is_linear=True,
        is_twice_differentiable=True,
    )
    objective_2 = Objective(
        name="DO municipality",
        symbol="f_2",
        func=f_2,
        maximize=True,
        ideal=3.44,
        nadir=2.85,
        is_convex=False,
        is_linear=False,
        is_twice_differentiable=True,
    )
    objective_3 = Objective(
        name="ROI fishery",
        symbol="f_3",
        func=f_3,
        maximize=True,
        ideal=7.5,
        nadir=0.32,
        is_convex=True,
        is_linear=False,
        is_twice_differentiable=True,
    )
    objective_4 = Objective(
        name="ROI city",
        symbol="f_4",
        func=f_4,
        maximize=True,
        ideal=0,
        nadir=-9.70,
        is_convex=True,
        is_linear=False,
        is_twice_differentiable=True,
    )
    objective_5 = Objective(
        name="BOD deviation",
        symbol="f_5",
        func=f_5,
        maximize=False,
        ideal=0,
        nadir=0.35,
        is_convex=False,
        is_linear=False,
        is_twice_differentiable=False,
    )

    objectives = (
        [objective_1, objective_2, objective_3, objective_4, objective_5]
        if five_objective_variant
        else [objective_1, objective_2, objective_3, objective_4]
    )

    return Problem(
        name="The river pollution problem",
        description="The river pollution problem to maximize return of investments (ROI) and dissolved oxygen (DO).",
        variables=[variable_1, variable_2],
        objectives=objectives,
    )

river_pollution_problem_discrete

river_pollution_problem_discrete(*, five_objective_variant: bool = True) -> Problem

Create a pydantic dataclass representation of the river pollution problem with either five or four variables.

The objective functions "DO city" (\(f_1\)), "DO municipality" (\(f_2), and "ROI fishery" (\)f_3\() and "ROI city" (\)f_4\() are to be maximized. If the four variant problem is used, the the "BOD deviation" objective function (\)f_5$) is not present, but if it is, it is to be minimized. This version of the problem uses discrete representation of the variables and objectives and does not provide the analytical functions for the objectives.

Parameters:

Name Type Description Default
five_objective_variant bool

Whether to use to five objective function variant of the problem or not. Defaults to True.

True

Returns:

Name Type Description
Problem Problem

the river pollution problem.

References

Narula, Subhash C., and HRoland Weistroffer. "A flexible method for nonlinear multicriteria decision-making problems." IEEE Transactions on Systems, Man, and Cybernetics 19.4 (1989): 883-887.

Miettinen, Kaisa, and Marko M. Mäkelä. "Interactive method NIMBUS for nondifferentiable multiobjective optimization problems." Multicriteria Analysis: Proceedings of the XIth International Conference on MCDM, 1-6 August 1994, Coimbra, Portugal. Berlin, Heidelberg: Springer Berlin Heidelberg, 1997.

Source code in desdeo/problem/testproblems.py
def river_pollution_problem_discrete(*, five_objective_variant: bool = True) -> Problem:
    """Create a pydantic dataclass representation of the river pollution problem with either five or four variables.

    The objective functions "DO city" ($f_1$), "DO municipality" ($f_2), and
    "ROI fishery" ($f_3$) and "ROI city" ($f_4$) are to be
    maximized. If the four variant problem is used, the the "BOD deviation" objective
    function ($f_5$) is not present, but if it is, it is to be minimized.
    This version of the problem uses discrete representation of the variables and objectives and does not provide
    the analytical functions for the objectives.

    Args:
        five_objective_variant (bool, optional): Whether to use to five
            objective function variant of the problem or not. Defaults to True.

    Returns:
        Problem: the river pollution problem.

    References:
        Narula, Subhash C., and HRoland Weistroffer. "A flexible method for
            nonlinear multicriteria decision-making problems." IEEE Transactions on
            Systems, Man, and Cybernetics 19.4 (1989): 883-887.

        Miettinen, Kaisa, and Marko M. Mäkelä. "Interactive method NIMBUS for
            nondifferentiable multiobjective optimization problems." Multicriteria
            Analysis: Proceedings of the XIth International Conference on MCDM, 1-6
            August 1994, Coimbra, Portugal. Berlin, Heidelberg: Springer Berlin
            Heidelberg, 1997.
    """
    filename = "datasets/river_poll_4_objs.csv"
    trueVarNames = {"x_1": "BOD", "x_2": "DO"}
    trueObjNames = {"f1": "DO city", "f2": "DO municipality", "f3": "ROI fishery", "f4": "ROI city"}
    if five_objective_variant:
        filename = "datasets/river_poll_5_objs.csv"
        trueObjNames["f5"] = "BOD deviation"

    path = Path(__file__).parent.parent.parent / filename
    data = pl.read_csv(path, has_header=True)

    variables = [
        Variable(
            name=trueVarNames[varName],
            symbol=varName,
            variable_type=VariableTypeEnum.real,
            lowerbound=0.3,
            upperbound=1.0,
            initial_value=0.65,
        )
        for varName in trueVarNames
    ]
    maximize = {"f1": True, "f2": True, "f3": True, "f4": True, "f5": False}
    ideal = {objName: (data[objName].max() if maximize[objName] else data[objName].min()) for objName in trueObjNames}
    nadir = {objName: (data[objName].min() if maximize[objName] else data[objName].max()) for objName in trueObjNames}
    units = {"f1": "mg/L", "f2": "mg/L", "f3": "%", "f4": "%", "f5": "mg/L"}

    objectives = [
        Objective(
            name=trueObjNames[objName],
            symbol=objName,
            func=None,
            unit=units[objName],
            objective_type=ObjectiveTypeEnum.data_based,
            maximize=maximize[objName],
            ideal=ideal[objName],
            nadir=nadir[objName],
        )
        for objName in trueObjNames
    ]

    discrete_def = DiscreteRepresentation(
        variable_values=data[list(trueVarNames.keys())].to_dict(),
        objective_values=data[list(trueObjNames.keys())].to_dict(),
    )

    return Problem(
        name="The river pollution problem (Discrete)",
        description="The river pollution problem to maximize return of investments (ROI) and dissolved oxygen (DO).",
        variables=variables,
        objectives=objectives,
        discrete_representation=discrete_def,
    )

river_pollution_scenario

river_pollution_scenario() -> Problem

Defines the scenario-based uncertain variant of the river pollution problem.

The river pollution problem considers a river close to a city. There are two sources of pollution: industrial pollution from a fishery and municipal waste from the city. Two treatment plants (in the fishery and the city) are responsible for managing the pollution. Pollution is reported in pounds of biochemical oxygen demanding material (BOD), and water quality is measured in dissolved oxygen concentration (DO).

Cleaning water in the city increases the tax rate, and cleaning in the fishery reduces the return on investment. The problem is to improve the DO level in the city and at the municipality border (f1 and f2, respectively), while, at the same time, maximizing the percent return on investment at the fishery (f3) and minimizing additions to the city tax (f4).

Decision variables are:

  • x1: The proportional amount of BOD removed from water after the fishery (treatment plant 1).
  • x2: The proportional amount of BOD removed from water after the city (treatment plant 2).

The original problem considered specific values for all parameters. However, in this formulation, some parameters are deeply uncertain, and only a range of plausible values is known for each. These deeply uncertain parameters are as follows:

  • α ∈ [3, 4.24]: Water quality index after the fishery.
  • β ∈ [2.25, 2.4]: BOD reduction rate at treatment plant 1 (after the fishery).
  • δ ∈ [0.075, 0.092]: BOD reduction rate at treatment plant 2 (after the city).
  • ξ ∈ [0.067, 0.083]: Effective rate of BOD reduction at treatment plant 1 after the city.
  • η ∈ [1.2, 1.50]: Parameter used to calculate the effective BOD reduction rate at the second treatment plant.
  • r ∈ [5.1, 12.5]: Investment return rate.

The uncertain version of the river problem is formulated as follows:

\[ \\begin{equation} \\begin{array}{rll} \\text{maximize} & f_1(\\mathbf{x}) = & \\alpha + \\left(\\log\\left(\\left(\\frac{\\beta}{2} - 1.14\\right)^2\\right) + \\beta^3\\right) x_1 \\\\ \\text{maximize} & f_2(\\mathbf{x}) = & \\gamma + \\delta x_1 + \\xi x_2 + \\frac{0.01}{\\eta - x_1^2} + \\frac{0.30}{\\eta - x_2^2} \\\\ \\text{maximize} & f_3(\\mathbf{x}) = & r - \\frac{0.71}{1.09 - x_1^2} \\\\ \\text{minimize} & f_4(\\mathbf{x}) = & -0.96 + \\frac{0.96}{1.09 - x_2^2} \\\\ \\text{subject to} & & 0.3 \\leq x_1, x_2 \\leq 1.0. \\end{array} \\end{equation} \]

where \(\\gamma = \\log\\left(\\frac{\\alpha}{2} - 1\\right) + \\frac{\\alpha}{2} + 1.5\).

Returns:

Name Type Description
Problem Problem

the scenario-based river pollution problem.

References

Narula, Subhash C., and HRoland Weistroffer. "A flexible method for nonlinear multicriteria decision-making problems." IEEE Transactions on Systems, Man, and Cybernetics 19.4 (1989): 883-887.

Miettinen, Kaisa, and Marko M. Mäkelä. "Interactive method NIMBUS for nondifferentiable multiobjective optimization problems." Multicriteria Analysis: Proceedings of the XIth International Conference on MCDM, 1-6 August 1994, Coimbra, Portugal. Berlin, Heidelberg: Springer Berlin Heidelberg, 1997.

Source code in desdeo/problem/testproblems.py
def river_pollution_scenario() -> Problem:
    r"""Defines the scenario-based uncertain variant of the river pollution problem.

    The river pollution problem considers a river close to a city.
    There are two sources of pollution: industrial pollution from a
    fishery and municipal waste from the city. Two treatment plants
    (in the fishery and the city) are responsible for managing the pollution.
    Pollution is reported in pounds of biochemical oxygen demanding material (BOD),
    and water quality is measured in dissolved oxygen concentration (DO).

    Cleaning water in the city increases the tax rate, and cleaning in the
    fishery reduces the return on investment. The problem is to improve
    the DO level in the city and at the municipality border (`f1` and `f2`, respectively),
    while, at the same time, maximizing the percent return on investment at the fishery (`f3`)
    and minimizing additions to the city tax (`f4`).

    Decision variables are:

    * `x1`: The proportional amount of BOD removed from water after the fishery (treatment plant 1).
    * `x2`: The proportional amount of BOD removed from water after the city (treatment plant 2).

    The original problem considered specific values for all parameters. However, in this formulation,
    some parameters are deeply uncertain, and only a range of plausible values is known for each.
    These deeply uncertain parameters are as follows:

    * `α ∈ [3, 4.24]`: Water quality index after the fishery.
    * `β ∈ [2.25, 2.4]`: BOD reduction rate at treatment plant 1 (after the fishery).
    * `δ ∈ [0.075, 0.092]`: BOD reduction rate at treatment plant 2 (after the city).
    * `ξ ∈ [0.067, 0.083]`: Effective rate of BOD reduction at treatment plant 1 after the city.
    * `η ∈ [1.2, 1.50]`: Parameter used to calculate the effective BOD reduction rate at the second treatment plant.
    * `r ∈ [5.1, 12.5]`: Investment return rate.

    The uncertain version of the river problem is formulated as follows:

    $$ 
    \\begin{equation}
    \\begin{array}{rll}
    \\text{maximize}   & f_1(\\mathbf{x}) = & \\alpha + \\left(\\log\\left(\\left(\\frac{\\beta}{2} - 1.14\\right)^2\\right) + \\beta^3\\right) x_1 \\\\
    \\text{maximize}   & f_2(\\mathbf{x}) = & \\gamma + \\delta x_1 + \\xi x_2 + \\frac{0.01}{\\eta - x_1^2} + \\frac{0.30}{\\eta - x_2^2} \\\\
    \\text{maximize}   & f_3(\\mathbf{x}) = & r - \\frac{0.71}{1.09 - x_1^2} \\\\
    \\text{minimize}   & f_4(\\mathbf{x}) = & -0.96 + \\frac{0.96}{1.09 - x_2^2} \\\\
    \\text{subject to} & & 0.3 \\leq x_1, x_2 \\leq 1.0.
    \\end{array}
    \\end{equation}
    $$

    where $\\gamma = \\log\\left(\\frac{\\alpha}{2} - 1\\right) + \\frac{\\alpha}{2} + 1.5$.

    Returns:
        Problem: the scenario-based river pollution problem.

    References:
        Narula, Subhash C., and HRoland Weistroffer. "A flexible method for
            nonlinear multicriteria decision-making problems." IEEE Transactions on
            Systems, Man, and Cybernetics 19.4 (1989): 883-887.

        Miettinen, Kaisa, and Marko M. Mäkelä. "Interactive method NIMBUS for
            nondifferentiable multiobjective optimization problems." Multicriteria
            Analysis: Proceedings of the XIth International Conference on MCDM, 1-6
            August 1994, Coimbra, Portugal. Berlin, Heidelberg: Springer Berlin
            Heidelberg, 1997.
    """
    num_scenarios = 6
    scenario_key_stub = "scenario"

    # defining scenario parameters
    alpha_values = [4.070, 3.868, 3.620, 3.372, 3.124, 4.116]
    beta_values = [2.270, 2.262, 2.278, 2.254, 2.270, 2.286]
    delta_values = [0.0800, 0.0869, 0.0835, 0.0903, 0.0801, 0.0767]
    xi_values = [0.0750, 0.0782, 0.0750, 0.0814, 0.0686, 0.0718]
    eta_values = [1.39, 1.47, 1.23, 1.35, 1.29, 1.41]
    r_values = [8.21, 10.28, 5.84, 11.76, 7.32, 8.80]

    # each scenario parameter is defined as its own tensor constant
    alpha_constant = TensorConstant(
        name="Water quality index after fishery", symbol="alpha", shape=[num_scenarios], values=alpha_values
    )
    beta_constant = TensorConstant(
        name="BOD reduction rate at treatment plant 1 (after the fishery)",
        symbol="beta",
        shape=[num_scenarios],
        values=beta_values,
    )
    delta_constant = TensorConstant(
        name="BOD reduction rate at treatment plant 2 (after the city)",
        symbol="delta",
        shape=[num_scenarios],
        values=delta_values,
    )
    xi_constant = TensorConstant(
        name="The effective rate of BOD reduction at treatment plant 1 (after the city)",
        symbol="xi",
        shape=[num_scenarios],
        values=xi_values,
    )
    eta_constant = TensorConstant(
        name="The effective rate of BOD reduction rate at plant 2 (after the fishery)",
        symbol="eta",
        shape=[num_scenarios],
        values=eta_values,
    )
    r_constant = TensorConstant(
        name="Investment return rate",
        symbol="r",
        shape=[num_scenarios],
        values=r_values,
    )

    constants = [alpha_constant, beta_constant, delta_constant, xi_constant, eta_constant, r_constant]

    # define variables
    x1 = Variable(
        name="BOD removed after fishery",
        symbol="x_1",
        variable_type=VariableTypeEnum.real,
        lowerbound=0.3,
        upperbound=1.0,
    )

    x2 = Variable(
        name="BOD removed after city",
        symbol="x_2",
        variable_type=VariableTypeEnum.real,
        lowerbound=0.3,
        upperbound=1.0,
    )

    variables = [x1, x2]

    # define objectives for each scenario
    objectives = []
    scenario_keys = []

    for i in range(num_scenarios):
        scenario_key = f"{scenario_key_stub}_{i+1}"
        scenario_keys.append(scenario_key)

        gamma_expr = f"Ln(alpha[{i+1}]/2 - 1) + alpha[{i+1}]/2 + 1.5"

        f1_expr = f"alpha[{i+1}] + (Ln((beta[{i+1}]/2 - 1.14)**2) + beta[{i+1}]**3)*x_1"
        f2_expr = (
            f"{gamma_expr} + delta[{i+1}]*x_1 + xi[{i+1}]*x_2 + 0.01/(eta[{i+1}] - x_1**2) + 0.3/(eta[{i+1}] - x_2**2)"
        )
        f3_expr = f"r[{i+1}]  - 0.71/(1.09 - x_1**2)"

        # f1
        objectives.append(
            Objective(
                name="DO level city",
                symbol=f"f1_{i+1}",
                scenario_keys=[scenario_key],
                func=f1_expr,
                objective_type=ObjectiveTypeEnum.analytical,
                maximize=True,
                is_linear=False,
                is_convex=False,
                is_twice_differentiable=True,
            )
        )

        # f2
        objectives.append(
            Objective(
                name="DO level fishery",
                symbol=f"f2_{i+1}",
                scenario_keys=[scenario_key],
                func=f2_expr,
                objective_type=ObjectiveTypeEnum.analytical,
                maximize=True,
                is_linear=False,
                is_convex=False,
                is_twice_differentiable=True,
            )
        )

        # f3
        objectives.append(
            Objective(
                name="Return of investment",
                symbol=f"f3_{i+1}",
                scenario_keys=[scenario_key],
                func=f3_expr,
                objective_type=ObjectiveTypeEnum.analytical,
                maximize=True,
                is_linear=False,
                is_convex=False,
                is_twice_differentiable=True,
            )
        )

    f4_expr = "-0.96 + 0.96/(1.09 - x_2**2)"

    # f4, by setting the scenario_key to None, the objective function is assumed to be part of all the scenarios.
    objectives.append(
        Objective(
            name="Addition to city tax",
            symbol="f4",
            scenario_keys=None,
            func=f4_expr,
            objective_type=ObjectiveTypeEnum.analytical,
            maximize=False,
            is_linear=False,
            is_convex=False,
            is_twice_differentiable=True,
        )
    )

    return Problem(
        name="Scenario-based river pollution problem",
        description="The scenario-based river pollution problem",
        constants=constants,
        variables=variables,
        objectives=objectives,
        scenario_keys=scenario_keys,
    )

simple_data_problem

simple_data_problem() -> Problem

Defines a simple problem with only data-based objective functions.

Source code in desdeo/problem/testproblems.py
def simple_data_problem() -> Problem:
    """Defines a simple problem with only data-based objective functions."""
    constants = [Constant(name="c", symbol="c", value=1000)]

    n_var = 5
    variables = [
        Variable(
            name=f"y_{i}",
            symbol=f"y_{i}",
            variable_type=VariableTypeEnum.real,
            lowerbound=-50.0,
            upperbound=50.0,
            initial_value=0.1,
        )
        for i in range(1, n_var + 1)
    ]

    n_objectives = 3
    # only the first objective is to be maximized, the rest are to be minimized
    objectives = [
        Objective(
            name=f"g_{i}",
            symbol=f"g_{i}",
            func=None,
            objective_type=ObjectiveTypeEnum.data_based,
            maximize=i == 1,
            ideal=3000 if i == 1 else -60.0 if i == 3 else 0,
            nadir=0 if i == 1 else 15 - 2.0 if i == 3 else 15,
        )
        for i in range(1, n_objectives + 1)
    ]

    constraints = [Constraint(name="cons 1", symbol="c_1", cons_type=ConstraintTypeEnum.EQ, func="y_1 + y_2 - c")]

    data_len = 10
    var_data = {f"y_{i}": [i * 0.5 + j for j in range(data_len)] for i in range(1, n_var + 1)}
    obj_data = {
        "g_1": [sum(var_data[f"y_{j}"][i] for j in range(1, n_var + 1)) ** 2 for i in range(data_len)],
        "g_2": [max(var_data[f"y_{j}"][i] for j in range(1, n_var + 1)) for i in range(data_len)],
        "g_3": [-sum(var_data[f"y_{j}"][i] for j in range(1, n_var + 1)) for i in range(data_len)],
    }

    discrete_def = DiscreteRepresentation(variable_values=var_data, objective_values=obj_data)

    return Problem(
        name="Simple data problem",
        description="Simple problem with all objectives being data-based. Has constraints and a constant also.",
        constants=constants,
        variables=variables,
        objectives=objectives,
        constraints=constraints,
        discrete_representation=discrete_def,
    )

simple_integer_test_problem

simple_integer_test_problem() -> Problem

Defines a simple integer problem suitable for testing purposes.

Source code in desdeo/problem/testproblems.py
def simple_integer_test_problem() -> Problem:
    """Defines a simple integer problem suitable for testing purposes."""
    variables = [
        Variable(
            name="x_1",
            symbol="x_1",
            variable_type=VariableTypeEnum.integer,
            lowerbound=0,
            upperbound=10,
            initial_value=5,
        ),
        Variable(
            name="x_2",
            symbol="x_2",
            variable_type=VariableTypeEnum.integer,
            lowerbound=0,
            upperbound=10,
            initial_value=5,
        ),
        Variable(
            name="x_3",
            symbol="x_3",
            variable_type=VariableTypeEnum.integer,
            lowerbound=0,
            upperbound=10,
            initial_value=5,
        ),
        Variable(
            name="x_4",
            symbol="x_4",
            variable_type=VariableTypeEnum.integer,
            lowerbound=0,
            upperbound=10,
            initial_value=5,
        ),
    ]

    constants = [Constant(name="c", symbol="c", value=4.2)]

    f_1 = "x_1 + x_2 + x_3"
    f_2 = "x_2**x_4 - x_3**x_1"
    f_3 = "x_1 - x_2 + x_3*x_4"
    f_4 = "Max(Abs(x_1 - x_2), c) + Max(x_3, x_4)"  # c = 4.2
    f_5 = "(-x_1) * (-x_2)"

    objectives = [
        Objective(name="f_1", symbol="f_1", func=f_1, maximize=False),  # min!
        Objective(name="f_2", symbol="f_2", func=f_2, maximize=True),  # max!
        Objective(name="f_3", symbol="f_3", func=f_3, maximize=True),  # max!
        Objective(name="f_4", symbol="f_4", func=f_4, maximize=False),  # min!
        Objective(name="f_5", symbol="f_5", func=f_5, maximize=True),  # max!
    ]

    return Problem(
        name="Simple integer test problem.",
        description="A simple problem for testing purposes.",
        constants=constants,
        variables=variables,
        objectives=objectives,
    )

simple_knapsack

simple_knapsack() -> Problem

Defines a simple multiobjective knapsack problem.

Given a set of 4 items, each with a weight and three values corresponding to different objectives, the problem is defined as follows:

  • Item 1: weight = 2, values = (5, 10, 15)
  • Item 2: weight = 3, values = (4, 7, 9)
  • Item 3: weight = 1, values = (3, 5, 8)
  • Item 4: weight = 4, values = (2, 3, 5)

The problem is then to maximize the following functions:

\[\begin{align*} f_1(x) &= 5x_1 + 4x_2 + 3x_3 + 2x_4 \\ f_2(x) &= 10x_1 + 7x_2 + 5x_3 + 3x_4 \\ f_3(x) &= 15x_1 + 9x_2 + 8x_3 + 5x_4 \\ \text{s.t.}\quad & 2x_1 + 3x_2 + 1x_3 + 4x_4 \leq 7 \\ & x_i \in \{0,1\} \quad \text{for} \quad i = 1, 2, 3, 4, \end{align*}\]

where the inequality constraint is a weight constraint. The problem is a binary variable problem.

Returns:

Name Type Description
Problem Problem

the simple knapsack problem.

Source code in desdeo/problem/testproblems.py
def simple_knapsack() -> Problem:
    r"""Defines a simple multiobjective knapsack problem.

    Given a set of 4 items, each with a weight and three values corresponding to
    different objectives, the problem is defined as follows:

    -   Item 1: weight = 2, values = (5, 10, 15)
    -   Item 2: weight = 3, values = (4, 7, 9)
    -   Item 3: weight = 1, values = (3, 5, 8)
    -   Item 4: weight = 4, values = (2, 3, 5)

    The problem is then to maximize the following functions:

    \begin{align*}
    f_1(x) &= 5x_1 + 4x_2 + 3x_3 + 2x_4 \\
    f_2(x) &= 10x_1 + 7x_2 + 5x_3 + 3x_4 \\
    f_3(x) &= 15x_1 + 9x_2 + 8x_3 + 5x_4 \\
    \text{s.t.}\quad & 2x_1 + 3x_2 + 1x_3 + 4x_4 \leq 7 \\
    & x_i \in \{0,1\} \quad \text{for} \quad i = 1, 2, 3, 4,
    \end{align*}

    where the inequality constraint is a weight constraint. The problem is a binary variable problem.

    Returns:
        Problem: the simple knapsack problem.
    """
    variables = [
        Variable(
            name=f"x_{i}",
            symbol=f"x_{i}",
            variable_type=VariableTypeEnum.binary,
            lowerbound=0,
            upperbound=1,
            initial_value=0,
        )
        for i in range(1, 5)
    ]

    exprs = {
        "f1": "5*x_1 + 4*x_2 + 3*x_3 + 2*x_4",
        "f2": "10*x_1 + 7*x_2 + 5*x_3 + 3*x_4",
        "f3": "15*x_1 + 9*x_2 + 8*x_3 + 5*x_4",
    }

    ideals = {"f1": 15, "f2": 25, "f3": 37}

    objectives = [
        Objective(
            name=f"f_{i}",
            symbol=f"f_{i}",
            func=exprs[f"f{i}"],
            maximize=True,
            ideal=ideals[f"f{i}"],
            nadir=0,
            objective_type=ObjectiveTypeEnum.analytical,
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
        )
        for i in range(1, 4)
    ]

    constraints = [
        Constraint(
            name="Weight constraint",
            symbol="g_w",
            cons_type=ConstraintTypeEnum.LTE,
            func="2*x_1 + 3*x_2 + 1*x_3 + 4*x_4 - 7",
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
        )
    ]

    return Problem(
        name="Simple knapsack",
        description="A simple knapsack problem with three objectives to be maximized.",
        variables=variables,
        objectives=objectives,
        constraints=constraints,
    )

simple_knapsack_vectors

simple_knapsack_vectors()

Define a simple variant of the knapsack problem that utilizes vectors (TensorVariable and TensorConstant).

Source code in desdeo/problem/testproblems.py
def simple_knapsack_vectors():
    """Define a simple variant of the knapsack problem that utilizes vectors (TensorVariable and TensorConstant)."""
    n_items = 4
    weight_values = [2, 3, 4, 5]
    profit_values = [3, 5, 6, 8]
    efficiency_values = [4, 2, 7, 3]

    max_weight = Constant(name="Maximum weights", symbol="w_max", value=5)

    weights = TensorConstant(name="Weights of the items", symbol="W", shape=[len(weight_values)], values=weight_values)
    profits = TensorConstant(name="Profits", symbol="P", shape=[len(profit_values)], values=profit_values)
    efficiencies = TensorConstant(
        name="Efficiencies", symbol="E", shape=[len(efficiency_values)], values=efficiency_values
    )

    choices = TensorVariable(
        name="Chosen items",
        symbol="X",
        shape=[n_items],
        variable_type="binary",
        lowerbounds=n_items * [0],
        upperbounds=n_items * [1],
        initial_values=n_items * [1],
    )

    profit_objective = Objective(
        name="max profit",
        symbol="f_1",
        func="P@X",
        maximize=True,
        ideal=8,
        nadir=0,
        is_linear=True,
        is_convex=False,
        is_twice_differentiable=False,
    )

    efficiency_objective = Objective(
        name="max efficiency",
        symbol="f_2",
        func="E@X",
        maximize=True,
        ideal=7,
        nadir=0,
        is_linear=True,
        is_convex=False,
        is_twice_differentiable=False,
    )

    weight_constraint = Constraint(
        name="Weight constraint",
        symbol="g_1",
        cons_type="<=",
        func="W@X - w_max",
        is_linear=True,
        is_convex=False,
        is_twice_differentiable=False,
    )

    return Problem(
        name="Simple two-objective Knapsack problem",
        description="A simple variant of the classic combinatorial problem.",
        constants=[max_weight, weights, profits, efficiencies],
        variables=[choices],
        objectives=[profit_objective, efficiency_objective],
        constraints=[weight_constraint],
    )

simple_linear_test_problem

simple_linear_test_problem() -> Problem

Defines a simple single objective linear problem suitable for testing purposes.

Source code in desdeo/problem/testproblems.py
def simple_linear_test_problem() -> Problem:
    """Defines a simple single objective linear problem suitable for testing purposes."""
    variables = [
        Variable(name="x_1", symbol="x_1", variable_type="real", lowerbound=-10, upperbound=10, initial_value=5),
        Variable(name="x_2", symbol="x_2", variable_type="real", lowerbound=-10, upperbound=10, initial_value=5),
    ]

    constants = [Constant(name="c", symbol="c", value=4.2)]

    f_1 = "x_1 + x_2"

    objectives = [
        Objective(name="f_1", symbol="f_1", func=f_1, maximize=False),  # min!
    ]

    con_1 = Constraint(name="g_1", symbol="g_1", cons_type=ConstraintTypeEnum.LTE, func="c - x_1")
    con_2 = Constraint(name="g_2", symbol="g_2", cons_type=ConstraintTypeEnum.LTE, func="0.5*x_1 - x_2")

    return Problem(
        name="Simple linear test problem.",
        description="A simple problem for testing purposes.",
        constants=constants,
        variables=variables,
        constraints=[con_1, con_2],
        objectives=objectives,
    )

simple_scenario_test_problem

simple_scenario_test_problem()

Returns a simple, scenario-based multiobjective optimization test problem.

Source code in desdeo/problem/testproblems.py
def simple_scenario_test_problem():
    """Returns a simple, scenario-based multiobjective optimization test problem."""
    constants = [Constant(name="c_1", symbol="c_1", value=3)]
    variables = [
        Variable(
            name="x_1",
            symbol="x_1",
            lowerbound=-5.1,
            upperbound=6.2,
            initial_value=0,
            variable_type=VariableTypeEnum.real,
        ),
        Variable(
            name="x_2",
            symbol="x_2",
            lowerbound=-5.2,
            upperbound=6.1,
            initial_value=0,
            variable_type=VariableTypeEnum.real,
        ),
    ]

    constraints = [
        Constraint(
            name="con_1",
            symbol="con_1",
            cons_type=ConstraintTypeEnum.LTE,
            func="x_1 + x_2 - 15",
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys="s_1",
        ),
        Constraint(
            name="con_2",
            symbol="con_2",
            cons_type=ConstraintTypeEnum.LTE,
            func="x_1 + x_2 - 65",
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys="s_2",
        ),
        Constraint(
            name="con_3",
            symbol="con_3",
            cons_type=ConstraintTypeEnum.LTE,
            func="x_2 - 50",
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys=None,
        ),
        Constraint(
            name="con_4",
            symbol="con_4",
            cons_type=ConstraintTypeEnum.LTE,
            func="x_1 - 5",
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys=["s_1", "s_2"],
        ),
    ]

    expr_1 = "x_1 + x_2"
    expr_2 = "x_1 - x_2"
    expr_3 = "(x_1 - 3)**2 + x_2"
    expr_4 = "c_1 + x_2**2 - x_1"
    expr_5 = "-x_1 - x_2"

    objectives = [
        Objective(
            name="f_1",
            symbol="f_1",
            func=expr_1,
            maximize=False,
            ideal=-100,
            nadir=100,
            objective_type=ObjectiveTypeEnum.analytical,
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys="s_1",
        ),
        Objective(
            name="f_2",
            symbol="f_2",
            func=expr_2,
            maximize=False,
            ideal=-100,
            nadir=100,
            objective_type=ObjectiveTypeEnum.analytical,
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys=["s_1", "s_2"],
        ),
        Objective(
            name="f_3",
            symbol="f_3",
            func=expr_3,
            maximize=False,
            ideal=-100,
            nadir=100,
            objective_type=ObjectiveTypeEnum.analytical,
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys=None,
        ),
        Objective(
            name="f_4",
            symbol="f_4",
            func=expr_4,
            maximize=False,
            ideal=-100,
            nadir=100,
            objective_type=ObjectiveTypeEnum.analytical,
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys="s_2",
        ),
        Objective(
            name="f_5",
            symbol="f_5",
            func=expr_5,
            maximize=False,
            ideal=-100,
            nadir=100,
            objective_type=ObjectiveTypeEnum.analytical,
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys="s_2",
        ),
    ]

    extra_funcs = [
        ExtraFunction(
            name="extra_1",
            symbol="extra_1",
            func="5*x_1",
            is_linear=True,
            is_convex=True,
            is_twice_differentiable=True,
            scenario_keys="s_2",
        )
    ]

    return Problem(
        name="Simple scenario test problem",
        description="For testing the implementation of scenario-based problems.",
        variables=variables,
        constants=constants,
        constraints=constraints,
        objectives=objectives,
        extra_funcs=extra_funcs,
        scenario_keys=["s_1", "s_2"],
    )

simple_test_problem

simple_test_problem() -> Problem

Defines a simple problem suitable for testing purposes.

Source code in desdeo/problem/testproblems.py
def simple_test_problem() -> Problem:
    """Defines a simple problem suitable for testing purposes."""
    variables = [
        Variable(name="x_1", symbol="x_1", variable_type="real", lowerbound=0, upperbound=10, initial_value=5),
        Variable(name="x_2", symbol="x_2", variable_type="real", lowerbound=0, upperbound=10, initial_value=5),
    ]

    constants = [Constant(name="c", symbol="c", value=4.2)]

    f_1 = "x_1 + x_2"
    f_2 = "x_2**3"
    f_3 = "x_1 + x_2"
    f_4 = "Max(Abs(x_1 - x_2), c)"  # c = 4.2
    f_5 = "(-x_1) * (-x_2)"

    objectives = [
        Objective(name="f_1", symbol="f_1", func=f_1, maximize=False),  # min!
        Objective(name="f_2", symbol="f_2", func=f_2, maximize=True),  # max!
        Objective(name="f_3", symbol="f_3", func=f_3, maximize=True),  # max!
        Objective(name="f_4", symbol="f_4", func=f_4, maximize=False),  # min!
        Objective(name="f_5", symbol="f_5", func=f_5, maximize=True),  # max!
    ]

    return Problem(
        name="Simple test problem.",
        description="A simple problem for testing purposes.",
        constants=constants,
        variables=variables,
        objectives=objectives,
    )

simulator_problem

simulator_problem(file_dir: str | Path)

A test problem with analytical, simulator and surrogate based objectives, constraints and extra functions.

The problem uses two different simulator files. There are also objectives, constraints and extra fucntions that are surrogate based but it is assumed that the surrogate models are given when evaluating (while testing they are stored as temporary directories and files by pytest). There are also analytical functions to test utilizing PolarsEvaluator from the simulator evaluator.

Parameters:

Name Type Description Default
file_dir str | Path

path to the directory with the simulator files.

required
Source code in desdeo/problem/testproblems.py
def simulator_problem(file_dir: str | Path):
    """A test problem with analytical, simulator and surrogate based objectives, constraints and extra functions.

    The problem uses two different simulator files. There are also objectives, constraints and extra fucntions that
    are surrogate based but it is assumed that the surrogate models are given when evaluating (while testing they
    are stored as temporary directories and files by pytest). There are also analytical functions to test utilizing
    PolarsEvaluator from the simulator evaluator.

    Args:
        file_dir (str | Path): path to the directory with the simulator files.
    """
    variables = [
        Variable(name="x_1", symbol="x_1", variable_type=VariableTypeEnum.real),
        Variable(name="x_2", symbol="x_2", variable_type=VariableTypeEnum.real),
        Variable(name="x_3", symbol="x_3", variable_type=VariableTypeEnum.real),
        Variable(name="x_4", symbol="x_4", variable_type=VariableTypeEnum.real),
    ]
    f1 = Objective(
        name="f_1",
        symbol="f_1",
        simulator_path=Path(f"{file_dir}/simulator_file.py"),
        objective_type=ObjectiveTypeEnum.simulator,
    )
    f2 = Objective(
        name="f_2", symbol="f_2", func="x_1 + x_2 + x_3", maximize=True, objective_type=ObjectiveTypeEnum.analytical
    )
    f3 = Objective(
        name="f_3",
        symbol="f_3",
        maximize=True,
        simulator_path=f"{file_dir}/simulator_file2.py",
        objective_type=ObjectiveTypeEnum.simulator,
    )
    f4 = Objective(
        name="f_4",
        symbol="f_4",
        simulator_path=f"{file_dir}/simulator_file.py",
        objective_type=ObjectiveTypeEnum.simulator,
    )
    f5 = Objective(name="f_5", symbol="f_5", objective_type=ObjectiveTypeEnum.surrogate)
    f6 = Objective(name="f_6", symbol="f_6", objective_type=ObjectiveTypeEnum.surrogate)
    g1 = Constraint(
        name="g_1",
        symbol="g_1",
        cons_type=ConstraintTypeEnum.LTE,
        simulator_path=f"{file_dir}/simulator_file2.py",
    )
    g2 = Constraint(
        name="g_2",
        symbol="g_2",
        cons_type=ConstraintTypeEnum.LTE,
        func="-x_1 - x_2 - x_3",
    )
    g3 = Constraint(
        name="g_3",
        symbol="g_3",
        cons_type=ConstraintTypeEnum.LTE,
    )
    e1 = ExtraFunction(name="e_1", symbol="e_1", simulator_path=f"{file_dir}/simulator_file.py")
    e2 = ExtraFunction(name="e_2", symbol="e_2", func="x_1 * x_2 * x_3")
    e3 = ExtraFunction(
        name="e_3",
        symbol="e_3",
    )
    return Problem(
        name="Simulator problem",
        description="",
        variables=variables,
        objectives=[f1, f2, f3, f4, f5, f6],
        constraints=[g1, g2, g3],
        extra_funcs=[e1, e2, e3],
        simulators=[
            Simulator(
                name="s_1", symbol="s_1", file=Path(f"{file_dir}/simulator_file.py"), parameter_options={"delta": 0.5}
            ),
            Simulator(name="s_2", symbol="s_2", file=Path(f"{file_dir}/simulator_file2.py")),
        ],
    )

spanish_sustainability_problem

spanish_sustainability_problem()

Implements the Spanish sustainability problem.

Source code in desdeo/problem/testproblems.py
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
def spanish_sustainability_problem():
    """Implements the Spanish sustainability problem."""
    coefficients_dict = {
        "social_linear": {
            "x_1": -0.0108,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.185,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.00855,
            "x_10": 0.0,
            "x_11": 0.0,
        },
        "social_quadratic": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": 0.0,
        },
        "social_cubic": {
            "x_1": 0.0,
            "x_2": 9.79e-07,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": 0.0,
        },
        "social_log": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": 0.0,
        },
        "economical_linear": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.38,
            "x_5": 0.0281,
            "x_6": 0.0,
            "x_7": 0.00826,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": 0.0,
        },
        "economical_quadratic": {
            "x_1": -0.000316,
            "x_2": 3.18e-05,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.000662,
            "x_9": 0.0,
            "x_10": 1.81e-05,
            "x_11": 0.0,
        },
        "economical_cubic": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": 0.0,
        },
        "economical_log": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.121,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": -0.262,
        },
        "enviro_linear": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": -0.00122,
            "x_11": 0.0,
        },
        "enviro_quadratic": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": 0.0,
            "x_7": -0.000245,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": 1.2e-05,
        },
        "enviro_cubic": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": 0.0,
            "x_6": -2.37e-06,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": 0.0,
        },
        "enviro_log": {
            "x_1": 0.0,
            "x_2": 0.0,
            "x_3": 0.0,
            "x_4": 0.0,
            "x_5": -0.329,
            "x_6": 0.0,
            "x_7": 0.0,
            "x_8": 0.0,
            "x_9": 0.0,
            "x_10": 0.0,
            "x_11": 0.0,
        },
        "lower_bounds": {
            "x_1": 1,
            "x_2": 60,
            "x_3": 1,
            "x_4": 1,
            "x_5": 1,
            "x_6": 1,
            "x_7": 1,
            "x_8": 1,
            "x_9": 40,
            "x_10": 75,
            "x_11": 80,
        },
        "upper_bounds": {
            "x_1": 40,
            "x_2": 90,
            "x_3": 25,
            "x_4": 3,
            "x_5": 40,
            "x_6": 15,
            "x_7": 30,
            "x_8": 25,
            "x_9": 70,
            "x_10": 105,
            "x_11": 120,
        },
    }

    social_cte_value = -0.46
    economical_cte_value = 0.12
    enviro_cte_value = 2.92

    coefficients = (
        pl.DataFrame(coefficients_dict)
        .transpose(include_header=True, column_names=["coefficients"])
        .unnest("coefficients")
    )

    variable_names = [f"x_{i}" for i in range(1, 12)]
    n_variables = len(variable_names)

    # Define constants
    # For the social indicator
    social_linear = TensorConstant(
        name="Linear coefficients for the social indicator",
        symbol="beta_social",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "social_linear").row(0)[1:]),
    )

    social_quadratic = TensorConstant(
        name="Quadratic coefficients for the social indicator",
        symbol="gamma_social",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "social_quadratic").row(0)[1:]),
    )

    social_cubic = TensorConstant(
        name="Cubic coefficients for the social indicator",
        symbol="delta_social",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "social_cubic").row(0)[1:]),
    )

    social_log = TensorConstant(
        name="Logarithmic coefficients for the social indicator",
        symbol="omega_social",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "social_log").row(0)[1:]),
    )

    social_c = Constant(
        name="Constant coefficient for the social indicator", symbol="cte_social", value=social_cte_value
    )

    # For the economical indicator
    economical_linear = TensorConstant(
        name="Linear coefficients for the economical indicator",
        symbol="beta_economical",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "economical_linear").row(0)[1:]),
    )

    economical_quadratic = TensorConstant(
        name="Quadratic coefficients for the economical indicator",
        symbol="gamma_economical",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "economical_quadratic").row(0)[1:]),
    )

    economical_cubic = TensorConstant(
        name="Cubic coefficients for the economical indicator",
        symbol="delta_economical",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "economical_cubic").row(0)[1:]),
    )

    economical_log = TensorConstant(
        name="Logarithmic coefficients for the economical indicator",
        symbol="omega_economical",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "economical_log").row(0)[1:]),
    )

    economical_c = Constant(
        name="Constant coefficient for the economical indicator", symbol="cte_economical", value=economical_cte_value
    )

    # For the environmental indicator
    enviro_linear = TensorConstant(
        name="Linear coefficients for the environmental indicator",
        symbol="beta_enviro",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "enviro_linear").row(0)[1:]),
    )

    enviro_quadratic = TensorConstant(
        name="Quadratic coefficients for the environmental indicator",
        symbol="gamma_enviro",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "enviro_quadratic").row(0)[1:]),
    )

    enviro_cubic = TensorConstant(
        name="Cubic coefficients for the environmental indicator",
        symbol="delta_enviro",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "enviro_cubic").row(0)[1:]),
    )

    enviro_log = TensorConstant(
        name="Logarithmic coefficients for the environmental indicator",
        symbol="omega_enviro",
        shape=[n_variables],
        values=list(coefficients.filter(pl.col("column") == "enviro_log").row(0)[1:]),
    )

    enviro_c = Constant(
        name="Constant coefficient for the environmental indicator", symbol="cte_enviro", value=enviro_cte_value
    )

    constants = [
        social_linear,
        social_quadratic,
        social_cubic,
        social_log,
        social_c,
        economical_linear,
        economical_quadratic,
        economical_cubic,
        economical_log,
        economical_c,
        enviro_linear,
        enviro_quadratic,
        enviro_cubic,
        enviro_log,
        enviro_c,
    ]

    # Define variables
    x = TensorVariable(
        name="Variables 'x_1' through 'x_11' defined as a vector.",
        symbol="X",
        variable_type=VariableTypeEnum.real,
        shape=[n_variables],
        lowerbounds=list(coefficients.filter(pl.col("column") == "lower_bounds").row(0)[1:]),
        upperbounds=list(coefficients.filter(pl.col("column") == "upper_bounds").row(0)[1:]),
        initial_values=1.0,
    )

    variables = [x]

    # Define objective functions
    # Social
    f1_expr = "cte_social + X @ beta_social + (X**2) @ gamma_social + (X**3) @ delta_social + Ln(X) @ omega_social"

    f1 = Objective(
        name="Societal indicator",
        symbol="f1",
        func=f1_expr,
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=1.17,
        nadir=1.15,
        maximize=True,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    # economical
    f2_expr = (
        "cte_economical + beta_economical @ X + gamma_economical @ (X**2) + delta_economical @ (X**3) "
        "+ omega_economical @ Ln(X)"
    )

    f2 = Objective(
        name="economical indicator",
        symbol="f2",
        func=f2_expr,
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=1.98,
        nadir=0.63,
        maximize=True,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    # Environmental
    f3_expr = "cte_enviro + beta_enviro @ X + gamma_enviro @ (X**2) + delta_enviro @ (X**3) " "+ omega_enviro @ Ln(X)"

    f3 = Objective(
        name="Environmental indicator",
        symbol="f3",
        func=f3_expr,
        objective_type=ObjectiveTypeEnum.analytical,
        ideal=2.93,
        nadir=1.52,
        maximize=True,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    objectives = [f1, f2, f3]

    # Define constraints

    con_1_expr = "(18844.09 * X[3] + 31749.1) - X[9]**3"
    con_1 = Constraint(
        name="Independent X[3], dependent X[9]. Less than part.",
        symbol="con_1",
        func=con_1_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_2_expr = "X[9]**3 - (25429.65 * X[3] + 114818.5)"
    con_2 = Constraint(
        name="Independent X[3], dependent X[9]. More than part.",
        symbol="con_2",
        func=con_2_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_3_expr = "(0.0696724 * X[3] + 0.4026487) - X[4]"
    con_3 = Constraint(
        name="Independent X[3], dependent X[4]. Less than part.",
        symbol="con_3",
        func=con_3_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )

    con_4_expr = "X[4] - (0.1042275 * X[3] + 0.8385217)"
    con_4 = Constraint(
        name="Independent X[3], dependent X[4]. More than part.",
        symbol="con_4",
        func=con_4_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )

    con_5_expr = "(2.90e-06 * X[9]**3 + 0.2561155) - X[4]"
    con_5 = Constraint(
        name="Independent X[9]^3, dependent X[4]. Less than part.",
        symbol="con_5",
        func=con_5_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_6_expr = "X[4] - (4.07e-06 * X[9]**3 + 0.6763224)"
    con_6 = Constraint(
        name="Independent X[9]^3, dependent X[4]. More than part.",
        symbol="con_6",
        func=con_6_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_7_expr = "(-0.0121761 * X[6] + 4.272166) - Ln(X[9])"
    con_7 = Constraint(
        name="Independent X[6], dependent Ln(X[9]). Less than part.",
        symbol="con_7",
        func=con_7_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_8_expr = "Ln(X[9]) - (-0.0078968 * X[6] + 4.387051)"
    con_8 = Constraint(
        name="Independent X[6], dependent Ln(X[9]). More than part.",
        symbol="con_8",
        func=con_8_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_9_expr = "(-0.6514348 * Ln(X[1]) + 5.368645) - Ln(X[9])"
    con_9 = Constraint(
        name="Independent Ln(X[1]), dependent Ln(X[9]). Less than part.",
        symbol="con_9",
        func=con_9_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_10_expr = "Ln(X[9]) - (-0.3965489 * Ln(X[1]) + 6.174052)"
    con_10 = Constraint(
        name="Independent Ln(X[1]), dependent Ln(X[9]). More than part.",
        symbol="con_10",
        func=con_10_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_11_expr = "(-1.660054 * Ln(X[1]) + 3.524567) - Ln(X[4])"
    con_11 = Constraint(
        name="Independent Ln(X[1]), dependent Ln(X[4]). Less than part.",
        symbol="con_11",
        func=con_11_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_12_expr = "Ln(X[4]) - (-1.045873 * Ln(X[1]) + 5.4653)"
    con_12 = Constraint(
        name="Independent Ln(X[1]), dependent Ln(X[4]). More than part.",
        symbol="con_12",
        func=con_12_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_13_expr = "(54.36616 * X[1] - 1525.248) - X[6]**2"
    con_13 = Constraint(
        name="Independent X[1], dependent X[6]^2. Less than part.",
        symbol="con_13",
        func=con_13_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_14_expr = "X[6]**2 - (90.89275 * X[1] - 581.0572)"
    con_14 = Constraint(
        name="Independent X[1], dependent X[6]^2. More than part.",
        symbol="con_14",
        func=con_14_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_15_expr = "(0.5171291 * X[1]**3 + 4384.214) - X[7]**3"
    con_15 = Constraint(
        name="Independent X[1]^3, dependent X[7]^3. Less than part.",
        symbol="con_15",
        func=con_15_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_16_expr = "X[7]**3 - (0.7551735 * X[1]**3 + 13106.71)"
    con_16 = Constraint(
        name="Independent X[1]^3, dependent X[7]^3. More than part.",
        symbol="con_16",
        func=con_16_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_17_expr = "(-9.537996 * Ln(X[3]) + 36.99891) - X[7]"
    con_17 = Constraint(
        name="Independent Ln(X[3]), dependent X[7]. Less than part.",
        symbol="con_17",
        func=con_17_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_18_expr = "X[7] - (-5.908175 * Ln(X[3]) + 44.97534)"
    con_18 = Constraint(
        name="Independent Ln(X[3]), dependent X[7]. More than part.",
        symbol="con_18",
        func=con_18_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_19_expr = "(-1.233805 * Ln(X[9]) + 6.303354) - Ln(X[7])"
    con_19 = Constraint(
        name="Independent Ln(X[9]), dependent Ln(X[7]). Less than part.",
        symbol="con_19",
        func=con_19_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_20_expr = "Ln(X[7]) - (-0.7622909 * Ln(X[9]) + 8.251018)"
    con_20 = Constraint(
        name="Independent Ln(X[9]), dependent Ln(X[7]). More than part.",
        symbol="con_20",
        func=con_20_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_21_expr = "(0.0701477 * X[10] + 4.270586) - X[8]"
    con_21 = Constraint(
        name="Independent X[10], dependent X[8]. Less than part.",
        symbol="con_21",
        func=con_21_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )

    con_22_expr = "X[8] - (0.1216334 * X[10] + 6.975359)"
    con_22 = Constraint(
        name="Independent X[10], dependent X[8]. More than part.",
        symbol="con_22",
        func=con_22_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=True,
        is_convex=True,
        is_twice_differentiable=True,
    )

    con_23_expr = "(-11.7387 * Ln(X[4]) + 25.75422) - X[7]"
    con_23 = Constraint(
        name="Independent Ln(X[4]), dependent X[7]. Less than part.",
        symbol="con_23",
        func=con_23_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_24_expr = "X[7] - (-6.886529 * Ln(X[4]) + 28.89969)"
    con_24 = Constraint(
        name="Independent Ln(X[4]), dependent X[7]. More than part.",
        symbol="con_24",
        func=con_24_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_25_expr = "(-1217.427 * Ln(X[4]) + 773.2538) - X[6]**2"
    con_25 = Constraint(
        name="Independent Ln(X[4]), dependent X[6]^2. Less than part.",
        symbol="con_25",
        func=con_25_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_26_expr = "X[6]**2 - (-677.1691 * Ln(X[4]) + 1123.481)"
    con_26 = Constraint(
        name="Independent Ln(X[4]), dependent X[6]^2. More than part.",
        symbol="con_26",
        func=con_26_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_27_expr = "(-0.0793273 * X[1] + 3.300731) - Ln(X[3])"
    con_27 = Constraint(
        name="Independent X[1], dependent Ln(X[3]). Less than part.",
        symbol="con_27",
        func=con_27_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_28_expr = "Ln(X[3]) - (-0.0516687 * X[1] + 4.015687)"
    con_28 = Constraint(
        name="Independent X[1], dependent Ln(X[3]). More than part.",
        symbol="con_28",
        func=con_28_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_29_expr = "(-6.32e-06 * X[2]**3 + 3.694027) - Ln(X[6])"
    con_29 = Constraint(
        name="Independent X[2]^3, dependent Ln(X[6]). Less than part.",
        symbol="con_29",
        func=con_29_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_30_expr = "Ln(X[6]) - (-3.72e-06 * X[2]**3 + 4.566568)"
    con_30 = Constraint(
        name="Independent X[2]^3, dependent Ln(X[6]). More than part.",
        symbol="con_30",
        func=con_30_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_31_expr = "(-19.18876 * Ln(X[3]) + 44.91148) - X[6]"
    con_31 = Constraint(
        name="Independent Ln(X[3]), dependent X[6]. Less than part.",
        symbol="con_31",
        func=con_31_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_32_expr = "X[6] - (-12.08424 * Ln(X[3]) + 60.52347)"
    con_32 = Constraint(
        name="Independent Ln(X[3]), dependent X[6]. More than part.",
        symbol="con_32",
        func=con_32_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_33_expr = "(0.6393434 * Ln(X[4]) + 1.433712) - Ln(X[8])"
    con_33 = Constraint(
        name="Independent Ln(X[4]), dependent Ln(X[8]). Less than part.",
        symbol="con_33",
        func=con_33_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_34_expr = "Ln(X[8]) - (1.1418 * Ln(X[4]) + 1.759434)"
    con_34 = Constraint(
        name="Independent Ln(X[4]), dependent Ln(X[8]). More than part.",
        symbol="con_34",
        func=con_34_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_f1_1_expr = "-1.0*f1"
    con_f1_1 = Constraint(
        name="f1 greater than zero",
        symbol="con_f1_1",
        func=con_f1_1_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_f1_2_expr = "f1 - 4.0"
    con_f1_2 = Constraint(
        name="f1 less than four",
        symbol="con_f1_2",
        func=con_f1_2_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_f2_1_expr = "-1.0*f2"
    con_f2_1 = Constraint(
        name="f2 greater than zero",
        symbol="con_f2_1",
        func=con_f2_1_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_f2_2_expr = "f2 - 4.0"
    con_f2_2 = Constraint(
        name="f2 less than four",
        symbol="con_f2_2",
        func=con_f2_2_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_f3_1_expr = "-1.0*f3"
    con_f3_1 = Constraint(
        name="f3 greater than zero",
        symbol="con_f3_1",
        func=con_f3_1_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    con_f3_2_expr = "f3 - 4.0"
    con_f3_2 = Constraint(
        name="f3 less than four",
        symbol="con_f3_2",
        func=con_f3_2_expr,
        cons_type=ConstraintTypeEnum.LTE,
        is_linear=False,
        is_convex=False,
        is_twice_differentiable=True,
    )

    constraints = [
        con_1,
        con_2,
        con_3,
        con_4,
        con_5,
        con_6,
        con_7,
        con_8,
        con_9,
        con_10,
        con_11,
        con_12,
        con_13,
        con_14,
        con_15,
        con_16,
        con_17,
        con_18,
        con_19,
        con_20,
        con_21,
        con_22,
        con_23,
        con_24,
        con_25,
        con_26,
        con_27,
        con_28,
        con_29,
        con_30,
        con_31,
        con_32,
        con_33,
        con_34,
        con_f1_1,
        con_f1_2,
        con_f2_1,
        con_f2_2,
        con_f3_1,
        con_f3_2,
    ]

    return Problem(
        name="Spanish sustainability problem.",
        description="Defines a sustainability problem with three indicators: societal, economical, and environmental.",
        constants=constants,
        variables=variables,
        objectives=objectives,
        constraints=constraints,
    )

spanish_sustainability_problem_discrete

spanish_sustainability_problem_discrete()

Implements the Spanish sustainability problem using Pareto front representation.

Source code in desdeo/problem/testproblems.py
def spanish_sustainability_problem_discrete():
    """Implements the Spanish sustainability problem using Pareto front representation."""
    filename = "datasets/sustainability_spanish.csv"
    varnames = [f"x{i}" for i in range(1, 12)]
    objNames = {"f1": "social", "f2": "economic", "f3": "environmental"}

    path = Path(__file__).parent.parent.parent / filename
    data = pl.read_csv(path, has_header=True)

    data = data.rename({"social": "f1", "economic": "f2", "environmental": "f3"})

    variables = [
        Variable(
            name=varname,
            symbol=varname,
            variable_type=VariableTypeEnum.real,
            lowerbound=data[varname].min(),
            upperbound=data[varname].max(),
            initial_value=data[varname].mean(),
        )
        for varname in varnames
    ]

    objectives = [
        Objective(
            name=objNames[objname],
            symbol=objname,
            objective_type=ObjectiveTypeEnum.data_based,
            ideal=data[objname].max(),
            nadir=data[objname].min(),
            maximize=True,
        )
        for objname in objNames
    ]

    discrete_def = DiscreteRepresentation(
        variable_values=data[varnames].to_dict(),
        objective_values=data[[obj.symbol for obj in objectives]].to_dict(),
    )

    return Problem(
        name="Spanish sustainability problem (Discrete)",
        description="Defines a sustainability problem with three indicators: social, ecological, and environmental.",
        variables=variables,
        objectives=objectives,
        discrete_representation=discrete_def,
    )

zdt1

zdt1(number_of_variables: int) -> Problem

Defines the ZDT1 test problem.

The problem has a variable number of decision variables and two objective functions to be minimized as follows:

\[\begin{align*} \min\quad f_1(\textbf{x}) &= x_1 \\ \min\quad f_2(\textbf{x}) &= g(\textbf{x}) \cdot h(f_1(\textbf{x}), g(\textbf{x}))\\ g(\textbf{x}) &= 1 + \frac{9}{n-1} \sum_{i=2}^{n} x_i \\ h(f_1, g) &= 1 - \sqrt{\frac{f_1}{g}}, \\ \end{align*}\]

where \(f_1\) and \(f_2\) are objective functions, \(x_1,\dots,x_n\) are decision variable, \(n\) is the number of decision variables, and \(g\) and \(h\) are auxiliary functions.

Source code in desdeo/problem/testproblems.py
def zdt1(number_of_variables: int) -> Problem:
    r"""Defines the ZDT1 test problem.

    The problem has a variable number of decision variables and two objective functions to be minimized as
    follows:

    \begin{align*}
        \min\quad f_1(\textbf{x}) &= x_1 \\
        \min\quad f_2(\textbf{x}) &= g(\textbf{x}) \cdot h(f_1(\textbf{x}), g(\textbf{x}))\\
        g(\textbf{x}) &= 1 + \frac{9}{n-1} \sum_{i=2}^{n} x_i \\
        h(f_1, g) &= 1 - \sqrt{\frac{f_1}{g}}, \\
    \end{align*}

    where $f_1$ and $f_2$ are objective functions, $x_1,\dots,x_n$ are decision variable, $n$
    is the number of decision variables,
    and $g$ and $h$ are auxiliary functions.
    """
    n = number_of_variables

    # function f_1
    f1_symbol = "f_1"
    f1_expr = "x_1"

    # function g
    g_symbol = "g"
    g_expr_1 = f"1 + (9 / ({n} - 1))"
    g_expr_2 = "(" + " + ".join([f"x_{i}" for i in range(2, n + 1)]) + ")"
    g_expr = g_expr_1 + " * " + g_expr_2

    # function h(f, g)
    h_symbol = "h"
    h_expr = f"1 - Sqrt(({f1_expr}) / ({g_expr}))"

    # function f_2
    f2_symbol = "f_2"
    f2_expr = f"{g_symbol} * {h_symbol}"

    variables = [
        Variable(name=f"x_{i}", symbol=f"x_{i}", variable_type="real", lowerbound=0, upperbound=1, initial_value=0.5)
        for i in range(1, n + 1)
    ]

    objectives = [
        Objective(
            name="f_1",
            symbol=f1_symbol,
            func=f1_expr,
            maximize=False,
            ideal=0,
            nadir=1,
            is_convex=True,
            is_linear=True,
            is_twice_differentiable=True,
        ),
        Objective(
            name="f_2",
            symbol=f2_symbol,
            func=f2_expr,
            maximize=False,
            ideal=0,
            nadir=1,
            is_convex=True,
            is_linear=False,
            is_twice_differentiable=True,
        ),
    ]

    extras = [
        ExtraFunction(
            name="g", symbol=g_symbol, func=g_expr, is_convex=True, is_linear=True, is_twice_differentiable=True
        ),
        ExtraFunction(
            name="h", symbol=h_symbol, func=h_expr, is_convex=True, is_linear=False, is_twice_differentiable=True
        ),
    ]

    return Problem(
        name="zdt1",
        description="The ZDT1 test problem.",
        variables=variables,
        objectives=objectives,
        extra_funcs=extras,
        is_convex=True,
        is_linear=False,
        is_twice_differentiable=True,
    )

zdt2