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,188 @@
|
|
|
1
|
+
"""A collection of archivers for storing solutions evaluated during evolution."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
|
|
5
|
+
import polars as pl
|
|
6
|
+
|
|
7
|
+
from desdeo.problem import Problem
|
|
8
|
+
from desdeo.tools.generics import EMOResult
|
|
9
|
+
from desdeo.tools.message import (
|
|
10
|
+
EvaluatorMessageTopics,
|
|
11
|
+
GeneratorMessageTopics,
|
|
12
|
+
Message,
|
|
13
|
+
MessageTopics,
|
|
14
|
+
SelectorMessageTopics,
|
|
15
|
+
TerminatorMessageTopics,
|
|
16
|
+
)
|
|
17
|
+
from desdeo.tools.non_dominated_sorting import non_dominated, non_dominated_merge
|
|
18
|
+
from desdeo.tools.patterns import Publisher, Subscriber
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BaseArchive(Subscriber):
|
|
22
|
+
"""Base class for archivers."""
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def interested_topics(self) -> Sequence[MessageTopics]:
|
|
26
|
+
"""Return the message topics that the archiver is interested in."""
|
|
27
|
+
return [
|
|
28
|
+
GeneratorMessageTopics.VERBOSE_OUTPUTS,
|
|
29
|
+
EvaluatorMessageTopics.VERBOSE_OUTPUTS,
|
|
30
|
+
SelectorMessageTopics.SELECTED_VERBOSE_OUTPUTS,
|
|
31
|
+
TerminatorMessageTopics.GENERATION,
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def provided_topics(self) -> dict[int, Sequence[MessageTopics]]:
|
|
36
|
+
"""Return the topics provided by the archiver."""
|
|
37
|
+
return {0: []}
|
|
38
|
+
|
|
39
|
+
def __init__(self, *, problem: Problem, publisher: Publisher):
|
|
40
|
+
"""Initialize the base archiver.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
problem (Problem): The problem being solved.
|
|
44
|
+
publisher (Publisher): The publisher object.
|
|
45
|
+
"""
|
|
46
|
+
super().__init__(publisher, verbosity=0)
|
|
47
|
+
self.solutions: pl.DataFrame = None
|
|
48
|
+
self.selections: pl.DataFrame = None
|
|
49
|
+
self.problem = problem
|
|
50
|
+
self.generation_number = 1
|
|
51
|
+
|
|
52
|
+
def state(self) -> Sequence[Message]:
|
|
53
|
+
"""Return the state of the archiver."""
|
|
54
|
+
return []
|
|
55
|
+
|
|
56
|
+
def update(self, message: Message) -> None:
|
|
57
|
+
"""Updae the archiver with new data.
|
|
58
|
+
|
|
59
|
+
Takes care of common archiving jobs. Make sure to run this for every archiver.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
message (Message): Message from the publisher.
|
|
63
|
+
"""
|
|
64
|
+
if message.topic == TerminatorMessageTopics.GENERATION:
|
|
65
|
+
self.generation_number = message.value
|
|
66
|
+
return
|
|
67
|
+
if message.topic == SelectorMessageTopics.SELECTED_VERBOSE_OUTPUTS:
|
|
68
|
+
data: pl.DataFrame = message.value
|
|
69
|
+
data = data.with_columns(generation=self.generation_number)
|
|
70
|
+
if self.selections is None:
|
|
71
|
+
self.selections = data
|
|
72
|
+
else:
|
|
73
|
+
self.selections = pl.concat([self.selections, data], how="vertical")
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def results(self) -> EMOResult:
|
|
78
|
+
"""Return the results of the archiver."""
|
|
79
|
+
dec_vars = [x.symbol for x in self.problem.get_flattened_variables()]
|
|
80
|
+
all_cols = self.solutions.columns
|
|
81
|
+
non_decs = [col for col in all_cols if col not in dec_vars]
|
|
82
|
+
return EMOResult(optimal_variables=self.solutions[dec_vars], optimal_outputs=self.solutions[non_decs])
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class FeasibleArchive(BaseArchive):
|
|
86
|
+
"""An archiver that stores all feasible solutions evaluated during evolution."""
|
|
87
|
+
|
|
88
|
+
def __init__(self, *, problem: Problem, publisher: Publisher):
|
|
89
|
+
"""Initialize the archiver.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
problem (Problem): The problem being solved.
|
|
93
|
+
publisher (Publisher): The publisher object.
|
|
94
|
+
"""
|
|
95
|
+
super().__init__(problem=problem, publisher=publisher)
|
|
96
|
+
|
|
97
|
+
if problem.constraints is None:
|
|
98
|
+
raise ValueError("The problem has no constraints.")
|
|
99
|
+
self.cons_symb = [x.symbol for x in problem.constraints]
|
|
100
|
+
|
|
101
|
+
def update(self, message: Message) -> None:
|
|
102
|
+
"""Update the archiver with the new data.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
message (Message): Message from the publisher.
|
|
106
|
+
"""
|
|
107
|
+
if (
|
|
108
|
+
message.topic == TerminatorMessageTopics.GENERATION # NOQA: PLR1714
|
|
109
|
+
or message.topic == SelectorMessageTopics.SELECTED_VERBOSE_OUTPUTS
|
|
110
|
+
):
|
|
111
|
+
super().update(message)
|
|
112
|
+
return
|
|
113
|
+
data = message.value
|
|
114
|
+
feasible_mask = (data[self.cons_symb] <= 0).to_numpy().all(axis=1)
|
|
115
|
+
feasible_data = data.filter(feasible_mask)
|
|
116
|
+
feasible_data = feasible_data.with_columns(generation=self.generation_number)
|
|
117
|
+
if self.solutions is None:
|
|
118
|
+
self.solutions = feasible_data
|
|
119
|
+
else:
|
|
120
|
+
self.solutions = pl.concat([self.solutions, feasible_data])
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class Archive(BaseArchive):
|
|
124
|
+
"""An archiver that stores the solutions evaluated during evolution."""
|
|
125
|
+
|
|
126
|
+
def update(self, message: Message) -> None:
|
|
127
|
+
"""Update the archiver with the new data.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
message (Message): Message from the publisher.
|
|
131
|
+
"""
|
|
132
|
+
if (
|
|
133
|
+
message.topic == TerminatorMessageTopics.GENERATION # NOQA: PLR1714
|
|
134
|
+
or message.topic == SelectorMessageTopics.SELECTED_VERBOSE_OUTPUTS
|
|
135
|
+
):
|
|
136
|
+
super().update(message)
|
|
137
|
+
return
|
|
138
|
+
data = message.value
|
|
139
|
+
data = data.with_columns(generation=self.generation_number)
|
|
140
|
+
if self.solutions is None:
|
|
141
|
+
self.solutions = data
|
|
142
|
+
else:
|
|
143
|
+
self.solutions = pl.concat([self.solutions, data])
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class NonDominatedArchive(Archive):
|
|
147
|
+
"""An archiver that stores only the feasible non-dominated solutions evaluated during evolution."""
|
|
148
|
+
|
|
149
|
+
def __init__(self, *, problem: Problem, publisher: Publisher):
|
|
150
|
+
"""Initialize the archiver.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
problem (Problem): The problem being solved.
|
|
154
|
+
publisher (Publisher): The publisher object.
|
|
155
|
+
"""
|
|
156
|
+
super().__init__(problem=problem, publisher=publisher)
|
|
157
|
+
self.targets = [f"{x.symbol}_min" for x in problem.objectives]
|
|
158
|
+
if problem.constraints is None:
|
|
159
|
+
self.cons_symb = []
|
|
160
|
+
else:
|
|
161
|
+
self.cons_symb = [x.symbol for x in problem.constraints]
|
|
162
|
+
|
|
163
|
+
def update(self, message: Message) -> None:
|
|
164
|
+
"""Update the archiver with the new data.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
message (Message): Message from the publisher.
|
|
168
|
+
"""
|
|
169
|
+
if (
|
|
170
|
+
message.topic == TerminatorMessageTopics.GENERATION # NOQA: PLR1714
|
|
171
|
+
or message.topic == SelectorMessageTopics.SELECTED_VERBOSE_OUTPUTS
|
|
172
|
+
):
|
|
173
|
+
super().update(message)
|
|
174
|
+
return
|
|
175
|
+
data = message.value
|
|
176
|
+
data = data.with_columns(generation=self.generation_number)
|
|
177
|
+
if type(data) is not pl.DataFrame:
|
|
178
|
+
raise ValueError("Data should be a polars DataFrame")
|
|
179
|
+
if self.cons_symb:
|
|
180
|
+
feasible_mask = (data[self.cons_symb] <= 0).to_numpy().all(axis=1)
|
|
181
|
+
data = data.filter(feasible_mask)
|
|
182
|
+
if self.solutions is None:
|
|
183
|
+
non_dom_mask = non_dominated(data[self.targets].to_numpy())
|
|
184
|
+
self.solutions = data.filter(non_dom_mask)
|
|
185
|
+
else:
|
|
186
|
+
to_add = data.filter(non_dominated(data[self.targets].to_numpy()))
|
|
187
|
+
mask1, mask2 = non_dominated_merge(self.solutions[self.targets].to_numpy(), to_add[self.targets].to_numpy())
|
|
188
|
+
self.solutions = pl.concat([self.solutions.filter(mask1), to_add.filter(mask2)])
|