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,186 @@
1
+ """Functions related to the reference point method.
2
+
3
+ This module contains functions related to the reference point method as
4
+ presented in Wierzbicki, A. P. (1982). A mathematical basis for satisficing
5
+ decision making. Mathematical modelling, 3(5), 391-405.
6
+ """
7
+
8
+ import numpy as np
9
+
10
+ from desdeo.problem import (
11
+ Problem,
12
+ numpy_array_to_objective_dict,
13
+ objective_dict_to_numpy_array,
14
+ )
15
+ from desdeo.tools import (
16
+ BaseSolver,
17
+ SolverOptions,
18
+ SolverResults,
19
+ add_asf_diff,
20
+ add_asf_nondiff,
21
+ guess_best_solver,
22
+ )
23
+
24
+
25
+ class ReferencePointError(Exception):
26
+ """Raised when an error with the reference point method is encountered."""
27
+
28
+
29
+ def rpm_solve_solutions(
30
+ problem: Problem,
31
+ reference_point: dict[str, float],
32
+ scalarization_options: dict | None = None,
33
+ solver: BaseSolver | None = None,
34
+ solver_options: SolverOptions | None = None,
35
+ ) -> list[SolverResults]:
36
+ """Finds (near) Pareto optimal solutions based on a reference point.
37
+
38
+ Find a (near) Pareto optimal solution based on the given reference point by
39
+ optimizing an achievement scalarizing function. The original reference point
40
+ is also perturbed, and another k (near) Pareto optimal solutions are found.
41
+ The k+1 solutions are then returned.
42
+
43
+ Args:
44
+ problem (Problem): the problem to be solved.
45
+ reference_point (dict[str, float]): the reference point. The keys of the dict
46
+ represent the objective function symbols defined in problem. The values
47
+ represent the aspiration level values.
48
+ scalarization_options (dict | None, optional): keyword arguments to be
49
+ passed to the achievement scalarizing function. Defaults to None.
50
+ solver (BaseSolver | None, optional): solver to optimize the achievement
51
+ scalarizing function. If not given, the method tried to guess the
52
+ most suitable solver based on the problem. Defaults to None.
53
+ solver_options (SolverOptions | None, optional): options passed to the
54
+ solver. If not given, the solver will use its default options. Defaults to None.
55
+
56
+ Raises:
57
+ ReferencePointError: the reference point is ill-defined.
58
+
59
+ Returns:
60
+ list[SolverResults]: a list of results containing the solutions found using
61
+ the reference point and the k perturbed reference points.
62
+
63
+ Note:
64
+ If the problem is twice differentiable, `add_asf_diff` is used from `desdeo.tools`.
65
+ If the problem is not twice differentiable, then `add_asf_nondiff` is used.
66
+ """
67
+ # setup problem with ASF
68
+ # check if problem is differentiable or not, choose appropriate ASF variant.
69
+
70
+ if not all(obj.symbol in reference_point for obj in problem.objectives):
71
+ msg = f"The reference point {reference_point} is missing entries for one or more of the objective functions."
72
+ raise ReferencePointError(msg)
73
+
74
+ _add_asf = add_asf_diff if problem.is_twice_differentiable else add_asf_nondiff
75
+
76
+ problem_w_asf, target = _add_asf(
77
+ problem, "_asf", reference_point, **scalarization_options if scalarization_options is not None else {}
78
+ )
79
+
80
+ # setup solver
81
+ # solve scalarized problem with given reference point
82
+
83
+ _init_solver = guess_best_solver(problem_w_asf) if solver is None else solver
84
+ _solver = _init_solver(problem_w_asf, solver_options)
85
+
86
+ initial_solution = _solver.solve(target)
87
+
88
+ # using the found solution, perturb the reference point to get
89
+ # k (num of objectives) perturbed reference points
90
+
91
+ initial_objective_vector = objective_dict_to_numpy_array(problem, initial_solution.optimal_objectives)
92
+ reference_point_vector = objective_dict_to_numpy_array(problem, reference_point)
93
+
94
+ distance = np.linalg.norm(reference_point_vector - initial_objective_vector)
95
+ unit_vectors = np.eye(len(initial_objective_vector))
96
+
97
+ perturbed_reference_point_vectors = reference_point_vector + (distance * unit_vectors)
98
+
99
+ perturbed_reference_points = [numpy_array_to_objective_dict(problem, v) for v in perturbed_reference_point_vectors]
100
+
101
+ # scalarize the problem using the appropriate ASF variant and the perturbed
102
+ # reference points
103
+
104
+ perturbed_problems_and_targets = [
105
+ _add_asf(problem, "_asf", rp, **scalarization_options if scalarization_options is not None else {})
106
+ for rp in perturbed_reference_points
107
+ ]
108
+
109
+ # solve the problems
110
+ perturbed_solutions = [
111
+ _init_solver(problem_and_target[0], solver_options).solve(problem_and_target[1])
112
+ for problem_and_target in perturbed_problems_and_targets
113
+ ]
114
+
115
+ # return the original solution and the solutions found with the perturbed reference points
116
+ return [initial_solution, *perturbed_solutions]
117
+
118
+
119
+ def rpm_intermediate_solutions( # noqa: PLR0913
120
+ problem: Problem,
121
+ solution_1: dict[str, float],
122
+ solution_2: dict[str, float],
123
+ num_desired: int,
124
+ scalarization_options: dict | None = None,
125
+ solver: BaseSolver | None = None,
126
+ solver_options: SolverOptions | None = None,
127
+ ) -> list[SolverResults]:
128
+ """Generates a desired number of intermediate solutions between two given solutions.
129
+
130
+ Generates a desires number of intermediate solutions given reference vectors.
131
+ The solutions are generated by taking n number of steps between the two reference points in the
132
+ objective space. The vectors corresponding to these values are then
133
+ utilized as reference points in the achievement scalarizing function. Solving the functions
134
+ for each reference point will a solution close the the projection of the reference point on the
135
+ Pareto optimal front of the problem. These solutions are then returned. Note that the
136
+ intermediate solutions are generated _between_ the two given reference points, this means the
137
+ returned solutions will not include solutions corresponding to the original reference points.
138
+
139
+ Args:
140
+ problem (Problem): the problem being solved.
141
+ solution_1 (dict[str, VariableType]): the first of the reference points between which the intermediate
142
+ solutions are to be generated.
143
+ solution_2 (dict[str, VariableType]): the second of the reference points between which the intermediate
144
+ solutions are to be generated.
145
+ num_desired (int): the number of desired intermediate solutions to be generated. Must be at least `1`.
146
+ scalarization_options (dict | None, optional): optional kwargs passed to the scalarization function.
147
+ Defaults to None.
148
+ solver (BaseSolver | None, optional): solver used to solve the problem.
149
+ If not given, an appropriate solver will be automatically determined based on the features of `problem`.
150
+ Defaults to None.
151
+ solver_options (SolverOptions | None, optional): optional options passed
152
+ to the `solver`. Ignored if `solver` is `None`.
153
+ Defaults to None.
154
+
155
+ Returns:
156
+ list[SolverResults]: a list with the projected intermediate solutions as
157
+ `SolverResults` objects.
158
+ """
159
+ if int(num_desired) < 1:
160
+ msg = f"The given number of desired intermediate ({num_desired=}) solutions must be at least 1."
161
+ raise ReferencePointError(msg)
162
+
163
+ init_solver = guess_best_solver(problem) if solver is None else solver
164
+ _solver_options = None if solver_options is None or solver is None else solver_options
165
+
166
+ # Find intermediate solutions by dividing the distance between the two Pareto points into num_desired+1 steps,
167
+ # calculate the solutions found in between the points, because we don't want to find the original solutions
168
+ intermediate_solutions = []
169
+
170
+ for i in range(num_desired):
171
+ rp = {
172
+ key: ((i + 1) * solution_1[key] + (num_desired - i) * solution_2[key]) / (num_desired + 1)
173
+ for key in solution_1.keys() # noqa: SIM118
174
+ }
175
+ # add scalarization
176
+ add_asf = add_asf_diff if problem.is_twice_differentiable else add_asf_nondiff
177
+ asf_problem, target = add_asf(problem, "target", rp, **(scalarization_options or {}))
178
+
179
+ solver = init_solver(asf_problem, _solver_options)
180
+
181
+ # solve and store results
182
+ result: SolverResults = solver.solve(target)
183
+
184
+ intermediate_solutions.append(result)
185
+
186
+ return intermediate_solutions
@@ -0,0 +1,83 @@
1
+ """Imports available from the desdeo-problem package."""
2
+
3
+ __all__ = [
4
+ "Constant",
5
+ "Constraint",
6
+ "ConstraintTypeEnum",
7
+ "DiscreteRepresentation",
8
+ "Evaluator",
9
+ "ExtraFunction",
10
+ "flatten_variable_dict",
11
+ "FormatEnum",
12
+ "GurobipyEvaluator",
13
+ "get_nadir_dict",
14
+ "get_ideal_dict",
15
+ "InfixExpressionParser",
16
+ "MathParser",
17
+ "numpy_array_to_objective_dict",
18
+ "objective_dict_to_numpy_array",
19
+ "Objective",
20
+ "ObjectiveTypeEnum",
21
+ "Problem",
22
+ "PyomoEvaluator",
23
+ "SympyEvaluator",
24
+ "tensor_constant_from_dataframe",
25
+ "PolarsEvaluator",
26
+ "PolarsEvaluatorModesEnum",
27
+ "ScalarizationFunction",
28
+ "Simulator",
29
+ "TensorConstant",
30
+ "TensorVariable",
31
+ "Url",
32
+ "unflatten_variable_array",
33
+ "Variable",
34
+ "VariableDimensionEnum",
35
+ "VariableDomainTypeEnum",
36
+ "VariableType",
37
+ "Tensor",
38
+ "VariableTypeEnum",
39
+ "variable_dimension_enumerate",
40
+ ]
41
+
42
+
43
+ from .evaluator import (
44
+ PolarsEvaluator,
45
+ PolarsEvaluatorModesEnum,
46
+ VariableDimensionEnum,
47
+ variable_dimension_enumerate,
48
+ )
49
+ from .gurobipy_evaluator import GurobipyEvaluator
50
+ from .infix_parser import InfixExpressionParser
51
+ from .json_parser import FormatEnum, MathParser
52
+ from .pyomo_evaluator import PyomoEvaluator
53
+ from .schema import (
54
+ Constant,
55
+ Constraint,
56
+ ConstraintTypeEnum,
57
+ DiscreteRepresentation,
58
+ ExtraFunction,
59
+ Objective,
60
+ ObjectiveTypeEnum,
61
+ Problem,
62
+ ScalarizationFunction,
63
+ Simulator,
64
+ Tensor,
65
+ TensorConstant,
66
+ TensorVariable,
67
+ Url,
68
+ Variable,
69
+ VariableDomainTypeEnum,
70
+ VariableType,
71
+ VariableTypeEnum,
72
+ )
73
+ from .simulator_evaluator import SimulatorEvaluator
74
+ from .sympy_evaluator import SympyEvaluator
75
+ from .utils import (
76
+ flatten_variable_dict,
77
+ get_ideal_dict,
78
+ get_nadir_dict,
79
+ numpy_array_to_objective_dict,
80
+ objective_dict_to_numpy_array,
81
+ tensor_constant_from_dataframe,
82
+ unflatten_variable_array,
83
+ )