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.
Files changed (182) hide show
  1. desdeo/__init__.py +8 -8
  2. desdeo/adm/ADMAfsar.py +551 -0
  3. desdeo/adm/ADMChen.py +414 -0
  4. desdeo/adm/BaseADM.py +119 -0
  5. desdeo/adm/__init__.py +11 -0
  6. desdeo/api/README.md +73 -0
  7. desdeo/api/__init__.py +15 -0
  8. desdeo/api/app.py +50 -0
  9. desdeo/api/config.py +90 -0
  10. desdeo/api/config.toml +64 -0
  11. desdeo/api/db.py +27 -0
  12. desdeo/api/db_init.py +85 -0
  13. desdeo/api/db_models.py +164 -0
  14. desdeo/api/malaga_db_init.py +27 -0
  15. desdeo/api/models/__init__.py +266 -0
  16. desdeo/api/models/archive.py +23 -0
  17. desdeo/api/models/emo.py +128 -0
  18. desdeo/api/models/enautilus.py +69 -0
  19. desdeo/api/models/gdm/gdm_aggregate.py +139 -0
  20. desdeo/api/models/gdm/gdm_base.py +69 -0
  21. desdeo/api/models/gdm/gdm_score_bands.py +114 -0
  22. desdeo/api/models/gdm/gnimbus.py +138 -0
  23. desdeo/api/models/generic.py +104 -0
  24. desdeo/api/models/generic_states.py +401 -0
  25. desdeo/api/models/nimbus.py +158 -0
  26. desdeo/api/models/preference.py +128 -0
  27. desdeo/api/models/problem.py +717 -0
  28. desdeo/api/models/reference_point_method.py +18 -0
  29. desdeo/api/models/session.py +49 -0
  30. desdeo/api/models/state.py +463 -0
  31. desdeo/api/models/user.py +52 -0
  32. desdeo/api/models/utopia.py +25 -0
  33. desdeo/api/routers/_EMO.backup +309 -0
  34. desdeo/api/routers/_NAUTILUS.py +245 -0
  35. desdeo/api/routers/_NAUTILUS_navigator.py +233 -0
  36. desdeo/api/routers/_NIMBUS.py +765 -0
  37. desdeo/api/routers/__init__.py +5 -0
  38. desdeo/api/routers/emo.py +497 -0
  39. desdeo/api/routers/enautilus.py +237 -0
  40. desdeo/api/routers/gdm/gdm_aggregate.py +234 -0
  41. desdeo/api/routers/gdm/gdm_base.py +420 -0
  42. desdeo/api/routers/gdm/gdm_score_bands/gdm_score_bands_manager.py +398 -0
  43. desdeo/api/routers/gdm/gdm_score_bands/gdm_score_bands_routers.py +377 -0
  44. desdeo/api/routers/gdm/gnimbus/gnimbus_manager.py +698 -0
  45. desdeo/api/routers/gdm/gnimbus/gnimbus_routers.py +591 -0
  46. desdeo/api/routers/generic.py +233 -0
  47. desdeo/api/routers/nimbus.py +705 -0
  48. desdeo/api/routers/problem.py +307 -0
  49. desdeo/api/routers/reference_point_method.py +93 -0
  50. desdeo/api/routers/session.py +100 -0
  51. desdeo/api/routers/test.py +16 -0
  52. desdeo/api/routers/user_authentication.py +520 -0
  53. desdeo/api/routers/utils.py +187 -0
  54. desdeo/api/routers/utopia.py +230 -0
  55. desdeo/api/schema.py +100 -0
  56. desdeo/api/tests/__init__.py +0 -0
  57. desdeo/api/tests/conftest.py +151 -0
  58. desdeo/api/tests/test_enautilus.py +330 -0
  59. desdeo/api/tests/test_models.py +1179 -0
  60. desdeo/api/tests/test_routes.py +1075 -0
  61. desdeo/api/utils/_database.py +263 -0
  62. desdeo/api/utils/_logger.py +29 -0
  63. desdeo/api/utils/database.py +36 -0
  64. desdeo/api/utils/emo_database.py +40 -0
  65. desdeo/core.py +34 -0
  66. desdeo/emo/__init__.py +159 -0
  67. desdeo/emo/hooks/archivers.py +188 -0
  68. desdeo/emo/methods/EAs.py +541 -0
  69. desdeo/emo/methods/__init__.py +0 -0
  70. desdeo/emo/methods/bases.py +12 -0
  71. desdeo/emo/methods/templates.py +111 -0
  72. desdeo/emo/operators/__init__.py +1 -0
  73. desdeo/emo/operators/crossover.py +1282 -0
  74. desdeo/emo/operators/evaluator.py +114 -0
  75. desdeo/emo/operators/generator.py +459 -0
  76. desdeo/emo/operators/mutation.py +1224 -0
  77. desdeo/emo/operators/scalar_selection.py +202 -0
  78. desdeo/emo/operators/selection.py +1778 -0
  79. desdeo/emo/operators/termination.py +286 -0
  80. desdeo/emo/options/__init__.py +108 -0
  81. desdeo/emo/options/algorithms.py +435 -0
  82. desdeo/emo/options/crossover.py +164 -0
  83. desdeo/emo/options/generator.py +131 -0
  84. desdeo/emo/options/mutation.py +260 -0
  85. desdeo/emo/options/repair.py +61 -0
  86. desdeo/emo/options/scalar_selection.py +66 -0
  87. desdeo/emo/options/selection.py +127 -0
  88. desdeo/emo/options/templates.py +383 -0
  89. desdeo/emo/options/termination.py +143 -0
  90. desdeo/explanations/__init__.py +6 -0
  91. desdeo/explanations/explainer.py +100 -0
  92. desdeo/explanations/utils.py +90 -0
  93. desdeo/gdm/__init__.py +22 -0
  94. desdeo/gdm/gdmtools.py +45 -0
  95. desdeo/gdm/score_bands.py +114 -0
  96. desdeo/gdm/voting_rules.py +50 -0
  97. desdeo/mcdm/__init__.py +41 -0
  98. desdeo/mcdm/enautilus.py +338 -0
  99. desdeo/mcdm/gnimbus.py +484 -0
  100. desdeo/mcdm/nautili.py +345 -0
  101. desdeo/mcdm/nautilus.py +477 -0
  102. desdeo/mcdm/nautilus_navigator.py +656 -0
  103. desdeo/mcdm/nimbus.py +417 -0
  104. desdeo/mcdm/pareto_navigator.py +269 -0
  105. desdeo/mcdm/reference_point_method.py +186 -0
  106. desdeo/problem/__init__.py +83 -0
  107. desdeo/problem/evaluator.py +561 -0
  108. desdeo/problem/external/__init__.py +18 -0
  109. desdeo/problem/external/core.py +356 -0
  110. desdeo/problem/external/pymoo_provider.py +266 -0
  111. desdeo/problem/external/runtime.py +44 -0
  112. desdeo/problem/gurobipy_evaluator.py +562 -0
  113. desdeo/problem/infix_parser.py +341 -0
  114. desdeo/problem/json_parser.py +944 -0
  115. desdeo/problem/pyomo_evaluator.py +487 -0
  116. desdeo/problem/schema.py +1829 -0
  117. desdeo/problem/simulator_evaluator.py +348 -0
  118. desdeo/problem/sympy_evaluator.py +244 -0
  119. desdeo/problem/testproblems/__init__.py +88 -0
  120. desdeo/problem/testproblems/benchmarks_server.py +120 -0
  121. desdeo/problem/testproblems/binh_and_korn_problem.py +88 -0
  122. desdeo/problem/testproblems/cake_problem.py +185 -0
  123. desdeo/problem/testproblems/dmitry_forest_problem_discrete.py +71 -0
  124. desdeo/problem/testproblems/dtlz2_problem.py +102 -0
  125. desdeo/problem/testproblems/forest_problem.py +283 -0
  126. desdeo/problem/testproblems/knapsack_problem.py +163 -0
  127. desdeo/problem/testproblems/mcwb_problem.py +831 -0
  128. desdeo/problem/testproblems/mixed_variable_dimenrions_problem.py +83 -0
  129. desdeo/problem/testproblems/momip_problem.py +172 -0
  130. desdeo/problem/testproblems/multi_valued_constraints.py +119 -0
  131. desdeo/problem/testproblems/nimbus_problem.py +143 -0
  132. desdeo/problem/testproblems/pareto_navigator_problem.py +89 -0
  133. desdeo/problem/testproblems/re_problem.py +492 -0
  134. desdeo/problem/testproblems/river_pollution_problems.py +440 -0
  135. desdeo/problem/testproblems/rocket_injector_design_problem.py +140 -0
  136. desdeo/problem/testproblems/simple_problem.py +351 -0
  137. desdeo/problem/testproblems/simulator_problem.py +92 -0
  138. desdeo/problem/testproblems/single_objective.py +289 -0
  139. desdeo/problem/testproblems/spanish_sustainability_problem.py +945 -0
  140. desdeo/problem/testproblems/zdt_problem.py +274 -0
  141. desdeo/problem/utils.py +245 -0
  142. desdeo/tools/GenerateReferencePoints.py +181 -0
  143. desdeo/tools/__init__.py +120 -0
  144. desdeo/tools/desc_gen.py +22 -0
  145. desdeo/tools/generics.py +165 -0
  146. desdeo/tools/group_scalarization.py +3090 -0
  147. desdeo/tools/gurobipy_solver_interfaces.py +258 -0
  148. desdeo/tools/indicators_binary.py +117 -0
  149. desdeo/tools/indicators_unary.py +362 -0
  150. desdeo/tools/interaction_schema.py +38 -0
  151. desdeo/tools/intersection.py +54 -0
  152. desdeo/tools/iterative_pareto_representer.py +99 -0
  153. desdeo/tools/message.py +265 -0
  154. desdeo/tools/ng_solver_interfaces.py +199 -0
  155. desdeo/tools/non_dominated_sorting.py +134 -0
  156. desdeo/tools/patterns.py +283 -0
  157. desdeo/tools/proximal_solver.py +99 -0
  158. desdeo/tools/pyomo_solver_interfaces.py +477 -0
  159. desdeo/tools/reference_vectors.py +229 -0
  160. desdeo/tools/scalarization.py +2065 -0
  161. desdeo/tools/scipy_solver_interfaces.py +454 -0
  162. desdeo/tools/score_bands.py +627 -0
  163. desdeo/tools/utils.py +388 -0
  164. desdeo/tools/visualizations.py +67 -0
  165. desdeo/utopia_stuff/__init__.py +0 -0
  166. desdeo/utopia_stuff/data/1.json +15 -0
  167. desdeo/utopia_stuff/data/2.json +13 -0
  168. desdeo/utopia_stuff/data/3.json +15 -0
  169. desdeo/utopia_stuff/data/4.json +17 -0
  170. desdeo/utopia_stuff/data/5.json +15 -0
  171. desdeo/utopia_stuff/from_json.py +40 -0
  172. desdeo/utopia_stuff/reinit_user.py +38 -0
  173. desdeo/utopia_stuff/utopia_db_init.py +212 -0
  174. desdeo/utopia_stuff/utopia_problem.py +403 -0
  175. desdeo/utopia_stuff/utopia_problem_old.py +415 -0
  176. desdeo/utopia_stuff/utopia_reference_solutions.py +79 -0
  177. desdeo-2.1.0.dist-info/METADATA +186 -0
  178. desdeo-2.1.0.dist-info/RECORD +180 -0
  179. {desdeo-1.2.dist-info → desdeo-2.1.0.dist-info}/WHEEL +1 -1
  180. desdeo-2.1.0.dist-info/licenses/LICENSE +21 -0
  181. desdeo-1.2.dist-info/METADATA +0 -16
  182. 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
+ )