desdeo 2.0.0__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/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/__init__.py +6 -6
- desdeo/api/app.py +38 -28
- desdeo/api/config.py +65 -44
- desdeo/api/config.toml +23 -12
- desdeo/api/db.py +10 -8
- desdeo/api/db_init.py +12 -6
- desdeo/api/models/__init__.py +220 -20
- desdeo/api/models/archive.py +16 -27
- 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 +44 -6
- desdeo/api/models/problem.py +274 -64
- desdeo/api/models/session.py +4 -1
- desdeo/api/models/state.py +419 -52
- desdeo/api/models/user.py +7 -6
- desdeo/api/models/utopia.py +25 -0
- desdeo/api/routers/_EMO.backup +309 -0
- desdeo/api/routers/_NIMBUS.py +6 -3
- 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 +201 -4
- desdeo/api/routers/reference_point_method.py +20 -44
- desdeo/api/routers/session.py +50 -26
- desdeo/api/routers/user_authentication.py +180 -26
- desdeo/api/routers/utils.py +187 -0
- desdeo/api/routers/utopia.py +230 -0
- desdeo/api/schema.py +10 -4
- desdeo/api/tests/conftest.py +94 -2
- desdeo/api/tests/test_enautilus.py +330 -0
- desdeo/api/tests/test_models.py +550 -72
- desdeo/api/tests/test_routes.py +902 -43
- desdeo/api/utils/_database.py +263 -0
- desdeo/api/utils/database.py +28 -266
- desdeo/api/utils/emo_database.py +40 -0
- desdeo/core.py +7 -0
- desdeo/emo/__init__.py +154 -24
- desdeo/emo/hooks/archivers.py +18 -2
- desdeo/emo/methods/EAs.py +128 -5
- desdeo/emo/methods/bases.py +9 -56
- desdeo/emo/methods/templates.py +111 -0
- desdeo/emo/operators/crossover.py +544 -42
- desdeo/emo/operators/evaluator.py +10 -14
- desdeo/emo/operators/generator.py +127 -24
- desdeo/emo/operators/mutation.py +212 -41
- desdeo/emo/operators/scalar_selection.py +202 -0
- desdeo/emo/operators/selection.py +956 -214
- desdeo/emo/operators/termination.py +124 -16
- 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/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 +23 -1
- desdeo/mcdm/enautilus.py +338 -0
- desdeo/mcdm/gnimbus.py +484 -0
- desdeo/mcdm/nautilus_navigator.py +7 -6
- desdeo/mcdm/reference_point_method.py +70 -0
- desdeo/problem/__init__.py +5 -1
- 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/infix_parser.py +2 -2
- desdeo/problem/pyomo_evaluator.py +25 -6
- desdeo/problem/schema.py +69 -48
- desdeo/problem/simulator_evaluator.py +65 -15
- desdeo/problem/testproblems/__init__.py +26 -11
- desdeo/problem/testproblems/benchmarks_server.py +120 -0
- desdeo/problem/testproblems/cake_problem.py +185 -0
- desdeo/problem/testproblems/dmitry_forest_problem_discrete.py +71 -0
- desdeo/problem/testproblems/forest_problem.py +77 -69
- desdeo/problem/testproblems/multi_valued_constraints.py +119 -0
- desdeo/problem/testproblems/{river_pollution_problem.py → river_pollution_problems.py} +28 -22
- desdeo/problem/testproblems/single_objective.py +289 -0
- desdeo/problem/testproblems/zdt_problem.py +4 -1
- desdeo/tools/__init__.py +39 -21
- desdeo/tools/desc_gen.py +22 -0
- desdeo/tools/generics.py +22 -2
- desdeo/tools/group_scalarization.py +3090 -0
- desdeo/tools/indicators_binary.py +107 -1
- desdeo/tools/indicators_unary.py +3 -16
- desdeo/tools/message.py +33 -2
- desdeo/tools/non_dominated_sorting.py +4 -3
- desdeo/tools/patterns.py +9 -7
- desdeo/tools/pyomo_solver_interfaces.py +48 -35
- desdeo/tools/reference_vectors.py +118 -351
- desdeo/tools/scalarization.py +340 -1413
- desdeo/tools/score_bands.py +491 -328
- desdeo/tools/utils.py +117 -49
- desdeo/tools/visualizations.py +67 -0
- desdeo/utopia_stuff/utopia_problem.py +1 -1
- desdeo/utopia_stuff/utopia_problem_old.py +1 -1
- {desdeo-2.0.0.dist-info → desdeo-2.1.0.dist-info}/METADATA +46 -28
- desdeo-2.1.0.dist-info/RECORD +180 -0
- {desdeo-2.0.0.dist-info → desdeo-2.1.0.dist-info}/WHEEL +1 -1
- desdeo-2.0.0.dist-info/RECORD +0 -120
- /desdeo/api/utils/{logger.py → _logger.py} +0 -0
- {desdeo-2.0.0.dist-info → desdeo-2.1.0.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"""Router for evolutionary multiobjective optimization (EMO) methods."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Annotated, Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
from fastapi import APIRouter, Depends, HTTPException, status
|
|
7
|
+
from sqlalchemy.orm import Session
|
|
8
|
+
from sqlmodel import select
|
|
9
|
+
|
|
10
|
+
from desdeo.api.db import get_session
|
|
11
|
+
from desdeo.api.models.archive import (
|
|
12
|
+
UserSavedEMOResults,
|
|
13
|
+
)
|
|
14
|
+
from desdeo.api.models.EMO import (
|
|
15
|
+
EMOSaveRequest,
|
|
16
|
+
EMOSolveRequest,
|
|
17
|
+
)
|
|
18
|
+
from desdeo.api.models.preference import (
|
|
19
|
+
NonPreferredSolutions,
|
|
20
|
+
PreferenceBase,
|
|
21
|
+
PreferenceDB,
|
|
22
|
+
PreferredRanges,
|
|
23
|
+
PreferredSolutions,
|
|
24
|
+
ReferencePoint,
|
|
25
|
+
)
|
|
26
|
+
from desdeo.api.models.problem import ProblemDB
|
|
27
|
+
from desdeo.api.models.session import InteractiveSessionDB
|
|
28
|
+
from desdeo.api.models.state import EMOSaveState, EMOState, StateDB
|
|
29
|
+
from desdeo.api.models.user import User
|
|
30
|
+
from desdeo.api.routers.user_authentication import get_current_user
|
|
31
|
+
from desdeo.api.utils.database import user_save_solutions
|
|
32
|
+
from desdeo.api.utils.emo_database import _convert_dataframe_to_dict_list
|
|
33
|
+
from desdeo.emo.hooks.archivers import NonDominatedArchive
|
|
34
|
+
from desdeo.emo.methods.EAs import nsga3, rvea
|
|
35
|
+
from desdeo.problem import Problem
|
|
36
|
+
|
|
37
|
+
router = APIRouter(prefix="/method/emo", tags=["evolutionary"])
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@router.post("/solve")
|
|
41
|
+
def start_emo_optimization(
|
|
42
|
+
request: EMOSolveRequest,
|
|
43
|
+
user: Annotated[User, Depends(get_current_user)],
|
|
44
|
+
session: Annotated[Session, Depends(get_session)],
|
|
45
|
+
) -> EMOState:
|
|
46
|
+
"""Start interactive evolutionary multiobjective optimization."""
|
|
47
|
+
|
|
48
|
+
# Handle session logic
|
|
49
|
+
if request.session_id is not None:
|
|
50
|
+
statement = select(InteractiveSessionDB).where(InteractiveSessionDB.id == request.session_id)
|
|
51
|
+
interactive_session = session.exec(statement).first()
|
|
52
|
+
|
|
53
|
+
if interactive_session is None:
|
|
54
|
+
raise HTTPException(
|
|
55
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
56
|
+
detail=f"Could not find interactive session with id={request.session_id}.",
|
|
57
|
+
)
|
|
58
|
+
else:
|
|
59
|
+
# Use active session
|
|
60
|
+
statement = select(InteractiveSessionDB).where(InteractiveSessionDB.id == user.active_session_id)
|
|
61
|
+
interactive_session = session.exec(statement).first()
|
|
62
|
+
|
|
63
|
+
# Fetch problem from DB
|
|
64
|
+
statement = select(ProblemDB).where(ProblemDB.user_id == user.id, ProblemDB.id == request.problem_id)
|
|
65
|
+
problem_db = session.exec(statement).first()
|
|
66
|
+
|
|
67
|
+
if problem_db is None:
|
|
68
|
+
raise HTTPException(
|
|
69
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
70
|
+
detail=f"Problem with id={request.problem_id} could not be found.",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Convert ProblemDB to Problem object
|
|
74
|
+
problem = Problem.from_problemdb(problem_db)
|
|
75
|
+
|
|
76
|
+
# Build reference vector options based on preference type
|
|
77
|
+
reference_vector_options = _build_reference_vector_options(request.preference, request.number_of_vectors)
|
|
78
|
+
|
|
79
|
+
# Create solver and publisher
|
|
80
|
+
if request.method == "RVEA":
|
|
81
|
+
solver, publisher = rvea(problem=problem, reference_vector_options=reference_vector_options)
|
|
82
|
+
elif request.method == "NSGA3":
|
|
83
|
+
solver, publisher = nsga3(problem=problem, reference_vector_options=reference_vector_options)
|
|
84
|
+
else:
|
|
85
|
+
raise HTTPException(
|
|
86
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
87
|
+
detail=f"Unsupported method: {request.method}. Supported methods are 'NSGA3' and 'RVEA'.",
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Add archive if requested
|
|
91
|
+
archive = None
|
|
92
|
+
if request.use_archive:
|
|
93
|
+
archive = NonDominatedArchive(problem=problem, publisher=publisher)
|
|
94
|
+
publisher.auto_subscribe(archive)
|
|
95
|
+
|
|
96
|
+
# Run optimization
|
|
97
|
+
emo_results = solver()
|
|
98
|
+
|
|
99
|
+
# Convert DataFrames to dictionaries for solutions
|
|
100
|
+
solutions_dict = _convert_dataframe_to_dict_list(getattr(emo_results, "solutions", None))
|
|
101
|
+
|
|
102
|
+
# Convert DataFrames to dictionaries for outputs
|
|
103
|
+
outputs_dict = _convert_dataframe_to_dict_list(getattr(emo_results, "outputs", None))
|
|
104
|
+
|
|
105
|
+
# Create DB preference
|
|
106
|
+
preference_db = PreferenceDB(user_id=user.id, problem_id=problem_db.id, preference=request.preference)
|
|
107
|
+
|
|
108
|
+
session.add(preference_db)
|
|
109
|
+
session.commit()
|
|
110
|
+
session.refresh(preference_db)
|
|
111
|
+
|
|
112
|
+
# Handle parent state
|
|
113
|
+
if request.parent_state_id is None:
|
|
114
|
+
parent_state = (
|
|
115
|
+
interactive_session.states[-1]
|
|
116
|
+
if (interactive_session is not None and len(interactive_session.states) > 0)
|
|
117
|
+
else None
|
|
118
|
+
)
|
|
119
|
+
else:
|
|
120
|
+
statement = select(StateDB).where(StateDB.id == request.parent_state_id)
|
|
121
|
+
parent_state = session.exec(statement).first()
|
|
122
|
+
|
|
123
|
+
if parent_state is None:
|
|
124
|
+
raise HTTPException(
|
|
125
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
126
|
+
detail=f"Could not find state with id={request.parent_state_id}",
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Create EMO state
|
|
130
|
+
emo_state = EMOState(
|
|
131
|
+
method=request.method, # Use the method directly (already uppercase)
|
|
132
|
+
max_evaluations=request.max_evaluations,
|
|
133
|
+
number_of_vectors=request.number_of_vectors,
|
|
134
|
+
use_archive=request.use_archive,
|
|
135
|
+
solutions=solutions_dict,
|
|
136
|
+
outputs=outputs_dict,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Create DB state
|
|
140
|
+
state = StateDB(
|
|
141
|
+
problem_id=problem_db.id,
|
|
142
|
+
preference_id=preference_db.id,
|
|
143
|
+
session_id=interactive_session.id if interactive_session is not None else None,
|
|
144
|
+
parent_id=parent_state.id if parent_state is not None else None,
|
|
145
|
+
state=emo_state, # Convert to dict for JSON serialization
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
session.add(state)
|
|
149
|
+
session.commit()
|
|
150
|
+
session.refresh(state)
|
|
151
|
+
|
|
152
|
+
return emo_state
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@router.post("/save")
|
|
156
|
+
def save(
|
|
157
|
+
request: EMOSaveRequest,
|
|
158
|
+
user: Annotated[User, Depends(get_current_user)],
|
|
159
|
+
session: Annotated[Session, Depends(get_session)],
|
|
160
|
+
) -> EMOSaveState:
|
|
161
|
+
"""Save solutions."""
|
|
162
|
+
if request.session_id is not None:
|
|
163
|
+
statement = select(InteractiveSessionDB).where(InteractiveSessionDB.id == request.session_id)
|
|
164
|
+
interactive_session = session.exec(statement)
|
|
165
|
+
|
|
166
|
+
if interactive_session is None:
|
|
167
|
+
raise HTTPException(
|
|
168
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
169
|
+
detail=f"Could not find interactive session with id={request.session_id}.",
|
|
170
|
+
)
|
|
171
|
+
else:
|
|
172
|
+
# request.session_id is None:
|
|
173
|
+
# use active session instead
|
|
174
|
+
statement = select(InteractiveSessionDB).where(InteractiveSessionDB.id == user.active_session_id)
|
|
175
|
+
|
|
176
|
+
interactive_session = session.exec(statement).first()
|
|
177
|
+
|
|
178
|
+
# fetch parent state
|
|
179
|
+
if request.parent_state_id is None:
|
|
180
|
+
# parent state is assumed to be the last state added to the session.
|
|
181
|
+
parent_state = (
|
|
182
|
+
interactive_session.states[-1]
|
|
183
|
+
if (interactive_session is not None and len(interactive_session.states) > 0)
|
|
184
|
+
else None
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
else:
|
|
188
|
+
# request.parent_state_id is not None
|
|
189
|
+
statement = session.select(StateDB).where(StateDB.id == request.parent_state_id)
|
|
190
|
+
parent_state = session.exec(statement).first()
|
|
191
|
+
|
|
192
|
+
if parent_state is None:
|
|
193
|
+
raise HTTPException(
|
|
194
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
195
|
+
detail=f"Could not find state with id={request.parent_state_id}",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# save solver results for state in SolverResults format just for consistency (dont save name field to state)
|
|
199
|
+
# Get values from parent state if available, otherwise use defaults
|
|
200
|
+
max_evaluations = 1000
|
|
201
|
+
number_of_vectors = 20
|
|
202
|
+
use_archive = True
|
|
203
|
+
|
|
204
|
+
if parent_state is not None and isinstance(parent_state.state, EMOState):
|
|
205
|
+
max_evaluations = parent_state.state.max_evaluations
|
|
206
|
+
number_of_vectors = parent_state.state.number_of_vectors
|
|
207
|
+
use_archive = parent_state.state.use_archive
|
|
208
|
+
|
|
209
|
+
save_state = EMOSaveState(
|
|
210
|
+
method=(parent_state.state.method if parent_state else "EMO"), # Get from parent or default
|
|
211
|
+
max_evaluations=max_evaluations,
|
|
212
|
+
number_of_vectors=number_of_vectors,
|
|
213
|
+
use_archive=use_archive,
|
|
214
|
+
problem_id=request.problem_id,
|
|
215
|
+
saved_solutions=[solution.to_emo_results() for solution in request.solutions],
|
|
216
|
+
solutions=[solution.model_dump() for solution in request.solutions], # Original solutions from request
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
# create DB state
|
|
220
|
+
state = StateDB(
|
|
221
|
+
problem_id=request.problem_id,
|
|
222
|
+
session_id=interactive_session.id if interactive_session is not None else None,
|
|
223
|
+
parent_id=parent_state.id if parent_state is not None else None,
|
|
224
|
+
state=save_state,
|
|
225
|
+
)
|
|
226
|
+
# save solutions to the user's archive and add state to the DB
|
|
227
|
+
user_save_solutions(state, request.solutions, user.id, session)
|
|
228
|
+
|
|
229
|
+
return save_state
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@router.get("/saved-solutions")
|
|
233
|
+
def get_saved_solutions(
|
|
234
|
+
user: Annotated[User, Depends(get_current_user)],
|
|
235
|
+
session: Annotated[Session, Depends(get_session)],
|
|
236
|
+
):
|
|
237
|
+
"""Get all saved solutions for the current user."""
|
|
238
|
+
from desdeo.api.models.archive import UserSavedSolutionDB
|
|
239
|
+
|
|
240
|
+
# Query saved solutions for the current user
|
|
241
|
+
statement = select(UserSavedSolutionDB).where(UserSavedSolutionDB.user_id == user.id)
|
|
242
|
+
saved_solutions = session.exec(statement).all()
|
|
243
|
+
|
|
244
|
+
# Convert to response format
|
|
245
|
+
results = []
|
|
246
|
+
for solution in saved_solutions:
|
|
247
|
+
results.append(
|
|
248
|
+
{
|
|
249
|
+
"id": solution.id,
|
|
250
|
+
"name": solution.name,
|
|
251
|
+
"variable_values": solution.variable_values,
|
|
252
|
+
"objective_values": solution.objective_values,
|
|
253
|
+
"constraint_values": solution.constraint_values,
|
|
254
|
+
"extra_func_values": solution.extra_func_values,
|
|
255
|
+
"problem_id": solution.problem_id,
|
|
256
|
+
}
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
return results
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
# Helper functions
|
|
263
|
+
def _build_reference_vector_options(preference: PreferenceBase, number_of_vectors: int) -> Dict:
|
|
264
|
+
"""Build reference vector options based on preference type."""
|
|
265
|
+
|
|
266
|
+
base_options = {
|
|
267
|
+
"number_of_vectors": number_of_vectors,
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
# Convert the preference dict to the correct object type
|
|
271
|
+
if isinstance(preference, dict):
|
|
272
|
+
preference_type = preference.get("preference_type")
|
|
273
|
+
if preference_type == "reference_point":
|
|
274
|
+
from desdeo.api.models.preference import ReferencePoint
|
|
275
|
+
|
|
276
|
+
preference = ReferencePoint.model_validate(preference)
|
|
277
|
+
elif preference_type == "preferred_solutions":
|
|
278
|
+
from desdeo.api.models.preference import PreferredSolutions
|
|
279
|
+
|
|
280
|
+
preference = PreferredSolutions.model_validate(preference)
|
|
281
|
+
elif preference_type == "non_preferred_solutions":
|
|
282
|
+
from desdeo.api.models.preference import NonPreferredSolutions
|
|
283
|
+
|
|
284
|
+
preference = NonPreferredSolutions.model_validate(preference)
|
|
285
|
+
elif preference_type == "preferred_ranges":
|
|
286
|
+
from desdeo.api.models.preference import PreferredRanges
|
|
287
|
+
|
|
288
|
+
preference = PreferredRanges.model_validate(preference)
|
|
289
|
+
|
|
290
|
+
# Now handle the properly typed preference object
|
|
291
|
+
if hasattr(preference, "aspiration_levels"):
|
|
292
|
+
base_options["interactive_adaptation"] = "reference_point"
|
|
293
|
+
base_options["reference_point"] = preference.aspiration_levels
|
|
294
|
+
elif hasattr(preference, "preferred_solutions"):
|
|
295
|
+
base_options["interactive_adaptation"] = "preferred_solutions"
|
|
296
|
+
base_options["preferred_solutions"] = preference.preferred_solutions
|
|
297
|
+
elif hasattr(preference, "non_preferred_solutions"):
|
|
298
|
+
base_options["interactive_adaptation"] = "non_preferred_solutions"
|
|
299
|
+
base_options["non_preferred_solutions"] = preference.non_preferred_solutions
|
|
300
|
+
elif hasattr(preference, "preferred_ranges"):
|
|
301
|
+
base_options["interactive_adaptation"] = "preferred_ranges"
|
|
302
|
+
base_options["preferred_ranges"] = preference.preferred_ranges
|
|
303
|
+
else:
|
|
304
|
+
raise HTTPException(
|
|
305
|
+
status_code=400,
|
|
306
|
+
detail=f"Unsupported preference type: {type(preference)} with preference_type: {getattr(preference, 'preference_type', 'unknown')}",
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
return base_options
|
desdeo/api/routers/_NIMBUS.py
CHANGED
|
@@ -150,7 +150,10 @@ def init_nimbus(
|
|
|
150
150
|
|
|
151
151
|
# If there are no solutions, generate a starting point for NIMBUS
|
|
152
152
|
if not solutions:
|
|
153
|
-
start_result = generate_starting_point(
|
|
153
|
+
start_result = generate_starting_point(
|
|
154
|
+
problem=problem,
|
|
155
|
+
solver=available_solvers[solver]["constructor"] if solver else None
|
|
156
|
+
)
|
|
154
157
|
save_results_to_db(
|
|
155
158
|
db=db, user_id=user.index, request=init_request, results=[start_result], previous_solutions=solutions
|
|
156
159
|
)
|
|
@@ -214,7 +217,7 @@ def iterate(
|
|
|
214
217
|
),
|
|
215
218
|
reference_point=dict(zip([obj.symbol for obj in problem.objectives], request.preference, strict=True)),
|
|
216
219
|
num_desired=request.num_solutions,
|
|
217
|
-
solver=available_solvers[solver] if solver else None,
|
|
220
|
+
solver=available_solvers[solver]["constructor"] if solver else None,
|
|
218
221
|
scalarization_options={"rho": 0.001, "delta": 0.001},
|
|
219
222
|
)
|
|
220
223
|
|
|
@@ -277,7 +280,7 @@ def intermediate(
|
|
|
277
280
|
solution_1=dict(zip(problem.objectives, request.reference_solution_1, strict=True)),
|
|
278
281
|
solution_2=dict(zip(problem.objectives, request.reference_solution_2, strict=True)),
|
|
279
282
|
num_desired=request.num_solutions,
|
|
280
|
-
solver=available_solvers[solver] if solver else None,
|
|
283
|
+
solver=available_solvers[solver]["constructor"] if solver else None,
|
|
281
284
|
)
|
|
282
285
|
|
|
283
286
|
# Do database stuff again.
|