desdeo 1.2__py3-none-any.whl → 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- desdeo/__init__.py +8 -8
- desdeo/adm/ADMAfsar.py +551 -0
- desdeo/adm/ADMChen.py +414 -0
- desdeo/adm/BaseADM.py +119 -0
- desdeo/adm/__init__.py +11 -0
- desdeo/api/README.md +73 -0
- desdeo/api/__init__.py +15 -0
- desdeo/api/app.py +50 -0
- desdeo/api/config.py +90 -0
- desdeo/api/config.toml +64 -0
- desdeo/api/db.py +27 -0
- desdeo/api/db_init.py +85 -0
- desdeo/api/db_models.py +164 -0
- desdeo/api/malaga_db_init.py +27 -0
- desdeo/api/models/__init__.py +266 -0
- desdeo/api/models/archive.py +23 -0
- desdeo/api/models/emo.py +128 -0
- desdeo/api/models/enautilus.py +69 -0
- desdeo/api/models/gdm/gdm_aggregate.py +139 -0
- desdeo/api/models/gdm/gdm_base.py +69 -0
- desdeo/api/models/gdm/gdm_score_bands.py +114 -0
- desdeo/api/models/gdm/gnimbus.py +138 -0
- desdeo/api/models/generic.py +104 -0
- desdeo/api/models/generic_states.py +401 -0
- desdeo/api/models/nimbus.py +158 -0
- desdeo/api/models/preference.py +128 -0
- desdeo/api/models/problem.py +717 -0
- desdeo/api/models/reference_point_method.py +18 -0
- desdeo/api/models/session.py +49 -0
- desdeo/api/models/state.py +463 -0
- desdeo/api/models/user.py +52 -0
- desdeo/api/models/utopia.py +25 -0
- desdeo/api/routers/_EMO.backup +309 -0
- desdeo/api/routers/_NAUTILUS.py +245 -0
- desdeo/api/routers/_NAUTILUS_navigator.py +233 -0
- desdeo/api/routers/_NIMBUS.py +765 -0
- desdeo/api/routers/__init__.py +5 -0
- desdeo/api/routers/emo.py +497 -0
- desdeo/api/routers/enautilus.py +237 -0
- desdeo/api/routers/gdm/gdm_aggregate.py +234 -0
- desdeo/api/routers/gdm/gdm_base.py +420 -0
- desdeo/api/routers/gdm/gdm_score_bands/gdm_score_bands_manager.py +398 -0
- desdeo/api/routers/gdm/gdm_score_bands/gdm_score_bands_routers.py +377 -0
- desdeo/api/routers/gdm/gnimbus/gnimbus_manager.py +698 -0
- desdeo/api/routers/gdm/gnimbus/gnimbus_routers.py +591 -0
- desdeo/api/routers/generic.py +233 -0
- desdeo/api/routers/nimbus.py +705 -0
- desdeo/api/routers/problem.py +307 -0
- desdeo/api/routers/reference_point_method.py +93 -0
- desdeo/api/routers/session.py +100 -0
- desdeo/api/routers/test.py +16 -0
- desdeo/api/routers/user_authentication.py +520 -0
- desdeo/api/routers/utils.py +187 -0
- desdeo/api/routers/utopia.py +230 -0
- desdeo/api/schema.py +100 -0
- desdeo/api/tests/__init__.py +0 -0
- desdeo/api/tests/conftest.py +151 -0
- desdeo/api/tests/test_enautilus.py +330 -0
- desdeo/api/tests/test_models.py +1179 -0
- desdeo/api/tests/test_routes.py +1075 -0
- desdeo/api/utils/_database.py +263 -0
- desdeo/api/utils/_logger.py +29 -0
- desdeo/api/utils/database.py +36 -0
- desdeo/api/utils/emo_database.py +40 -0
- desdeo/core.py +34 -0
- desdeo/emo/__init__.py +159 -0
- desdeo/emo/hooks/archivers.py +188 -0
- desdeo/emo/methods/EAs.py +541 -0
- desdeo/emo/methods/__init__.py +0 -0
- desdeo/emo/methods/bases.py +12 -0
- desdeo/emo/methods/templates.py +111 -0
- desdeo/emo/operators/__init__.py +1 -0
- desdeo/emo/operators/crossover.py +1282 -0
- desdeo/emo/operators/evaluator.py +114 -0
- desdeo/emo/operators/generator.py +459 -0
- desdeo/emo/operators/mutation.py +1224 -0
- desdeo/emo/operators/scalar_selection.py +202 -0
- desdeo/emo/operators/selection.py +1778 -0
- desdeo/emo/operators/termination.py +286 -0
- desdeo/emo/options/__init__.py +108 -0
- desdeo/emo/options/algorithms.py +435 -0
- desdeo/emo/options/crossover.py +164 -0
- desdeo/emo/options/generator.py +131 -0
- desdeo/emo/options/mutation.py +260 -0
- desdeo/emo/options/repair.py +61 -0
- desdeo/emo/options/scalar_selection.py +66 -0
- desdeo/emo/options/selection.py +127 -0
- desdeo/emo/options/templates.py +383 -0
- desdeo/emo/options/termination.py +143 -0
- desdeo/explanations/__init__.py +6 -0
- desdeo/explanations/explainer.py +100 -0
- desdeo/explanations/utils.py +90 -0
- desdeo/gdm/__init__.py +22 -0
- desdeo/gdm/gdmtools.py +45 -0
- desdeo/gdm/score_bands.py +114 -0
- desdeo/gdm/voting_rules.py +50 -0
- desdeo/mcdm/__init__.py +41 -0
- desdeo/mcdm/enautilus.py +338 -0
- desdeo/mcdm/gnimbus.py +484 -0
- desdeo/mcdm/nautili.py +345 -0
- desdeo/mcdm/nautilus.py +477 -0
- desdeo/mcdm/nautilus_navigator.py +656 -0
- desdeo/mcdm/nimbus.py +417 -0
- desdeo/mcdm/pareto_navigator.py +269 -0
- desdeo/mcdm/reference_point_method.py +186 -0
- desdeo/problem/__init__.py +83 -0
- desdeo/problem/evaluator.py +561 -0
- desdeo/problem/external/__init__.py +18 -0
- desdeo/problem/external/core.py +356 -0
- desdeo/problem/external/pymoo_provider.py +266 -0
- desdeo/problem/external/runtime.py +44 -0
- desdeo/problem/gurobipy_evaluator.py +562 -0
- desdeo/problem/infix_parser.py +341 -0
- desdeo/problem/json_parser.py +944 -0
- desdeo/problem/pyomo_evaluator.py +487 -0
- desdeo/problem/schema.py +1829 -0
- desdeo/problem/simulator_evaluator.py +348 -0
- desdeo/problem/sympy_evaluator.py +244 -0
- desdeo/problem/testproblems/__init__.py +88 -0
- desdeo/problem/testproblems/benchmarks_server.py +120 -0
- desdeo/problem/testproblems/binh_and_korn_problem.py +88 -0
- desdeo/problem/testproblems/cake_problem.py +185 -0
- desdeo/problem/testproblems/dmitry_forest_problem_discrete.py +71 -0
- desdeo/problem/testproblems/dtlz2_problem.py +102 -0
- desdeo/problem/testproblems/forest_problem.py +283 -0
- desdeo/problem/testproblems/knapsack_problem.py +163 -0
- desdeo/problem/testproblems/mcwb_problem.py +831 -0
- desdeo/problem/testproblems/mixed_variable_dimenrions_problem.py +83 -0
- desdeo/problem/testproblems/momip_problem.py +172 -0
- desdeo/problem/testproblems/multi_valued_constraints.py +119 -0
- desdeo/problem/testproblems/nimbus_problem.py +143 -0
- desdeo/problem/testproblems/pareto_navigator_problem.py +89 -0
- desdeo/problem/testproblems/re_problem.py +492 -0
- desdeo/problem/testproblems/river_pollution_problems.py +440 -0
- desdeo/problem/testproblems/rocket_injector_design_problem.py +140 -0
- desdeo/problem/testproblems/simple_problem.py +351 -0
- desdeo/problem/testproblems/simulator_problem.py +92 -0
- desdeo/problem/testproblems/single_objective.py +289 -0
- desdeo/problem/testproblems/spanish_sustainability_problem.py +945 -0
- desdeo/problem/testproblems/zdt_problem.py +274 -0
- desdeo/problem/utils.py +245 -0
- desdeo/tools/GenerateReferencePoints.py +181 -0
- desdeo/tools/__init__.py +120 -0
- desdeo/tools/desc_gen.py +22 -0
- desdeo/tools/generics.py +165 -0
- desdeo/tools/group_scalarization.py +3090 -0
- desdeo/tools/gurobipy_solver_interfaces.py +258 -0
- desdeo/tools/indicators_binary.py +117 -0
- desdeo/tools/indicators_unary.py +362 -0
- desdeo/tools/interaction_schema.py +38 -0
- desdeo/tools/intersection.py +54 -0
- desdeo/tools/iterative_pareto_representer.py +99 -0
- desdeo/tools/message.py +265 -0
- desdeo/tools/ng_solver_interfaces.py +199 -0
- desdeo/tools/non_dominated_sorting.py +134 -0
- desdeo/tools/patterns.py +283 -0
- desdeo/tools/proximal_solver.py +99 -0
- desdeo/tools/pyomo_solver_interfaces.py +477 -0
- desdeo/tools/reference_vectors.py +229 -0
- desdeo/tools/scalarization.py +2065 -0
- desdeo/tools/scipy_solver_interfaces.py +454 -0
- desdeo/tools/score_bands.py +627 -0
- desdeo/tools/utils.py +388 -0
- desdeo/tools/visualizations.py +67 -0
- desdeo/utopia_stuff/__init__.py +0 -0
- desdeo/utopia_stuff/data/1.json +15 -0
- desdeo/utopia_stuff/data/2.json +13 -0
- desdeo/utopia_stuff/data/3.json +15 -0
- desdeo/utopia_stuff/data/4.json +17 -0
- desdeo/utopia_stuff/data/5.json +15 -0
- desdeo/utopia_stuff/from_json.py +40 -0
- desdeo/utopia_stuff/reinit_user.py +38 -0
- desdeo/utopia_stuff/utopia_db_init.py +212 -0
- desdeo/utopia_stuff/utopia_problem.py +403 -0
- desdeo/utopia_stuff/utopia_problem_old.py +415 -0
- desdeo/utopia_stuff/utopia_reference_solutions.py +79 -0
- desdeo-2.1.0.dist-info/METADATA +186 -0
- desdeo-2.1.0.dist-info/RECORD +180 -0
- {desdeo-1.2.dist-info → desdeo-2.1.0.dist-info}/WHEEL +1 -1
- desdeo-2.1.0.dist-info/licenses/LICENSE +21 -0
- desdeo-1.2.dist-info/METADATA +0 -16
- desdeo-1.2.dist-info/RECORD +0 -4
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# A FastAPI server to expose pymoo benchmark problems
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import polars as pl
|
|
5
|
+
import requests
|
|
6
|
+
from fastapi import FastAPI
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
from pymoo.problems import get_problem
|
|
9
|
+
|
|
10
|
+
from desdeo.problem.schema import Objective, Problem, Simulator, Url, Variable
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PymooParameters(BaseModel):
|
|
14
|
+
"""Parameters for a pymoo problem instance."""
|
|
15
|
+
|
|
16
|
+
name: str
|
|
17
|
+
n_var: int
|
|
18
|
+
n_obj: int
|
|
19
|
+
minus: bool = False
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ProblemInfo(BaseModel):
|
|
23
|
+
"""Information about a pymoo problem instance."""
|
|
24
|
+
|
|
25
|
+
lower_bounds: dict[str, float]
|
|
26
|
+
"""Lower bounds of the decision variables. Keys are the names of the decision variables, e.g. "x_1", "x_2", etc."""
|
|
27
|
+
upper_bounds: dict[str, float]
|
|
28
|
+
"""Upper bounds of the decision variables."""
|
|
29
|
+
objective_names: list[str]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
app = FastAPI()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_pymoo_problem(p: PymooParameters):
|
|
36
|
+
"""Get a pymoo problem instance by name, number of variables, and number of objectives."""
|
|
37
|
+
params = p.model_dump()
|
|
38
|
+
params.pop("minus")
|
|
39
|
+
return get_problem(**params)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@app.get("/evaluate")
|
|
43
|
+
def evaluate(d: dict[str, list[float]], p: PymooParameters) -> dict[str, Any]:
|
|
44
|
+
"""Evaluate a pymoo problem instance with given parameters and input values."""
|
|
45
|
+
problem = get_pymoo_problem(p)
|
|
46
|
+
|
|
47
|
+
xs_df = pl.DataFrame(d)
|
|
48
|
+
|
|
49
|
+
output = problem.evaluate(xs_df.to_numpy())
|
|
50
|
+
output_df = pl.DataFrame(output, schema=[f"f_{i + 1}" for i in range(problem.n_obj)])
|
|
51
|
+
|
|
52
|
+
return d | output_df.to_dict(as_series=False)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@app.get("/info")
|
|
56
|
+
def info(p: PymooParameters) -> ProblemInfo:
|
|
57
|
+
"""Get information about a pymoo problem instance, including bounds and objective names."""
|
|
58
|
+
problem = get_pymoo_problem(p)
|
|
59
|
+
bounds = problem.bounds()
|
|
60
|
+
|
|
61
|
+
return ProblemInfo(
|
|
62
|
+
lower_bounds={f"x_{i + 1}": bounds[0][i] for i in range(problem.n_var)},
|
|
63
|
+
upper_bounds={f"x_{i + 1}": bounds[1][i] for i in range(problem.n_var)},
|
|
64
|
+
objective_names=[f"f_{i + 1}" for i in range(problem.n_obj)],
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
url = "http://127.0.0.1"
|
|
69
|
+
port = 8000
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def server_problem(parameters: PymooParameters) -> Problem:
|
|
73
|
+
"""Create a Problem instance from pymoo parameters."""
|
|
74
|
+
try:
|
|
75
|
+
info = requests.get(url + f":{port}/info", json=parameters.model_dump())
|
|
76
|
+
info.raise_for_status()
|
|
77
|
+
except requests.RequestException as e:
|
|
78
|
+
raise RuntimeError("Failed to fetch problem info. Is the server running?") from e
|
|
79
|
+
info: ProblemInfo = ProblemInfo.model_validate(info.json())
|
|
80
|
+
|
|
81
|
+
simulator_url = Url(url=f"{url}:{port}/evaluate")
|
|
82
|
+
|
|
83
|
+
return Problem(
|
|
84
|
+
name=parameters.name,
|
|
85
|
+
description=f"Problem {parameters.name} with {parameters.n_var} variables and {parameters.n_obj} objectives.",
|
|
86
|
+
variables=[
|
|
87
|
+
Variable(
|
|
88
|
+
name=f"x_{i + 1}",
|
|
89
|
+
symbol=f"x_{i + 1}",
|
|
90
|
+
lowerbound=info.lower_bounds[f"x_{i + 1}"],
|
|
91
|
+
upperbound=info.upper_bounds[f"x_{i + 1}"],
|
|
92
|
+
variable_type="real",
|
|
93
|
+
)
|
|
94
|
+
for i in range(parameters.n_var)
|
|
95
|
+
],
|
|
96
|
+
objectives=[
|
|
97
|
+
Objective(
|
|
98
|
+
name=f"f_{i + 1}",
|
|
99
|
+
symbol=f"f_{i + 1}",
|
|
100
|
+
simulator_path=simulator_url,
|
|
101
|
+
objective_type="simulator",
|
|
102
|
+
maximize=parameters.minus,
|
|
103
|
+
)
|
|
104
|
+
for i in range(parameters.n_obj)
|
|
105
|
+
],
|
|
106
|
+
simulators=[
|
|
107
|
+
Simulator(
|
|
108
|
+
name="s1",
|
|
109
|
+
symbol="s1",
|
|
110
|
+
url=simulator_url,
|
|
111
|
+
parameter_options=parameters.model_dump(),
|
|
112
|
+
)
|
|
113
|
+
],
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == "__main__":
|
|
118
|
+
import uvicorn
|
|
119
|
+
|
|
120
|
+
uvicorn.run(app)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from desdeo.problem.schema import (
|
|
2
|
+
Constant,
|
|
3
|
+
Constraint,
|
|
4
|
+
Objective,
|
|
5
|
+
Problem,
|
|
6
|
+
Variable,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
def binh_and_korn(maximize: tuple[bool] = (False, False)) -> Problem:
|
|
10
|
+
"""Create a pydantic dataclass representation of the Binh and Korn problem.
|
|
11
|
+
|
|
12
|
+
The function has two objective functions, two variables, and two constraint functions.
|
|
13
|
+
For testing purposes, it can be chosen whether the firs and second objective should
|
|
14
|
+
be maximized instead.
|
|
15
|
+
|
|
16
|
+
Arguments:
|
|
17
|
+
maximize (tuple[bool]): whether the first or second objective should be
|
|
18
|
+
maximized or not. Defaults to (False, False).
|
|
19
|
+
|
|
20
|
+
References:
|
|
21
|
+
Binh T. and Korn U. (1997) MOBES: A Multiobjective Evolution Strategy for Constrained Optimization Problems.
|
|
22
|
+
In: Proceedings of the Third International Conference on Genetic Algorithms. Czech Republic. pp. 176-182.
|
|
23
|
+
"""
|
|
24
|
+
# These constants are for demonstrative purposes.
|
|
25
|
+
constant_1 = Constant(name="Four", symbol="c_1", value=4)
|
|
26
|
+
constant_2 = Constant(name="Five", symbol="c_2", value=5)
|
|
27
|
+
|
|
28
|
+
variable_1 = Variable(
|
|
29
|
+
name="The first variable", symbol="x_1", variable_type="real", lowerbound=0, upperbound=5, initial_value=2.5
|
|
30
|
+
)
|
|
31
|
+
variable_2 = Variable(
|
|
32
|
+
name="The second variable", symbol="x_2", variable_type="real", lowerbound=0, upperbound=3, initial_value=1.5
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
objective_1 = Objective(
|
|
36
|
+
name="Objective 1",
|
|
37
|
+
symbol="f_1",
|
|
38
|
+
func=f"{'-' if maximize[0] else ''}(c_1 * x_1**2 + c_1*x_2**2)",
|
|
39
|
+
# func=["Add", ["Multiply", "c_1", ["Square", "x_1"]], ["Multiply", "c_1", ["Square", "x_2"]]],
|
|
40
|
+
maximize=maximize[0],
|
|
41
|
+
ideal=0,
|
|
42
|
+
nadir=140 if not maximize[0] else -140,
|
|
43
|
+
is_linear=False,
|
|
44
|
+
is_convex=True,
|
|
45
|
+
is_twice_differentiable=True,
|
|
46
|
+
)
|
|
47
|
+
objective_2 = Objective(
|
|
48
|
+
name="Objective 2",
|
|
49
|
+
symbol="f_2",
|
|
50
|
+
# func=["Add", ["Square", ["Subtract", "x_1", "c_2"]], ["Square", ["Subtract", "x_2", "c_2"]]],
|
|
51
|
+
func=f"{'-' if maximize[1] else ''}((x_1 - c_2)**2 + (x_2 - c_2)**2)",
|
|
52
|
+
maximize=maximize[1],
|
|
53
|
+
ideal=0,
|
|
54
|
+
nadir=50 if not maximize[0] else -50,
|
|
55
|
+
is_linear=False,
|
|
56
|
+
is_convex=True,
|
|
57
|
+
is_twice_differentiable=True,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
constraint_1 = Constraint(
|
|
61
|
+
name="Constraint 1",
|
|
62
|
+
symbol="g_1",
|
|
63
|
+
cons_type="<=",
|
|
64
|
+
func=["Add", ["Square", ["Subtract", "x_1", "c_2"]], ["Square", "x_2"], -25],
|
|
65
|
+
is_linear=False,
|
|
66
|
+
is_convex=True,
|
|
67
|
+
is_twice_differentiable=True,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
constraint_2 = Constraint(
|
|
71
|
+
name="Constraint 2",
|
|
72
|
+
symbol="g_2",
|
|
73
|
+
cons_type="<=",
|
|
74
|
+
func=["Add", ["Negate", ["Square", ["Subtract", "x_1", 8]]], ["Negate", ["Square", ["Add", "x_2", 3]]], 7.7],
|
|
75
|
+
is_linear=False,
|
|
76
|
+
is_convex=True,
|
|
77
|
+
is_twice_differentiable=True,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
return Problem(
|
|
81
|
+
name="The Binh and Korn function",
|
|
82
|
+
description="The two-objective problem used in the paper by Binh and Korn.",
|
|
83
|
+
constants=[constant_1, constant_2],
|
|
84
|
+
variables=[variable_1, variable_2],
|
|
85
|
+
objectives=[objective_1, objective_2],
|
|
86
|
+
constraints=[constraint_1, constraint_2],
|
|
87
|
+
is_twice_differentiable=True,
|
|
88
|
+
)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""Defines the 'best cake problem'."""
|
|
2
|
+
|
|
3
|
+
from desdeo.problem.schema import (
|
|
4
|
+
Constant,
|
|
5
|
+
Objective,
|
|
6
|
+
ObjectiveTypeEnum,
|
|
7
|
+
Problem,
|
|
8
|
+
Variable,
|
|
9
|
+
VariableTypeEnum,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
PI = 3.14159265358979323846
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Helper func
|
|
16
|
+
def U(z: float):
|
|
17
|
+
return 4.0 * z * (1.0 - z)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## Helper funcs to return string representations
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def bowl_str(z: str, a: str, invD: str) -> str:
|
|
24
|
+
tmp: str = f"({z} - {a})*{invD}"
|
|
25
|
+
return f"({tmp}*{tmp})"
|
|
26
|
+
# return f"{clamp01_str(f"{tmp}*{tmp}")}"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def U_str(z: str) -> str:
|
|
30
|
+
tmp: str = f"(4*{z}*(1.0 - {z}))"
|
|
31
|
+
return f"({tmp}*{tmp})"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def ripple_str(t: str) -> str:
|
|
35
|
+
tmp: str = f"Sin({PI} * {t})"
|
|
36
|
+
return f"({tmp}*{tmp})"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Objective function string representations
|
|
40
|
+
def f0_str() -> str:
|
|
41
|
+
yliq: str = "(0.5*x5 + 0.3*x4 + 0.2*x3)"
|
|
42
|
+
v: str = (
|
|
43
|
+
f"(0.4 * {bowl_str('x1', 'T1', 'INV_D1')}) + "
|
|
44
|
+
f"(0.4 * {bowl_str(yliq, 'Y_LIQ_STAR', 'INV_D_YLIQ')}) + "
|
|
45
|
+
f" (0.2 * {ripple_str('((x1 + x6) - (T1 + T6))')})"
|
|
46
|
+
)
|
|
47
|
+
return f"14*({v})"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def f1_str() -> str:
|
|
51
|
+
sbar: str = "((x2 + 0.5*x3)/1.5)"
|
|
52
|
+
w25: str = f"({U_str('x2')}*{U_str('x5')})"
|
|
53
|
+
d25: str = f"(({w25} - W25_STAR)*INV_DW25)"
|
|
54
|
+
v: str = f"(0.4*{bowl_str('x2', 'T2', 'INV_D2')}) + (0.3*{ripple_str(f'{sbar} - SBAR_STAR')}) +(0.3*{d25}*{d25})"
|
|
55
|
+
return f"14*({v})"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def f2_str() -> str:
|
|
59
|
+
v: str = (
|
|
60
|
+
f"(0.35*{bowl_str('x6', 'T6', 'INV_D6')}) + "
|
|
61
|
+
f"(0.25*{bowl_str('x4', 'T4', 'INV_D4')}) + "
|
|
62
|
+
f"(0.4*{ripple_str('((x6 - 0.5*x4) - (T6 - 0.5*T4))')})"
|
|
63
|
+
)
|
|
64
|
+
return f"14*({v})"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def f3_str() -> str:
|
|
68
|
+
w35: str = f"({U_str('x3')}*{U_str('x5')})"
|
|
69
|
+
d35: str = f"(({w35} - W35_STAR) * INV_DW35)"
|
|
70
|
+
v: str = f"(0.3*{bowl_str('x3', 'T3', 'INV_D3')}) + (0.3*{bowl_str('x5', 'T5', 'INV_D5')}) + (0.4*({d35}*{d35}))"
|
|
71
|
+
return f"14*({v})"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def f4_str() -> str:
|
|
75
|
+
v: str = (
|
|
76
|
+
f"(0.25*{bowl_str('x2', 'T2', 'INV_D2')}) + "
|
|
77
|
+
f"(0.25*{bowl_str('x3', 'T3', 'INV_D3')}) + "
|
|
78
|
+
f"(0.20*{ripple_str('(x4 - T4)')}) + "
|
|
79
|
+
f"(0.30*{ripple_str('((x2 - x5) - (T2 - T5))')})"
|
|
80
|
+
)
|
|
81
|
+
return f"14*({v})"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
## The cake problem
|
|
85
|
+
def best_cake_problem() -> Problem:
|
|
86
|
+
"""Defines the best cake problem."""
|
|
87
|
+
variable_inits = [
|
|
88
|
+
("Flour", 0.70),
|
|
89
|
+
("Sugar", 0.10),
|
|
90
|
+
("Butter", 0.40),
|
|
91
|
+
("Eggs", 0.50),
|
|
92
|
+
("Milk", 0.20),
|
|
93
|
+
("Baking powder", 0.80),
|
|
94
|
+
]
|
|
95
|
+
variables = [
|
|
96
|
+
Variable(
|
|
97
|
+
name=var[0],
|
|
98
|
+
symbol=f"x{i + 1}",
|
|
99
|
+
variable_type=VariableTypeEnum.real,
|
|
100
|
+
lowerbound=0.0,
|
|
101
|
+
upperbound=1.0,
|
|
102
|
+
initial_value=var[1],
|
|
103
|
+
)
|
|
104
|
+
for i, var in enumerate(variable_inits)
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
constants_init = [
|
|
108
|
+
("T1", 0.60),
|
|
109
|
+
("T2", 0.35),
|
|
110
|
+
("T3", 0.25),
|
|
111
|
+
("T4", 0.30),
|
|
112
|
+
("T5", 0.35),
|
|
113
|
+
("T6", 0.40),
|
|
114
|
+
("INV_D1", 1.0 / 0.60),
|
|
115
|
+
("INV_D2", 1.0 / 0.65),
|
|
116
|
+
("INV_D3", 1.0 / 0.75),
|
|
117
|
+
("INV_D4", 1.0 / 0.70),
|
|
118
|
+
("INV_D5", 1.0 / 0.65),
|
|
119
|
+
("INV_D6", 1.0 / 0.60),
|
|
120
|
+
("Y_LIQ_STAR", 0.5 * 0.35 + 0.3 * 0.30 + 0.2 * 0.25),
|
|
121
|
+
("INV_D_YLIQ", 1.0 / 0.685),
|
|
122
|
+
("SBAR_STAR", (0.35 + 0.5 * 0.25) / 1.5),
|
|
123
|
+
("W25_STAR", U(0.35) * U(0.35)),
|
|
124
|
+
("INV_DW25", 1.0 / 0.8281),
|
|
125
|
+
("W35_STAR", U(0.25) * U(0.35)),
|
|
126
|
+
("INV_DW35", 1.0 / 0.6825),
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
constants = [Constant(name=const[0], symbol=const[0], value=const[1]) for const in constants_init]
|
|
130
|
+
|
|
131
|
+
objectives = [
|
|
132
|
+
Objective(
|
|
133
|
+
name="Dry/crumb error",
|
|
134
|
+
symbol="dry_crumb",
|
|
135
|
+
func=f0_str(),
|
|
136
|
+
ideal=0.0,
|
|
137
|
+
nadir=14.0,
|
|
138
|
+
objective_type=ObjectiveTypeEnum.analytical,
|
|
139
|
+
is_twice_differentiable=True, # right?
|
|
140
|
+
),
|
|
141
|
+
Objective(
|
|
142
|
+
name="Sweetness/texture off-target",
|
|
143
|
+
symbol="sweet_texture",
|
|
144
|
+
func=f1_str(),
|
|
145
|
+
ideal=0.0,
|
|
146
|
+
nadir=14.0,
|
|
147
|
+
objective_type=ObjectiveTypeEnum.analytical,
|
|
148
|
+
is_twice_differentiable=True,
|
|
149
|
+
),
|
|
150
|
+
Objective(
|
|
151
|
+
name="Rise/collapse risk",
|
|
152
|
+
symbol="rise_collapse",
|
|
153
|
+
func=f2_str(),
|
|
154
|
+
ideal=0.0,
|
|
155
|
+
nadir=14.0,
|
|
156
|
+
objective_type=ObjectiveTypeEnum.analytical,
|
|
157
|
+
is_twice_differentiable=True,
|
|
158
|
+
),
|
|
159
|
+
Objective(
|
|
160
|
+
name="Moistness/grease imbalance",
|
|
161
|
+
symbol="moistness_grease",
|
|
162
|
+
func=f3_str(),
|
|
163
|
+
ideal=0.0,
|
|
164
|
+
nadir=14.0,
|
|
165
|
+
objective_type=ObjectiveTypeEnum.analytical,
|
|
166
|
+
is_twice_differentiable=True,
|
|
167
|
+
),
|
|
168
|
+
Objective(
|
|
169
|
+
name="Browning/burn risk",
|
|
170
|
+
symbol="browning_burn",
|
|
171
|
+
func=f4_str(),
|
|
172
|
+
ideal=0.0,
|
|
173
|
+
nadir=14.0,
|
|
174
|
+
objective_type=ObjectiveTypeEnum.analytical,
|
|
175
|
+
is_twice_differentiable=True,
|
|
176
|
+
),
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
return Problem(
|
|
180
|
+
name="Cake problem",
|
|
181
|
+
description="Try to find the most delicious cake!",
|
|
182
|
+
constants=constants,
|
|
183
|
+
variables=variables,
|
|
184
|
+
objectives=objectives,
|
|
185
|
+
)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""A forest problem with discrete representation."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import polars as pl
|
|
5
|
+
|
|
6
|
+
from desdeo.problem.schema import (
|
|
7
|
+
DiscreteRepresentation,
|
|
8
|
+
Objective,
|
|
9
|
+
ObjectiveTypeEnum,
|
|
10
|
+
Problem,
|
|
11
|
+
Variable,
|
|
12
|
+
VariableTypeEnum,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def dmitry_forest_problem_disc() -> Problem:
|
|
17
|
+
"""Implements the dmitry forest problem using Pareto front representation.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Problem: A problem instance representing the forest problem.
|
|
21
|
+
"""
|
|
22
|
+
path = Path(__file__)
|
|
23
|
+
while not str(path).endswith("/DESDEO"):
|
|
24
|
+
path = path.parent
|
|
25
|
+
|
|
26
|
+
path = path / "tests/data/dmitry_discrete_repr/dmitry_forest_problem_non_dom_solns.csv"
|
|
27
|
+
|
|
28
|
+
obj_names = ["Rev", "HA", "Carb", "DW"]
|
|
29
|
+
|
|
30
|
+
var_name = "index"
|
|
31
|
+
|
|
32
|
+
data = pl.read_csv(
|
|
33
|
+
path, has_header=True, columns=["Rev", "HA", "Carb", "DW"], separator=",", #decimal_comma=True
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
variables = [
|
|
37
|
+
Variable(
|
|
38
|
+
name=var_name,
|
|
39
|
+
symbol=var_name,
|
|
40
|
+
variable_type=VariableTypeEnum.integer,
|
|
41
|
+
lowerbound=0,
|
|
42
|
+
upperbound=len(data) - 1,
|
|
43
|
+
initial_value=0,
|
|
44
|
+
)
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
objectives = [
|
|
48
|
+
Objective(
|
|
49
|
+
name=obj_name,
|
|
50
|
+
symbol=obj_name,
|
|
51
|
+
objective_type=ObjectiveTypeEnum.data_based,
|
|
52
|
+
ideal=data[obj_name].max(),
|
|
53
|
+
nadir=data[obj_name].min(),
|
|
54
|
+
maximize=True,
|
|
55
|
+
)
|
|
56
|
+
for obj_name in obj_names
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
discrete_def = DiscreteRepresentation(
|
|
60
|
+
variable_values={"index": list(range(len(data)))},
|
|
61
|
+
objective_values=data[[obj.symbol for obj in objectives]].to_dict(),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return Problem(
|
|
65
|
+
name="Dmitry Forest Problem (Discrete)",
|
|
66
|
+
description="Defines a forest problem with four objectives: revenue, habitat availability, carbon storage, and deadwood.",
|
|
67
|
+
variables=variables,
|
|
68
|
+
objectives=objectives,
|
|
69
|
+
discrete_representation=discrete_def,
|
|
70
|
+
is_twice_differentiable=False,
|
|
71
|
+
)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from desdeo.problem.schema import (
|
|
4
|
+
ExtraFunction,
|
|
5
|
+
Objective,
|
|
6
|
+
Problem,
|
|
7
|
+
Variable,
|
|
8
|
+
VariableTypeEnum,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
def dtlz2(n_variables: int, n_objectives: int) -> Problem:
|
|
12
|
+
r"""Defines the DTLZ2 test problem.
|
|
13
|
+
|
|
14
|
+
The objective functions for DTLZ2 are defined as follows, for $i = 1$ to $M$:
|
|
15
|
+
|
|
16
|
+
\begin{equation}
|
|
17
|
+
\underset{\mathbf{x}}{\operatorname{min}}
|
|
18
|
+
f_i(\mathbf{x}) = (1+g(\mathbf{x}_M)) \prod_{j=1}^{M-i} \cos\left(x_j \frac{\pi}{2}\right) \times
|
|
19
|
+
\begin{cases}
|
|
20
|
+
1 & \text{if } i=1 \\
|
|
21
|
+
\sin\left(x_{(M-i+1)}\frac{\pi}{2}\right) & \text{otherwise},
|
|
22
|
+
\end{cases}
|
|
23
|
+
\end{equation}
|
|
24
|
+
|
|
25
|
+
where
|
|
26
|
+
|
|
27
|
+
\begin{equation}
|
|
28
|
+
g(\mathbf{x}_M) = \sum_{x_i \in \mathbf{x}_M} \left( x_i - 0.5 \right)^2,
|
|
29
|
+
\end{equation}
|
|
30
|
+
|
|
31
|
+
and $\mathbf{x}_M$ represents the last $n-k$ dimensions of the decision vector.
|
|
32
|
+
Pareto optimal solutions to the DTLZ2 problem consist of $x_i = 0.5$ for
|
|
33
|
+
all $x_i \in\mathbf{x}_{M}$, and $\sum{i=1}^{M} f_i^2 = 1$.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
n_variables (int): number of variables.
|
|
37
|
+
n_objectives (int): number of objective functions.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Problem: an instance of the DTLZ2 problem with `n_variables` variables and `n_objectives` objective
|
|
41
|
+
functions.
|
|
42
|
+
|
|
43
|
+
References:
|
|
44
|
+
Deb, K., Thiele, L., Laumanns, M., Zitzler, E. (2005). Scalable Test
|
|
45
|
+
Problems for Evolutionary Multiobjective Optimization. In: Abraham, A.,
|
|
46
|
+
Jain, L., Goldberg, R. (eds) Evolutionary Multiobjective Optimization.
|
|
47
|
+
Advanced Information and Knowledge Processing. Springer.
|
|
48
|
+
"""
|
|
49
|
+
# function g
|
|
50
|
+
g_symbol = "g"
|
|
51
|
+
g_expr = " + ".join([f"(x_{i} - 0.5)**2" for i in range(n_objectives, n_variables + 1)])
|
|
52
|
+
g_expr = "1 + " + g_expr
|
|
53
|
+
|
|
54
|
+
objectives = []
|
|
55
|
+
for m in range(1, n_objectives + 1):
|
|
56
|
+
# function f_m
|
|
57
|
+
prod_expr = " * ".join([f"Cos(0.5 * {np.pi} * x_{i})" for i in range(1, n_objectives - m + 1)])
|
|
58
|
+
if m > 1:
|
|
59
|
+
prod_expr += f"{' * ' if prod_expr != "" else ""}Sin(0.5 * {np.pi} * x_{n_objectives - m + 1})"
|
|
60
|
+
if prod_expr == "":
|
|
61
|
+
prod_expr = "1" # When m == n_objectives, the product is empty, implying f_M = g.
|
|
62
|
+
f_m_expr = f"({g_symbol}) * ({prod_expr})"
|
|
63
|
+
|
|
64
|
+
objectives.append(
|
|
65
|
+
Objective(
|
|
66
|
+
name=f"f_{m}",
|
|
67
|
+
symbol=f"f_{m}",
|
|
68
|
+
func=f_m_expr,
|
|
69
|
+
maximize=False,
|
|
70
|
+
ideal=0,
|
|
71
|
+
nadir=1, # Assuming the range of g and the trigonometric functions
|
|
72
|
+
is_convex=False,
|
|
73
|
+
is_linear=False,
|
|
74
|
+
is_twice_differentiable=True,
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
variables = [
|
|
79
|
+
Variable(
|
|
80
|
+
name=f"x_{i}",
|
|
81
|
+
symbol=f"x_{i}",
|
|
82
|
+
variable_type=VariableTypeEnum.real,
|
|
83
|
+
lowerbound=0,
|
|
84
|
+
upperbound=1,
|
|
85
|
+
initial_value=1.0,
|
|
86
|
+
)
|
|
87
|
+
for i in range(1, n_variables + 1)
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
extras = [
|
|
91
|
+
ExtraFunction(
|
|
92
|
+
name="g", symbol=g_symbol, func=g_expr, is_convex=False, is_linear=False, is_twice_differentiable=True
|
|
93
|
+
),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
return Problem(
|
|
97
|
+
name="dtlz2",
|
|
98
|
+
description="The DTLZ2 test problem.",
|
|
99
|
+
variables=variables,
|
|
100
|
+
objectives=objectives,
|
|
101
|
+
extra_funcs=extras,
|
|
102
|
+
)
|