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
desdeo/api/tests/test_models.py
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
"""Tests related to the SQLModels."""
|
|
2
2
|
|
|
3
|
+
import numpy as np
|
|
3
4
|
from sqlmodel import Session, select
|
|
4
5
|
|
|
5
6
|
from desdeo.api.models import (
|
|
6
|
-
ArchiveEntryBase,
|
|
7
|
-
ArchiveEntryDB,
|
|
8
7
|
Bounds,
|
|
9
8
|
ConstantDB,
|
|
10
9
|
ConstraintDB,
|
|
11
10
|
DiscreteRepresentationDB,
|
|
11
|
+
ENautilusState,
|
|
12
12
|
ExtraFunctionDB,
|
|
13
|
+
ForestProblemMetaData,
|
|
14
|
+
Group,
|
|
15
|
+
GroupIteration,
|
|
13
16
|
InteractiveSessionDB,
|
|
17
|
+
NIMBUSClassificationState,
|
|
18
|
+
NIMBUSFinalState,
|
|
19
|
+
NIMBUSInitializationState,
|
|
20
|
+
NIMBUSSaveState,
|
|
14
21
|
ObjectiveDB,
|
|
15
22
|
PreferenceDB,
|
|
16
23
|
ProblemDB,
|
|
24
|
+
ProblemMetaDataDB,
|
|
17
25
|
ReferencePoint,
|
|
26
|
+
RepresentativeNonDominatedSolutions,
|
|
18
27
|
RPMState,
|
|
19
28
|
ScalarizationFunctionDB,
|
|
20
29
|
SimulatorDB,
|
|
@@ -22,9 +31,13 @@ from desdeo.api.models import (
|
|
|
22
31
|
TensorConstantDB,
|
|
23
32
|
TensorVariableDB,
|
|
24
33
|
User,
|
|
34
|
+
UserSavedSolutionDB,
|
|
25
35
|
VariableDB,
|
|
26
36
|
)
|
|
27
|
-
from desdeo.
|
|
37
|
+
from desdeo.api.models.gdm.gnimbus import (
|
|
38
|
+
OptimizationPreference,
|
|
39
|
+
)
|
|
40
|
+
from desdeo.mcdm import enautilus_step, generate_starting_point, rpm_solve_solutions, solve_sub_problems
|
|
28
41
|
from desdeo.problem.schema import (
|
|
29
42
|
Constant,
|
|
30
43
|
Constraint,
|
|
@@ -46,6 +59,7 @@ from desdeo.problem.testproblems import (
|
|
|
46
59
|
dtlz2,
|
|
47
60
|
momip_ti2,
|
|
48
61
|
momip_ti7,
|
|
62
|
+
multi_valued_constraint_problem,
|
|
49
63
|
nimbus_test_problem,
|
|
50
64
|
pareto_navigator_test_problem,
|
|
51
65
|
re21,
|
|
@@ -63,7 +77,7 @@ from desdeo.problem.testproblems import (
|
|
|
63
77
|
spanish_sustainability_problem,
|
|
64
78
|
zdt1,
|
|
65
79
|
)
|
|
66
|
-
from desdeo.tools import available_solvers
|
|
80
|
+
from desdeo.tools import PyomoBonminSolver, available_solvers
|
|
67
81
|
|
|
68
82
|
|
|
69
83
|
def compare_models(
|
|
@@ -135,7 +149,7 @@ def test_tensor_constant(session_and_user: dict[str, Session | list[User]]):
|
|
|
135
149
|
# check that original added TensorConstant and fetched match
|
|
136
150
|
assert db_tensor == from_db_tensor
|
|
137
151
|
|
|
138
|
-
from_db_tensor_dump = from_db_tensor.model_dump()
|
|
152
|
+
from_db_tensor_dump = from_db_tensor.model_dump(exclude={"id", "problem_id"})
|
|
139
153
|
t_tensor_validated = TensorConstant.model_validate(from_db_tensor_dump)
|
|
140
154
|
|
|
141
155
|
assert t_tensor_validated == t_tensor
|
|
@@ -159,7 +173,7 @@ def test_constant(session_and_user: dict[str, Session | list[User]]):
|
|
|
159
173
|
|
|
160
174
|
assert db_constant == from_db_constant
|
|
161
175
|
|
|
162
|
-
from_db_constant_dump = from_db_constant.model_dump()
|
|
176
|
+
from_db_constant_dump = from_db_constant.model_dump(exclude={"id", "problem_id"})
|
|
163
177
|
constant_validated = Constant.model_validate(from_db_constant_dump)
|
|
164
178
|
|
|
165
179
|
assert constant_validated == constant
|
|
@@ -191,7 +205,7 @@ def test_variable(session_and_user: dict[str, Session | list[User]]):
|
|
|
191
205
|
|
|
192
206
|
assert db_variable == from_db_variable
|
|
193
207
|
|
|
194
|
-
from_db_variable_dump = from_db_variable.model_dump()
|
|
208
|
+
from_db_variable_dump = from_db_variable.model_dump(exclude={"id", "problem_id"})
|
|
195
209
|
variable_validated = Variable.model_validate(from_db_variable_dump)
|
|
196
210
|
|
|
197
211
|
assert variable_validated == variable
|
|
@@ -224,7 +238,7 @@ def test_tensor_variable(session_and_user: dict[str, Session | list[User]]):
|
|
|
224
238
|
|
|
225
239
|
assert db_t_variable == from_db_t_variable
|
|
226
240
|
|
|
227
|
-
from_db_t_variable_dump = from_db_t_variable.model_dump()
|
|
241
|
+
from_db_t_variable_dump = from_db_t_variable.model_dump(exclude={"id", "problem_id"})
|
|
228
242
|
t_variable_validated = TensorVariable.model_validate(from_db_t_variable_dump)
|
|
229
243
|
|
|
230
244
|
assert t_variable_validated == t_variable
|
|
@@ -264,7 +278,7 @@ def test_objective(session_and_user: dict[str, Session | list[User]]):
|
|
|
264
278
|
|
|
265
279
|
assert db_objective == from_db_objective
|
|
266
280
|
|
|
267
|
-
from_db_objective_dump = from_db_objective.model_dump()
|
|
281
|
+
from_db_objective_dump = from_db_objective.model_dump(exclude={"id", "problem_id"})
|
|
268
282
|
objective_validated = Objective.model_validate(from_db_objective_dump)
|
|
269
283
|
|
|
270
284
|
assert objective_validated == objective
|
|
@@ -300,7 +314,7 @@ def test_constraint(session_and_user: dict[str, Session | list[User]]):
|
|
|
300
314
|
|
|
301
315
|
assert db_constraint == from_db_constraint
|
|
302
316
|
|
|
303
|
-
from_db_constraint_dump = from_db_constraint.model_dump()
|
|
317
|
+
from_db_constraint_dump = from_db_constraint.model_dump(exclude={"id", "problem_id"})
|
|
304
318
|
constraint_validated = Constraint.model_validate(from_db_constraint_dump)
|
|
305
319
|
|
|
306
320
|
assert constraint_validated == constraint
|
|
@@ -333,7 +347,7 @@ def test_scalarization_function(session_and_user: dict[str, Session | list[User]
|
|
|
333
347
|
|
|
334
348
|
assert db_scalarization == from_db_scalarization
|
|
335
349
|
|
|
336
|
-
from_db_scalarization_dump = from_db_scalarization.model_dump()
|
|
350
|
+
from_db_scalarization_dump = from_db_scalarization.model_dump(exclude={"id", "problem_id"})
|
|
337
351
|
scalarization_validated = ScalarizationFunction.model_validate(from_db_scalarization_dump)
|
|
338
352
|
|
|
339
353
|
assert scalarization_validated == scalarization
|
|
@@ -366,7 +380,7 @@ def test_extra_function(session_and_user: dict[str, Session | list[User]]):
|
|
|
366
380
|
|
|
367
381
|
assert db_extra == from_db_extra
|
|
368
382
|
|
|
369
|
-
from_db_extra_dump = from_db_extra.model_dump()
|
|
383
|
+
from_db_extra_dump = from_db_extra.model_dump(exclude={"id", "problem_id"})
|
|
370
384
|
extra_validated = ExtraFunction.model_validate(from_db_extra_dump)
|
|
371
385
|
|
|
372
386
|
assert extra_validated == extra
|
|
@@ -395,7 +409,7 @@ def test_discrete_representation(session_and_user: dict[str, Session | list[User
|
|
|
395
409
|
|
|
396
410
|
assert db_discrete == from_db_discrete
|
|
397
411
|
|
|
398
|
-
from_db_discrete_dump = from_db_discrete.model_dump()
|
|
412
|
+
from_db_discrete_dump = from_db_discrete.model_dump(exclude={"id", "problem_id"})
|
|
399
413
|
discrete_validated = DiscreteRepresentation.model_validate(from_db_discrete_dump)
|
|
400
414
|
|
|
401
415
|
assert discrete_validated == discrete
|
|
@@ -425,7 +439,7 @@ def test_simulator(session_and_user: dict[str, Session | list[User]]):
|
|
|
425
439
|
|
|
426
440
|
assert db_simulator == from_db_simulator
|
|
427
441
|
|
|
428
|
-
from_db_simulator_dump = from_db_simulator.model_dump()
|
|
442
|
+
from_db_simulator_dump = from_db_simulator.model_dump(exclude={"id", "problem_id"})
|
|
429
443
|
simulator_validated = Simulator.model_validate(from_db_simulator_dump)
|
|
430
444
|
|
|
431
445
|
assert simulator_validated == simulator
|
|
@@ -464,6 +478,7 @@ def test_from_problem_to_d_and_back(session_and_user: dict[str, Session | list[U
|
|
|
464
478
|
spanish_sustainability_problem(),
|
|
465
479
|
zdt1(10),
|
|
466
480
|
dtlz2(5, 3),
|
|
481
|
+
multi_valued_constraint_problem(),
|
|
467
482
|
momip_ti2(),
|
|
468
483
|
momip_ti7(),
|
|
469
484
|
nimbus_test_problem(),
|
|
@@ -493,49 +508,84 @@ def test_from_problem_to_d_and_back(session_and_user: dict[str, Session | list[U
|
|
|
493
508
|
assert compare_models(problem, problem_db)
|
|
494
509
|
|
|
495
510
|
|
|
496
|
-
def
|
|
497
|
-
"""Test that the
|
|
511
|
+
def test_user_save_solutions(session_and_user: dict[str, Session | list[User]]):
|
|
512
|
+
"""Test that user_save_solutions correctly saves solutions to the usersavedsolutiondb in the database."""
|
|
498
513
|
session = session_and_user["session"]
|
|
499
514
|
user = session_and_user["user"]
|
|
500
515
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
516
|
+
# Create test solutions with proper dictionary values
|
|
517
|
+
objective_values = {"f_1": 1.2, "f_2": 0.9}
|
|
518
|
+
variable_values = {"x_1": 5.2, "x_2": 8.0, "x_3": -4.2}
|
|
519
|
+
|
|
520
|
+
user_id = user.id
|
|
521
|
+
problem_id = 1
|
|
522
|
+
|
|
523
|
+
test_solutions = [
|
|
524
|
+
UserSavedSolutionDB(
|
|
525
|
+
name="Solution 1",
|
|
526
|
+
objective_values=objective_values,
|
|
527
|
+
variable_values=variable_values,
|
|
528
|
+
user_id=user_id,
|
|
529
|
+
problem_id=problem_id,
|
|
530
|
+
origin_state_id=1,
|
|
531
|
+
),
|
|
532
|
+
UserSavedSolutionDB(
|
|
533
|
+
name="Solution 2",
|
|
534
|
+
objective_values=objective_values,
|
|
535
|
+
variable_values=variable_values,
|
|
536
|
+
solution_index=2,
|
|
537
|
+
user_id=user_id,
|
|
538
|
+
problem_id=problem_id,
|
|
539
|
+
origin_state_id=2,
|
|
540
|
+
),
|
|
541
|
+
]
|
|
507
542
|
|
|
508
|
-
|
|
509
|
-
objective_values = {"f_1": 1.2, "f_2": 0.9, "f_3": 1.5}
|
|
510
|
-
constraint_values = {"g_1": 0.1}
|
|
511
|
-
extra_func_values = {"extra_1": 5000, "extra_2": 600000}
|
|
543
|
+
num_test_solutions = len(test_solutions)
|
|
512
544
|
|
|
513
|
-
|
|
545
|
+
# Create NIMBUSSaveState
|
|
546
|
+
save_state = NIMBUSSaveState(solutions=test_solutions)
|
|
514
547
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
update={
|
|
518
|
-
"user_id": user.id,
|
|
519
|
-
"problem_id": problem_db.id,
|
|
520
|
-
"constraint_values": constraint_values,
|
|
521
|
-
"extra_func_values": extra_func_values,
|
|
522
|
-
},
|
|
523
|
-
)
|
|
548
|
+
# Create StateDB with NIMBUSSaveState
|
|
549
|
+
state_db = StateDB.create(session, problem_id=problem_id, state=save_state)
|
|
524
550
|
|
|
525
|
-
session.add(
|
|
551
|
+
session.add(state_db)
|
|
526
552
|
session.commit()
|
|
527
|
-
session.refresh(
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
assert
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
assert
|
|
536
|
-
assert
|
|
537
|
-
assert
|
|
538
|
-
assert
|
|
553
|
+
session.refresh(state_db)
|
|
554
|
+
|
|
555
|
+
# Verify the solutions were saved
|
|
556
|
+
saved_solutions = session.exec(select(UserSavedSolutionDB)).all()
|
|
557
|
+
assert len(saved_solutions) == num_test_solutions
|
|
558
|
+
|
|
559
|
+
# Verify the content of the first solution
|
|
560
|
+
first_solution = saved_solutions[0]
|
|
561
|
+
assert first_solution.name == "Solution 1"
|
|
562
|
+
assert first_solution.objective_values == objective_values
|
|
563
|
+
assert first_solution.variable_values == variable_values
|
|
564
|
+
assert first_solution.origin_state_id == 1
|
|
565
|
+
assert first_solution.solution_index is None
|
|
566
|
+
assert first_solution.user_id == user.id
|
|
567
|
+
assert first_solution.problem_id == problem_id
|
|
568
|
+
|
|
569
|
+
# Verify the content of the second solution
|
|
570
|
+
second_solution = saved_solutions[1]
|
|
571
|
+
assert second_solution.name == "Solution 2"
|
|
572
|
+
assert second_solution.objective_values == objective_values
|
|
573
|
+
assert second_solution.variable_values == variable_values
|
|
574
|
+
assert second_solution.origin_state_id == 2
|
|
575
|
+
assert second_solution.solution_index == 2
|
|
576
|
+
assert second_solution.user_id == user.id
|
|
577
|
+
assert second_solution.problem_id == problem_id
|
|
578
|
+
|
|
579
|
+
# Verify state relationship
|
|
580
|
+
saved_state = session.exec(select(StateDB).where(StateDB.id == state_db.id)).first()
|
|
581
|
+
assert isinstance(saved_state.state, NIMBUSSaveState)
|
|
582
|
+
assert len(saved_state.state.solutions) == num_test_solutions
|
|
583
|
+
|
|
584
|
+
# Check that relationships are formed
|
|
585
|
+
session.refresh(user)
|
|
586
|
+
|
|
587
|
+
assert len(user.archive) == len(test_solutions)
|
|
588
|
+
assert len(session.get(ProblemDB, problem_id).solutions) == len(test_solutions)
|
|
539
589
|
|
|
540
590
|
|
|
541
591
|
def test_preference_models(session_and_user: dict[str, Session | list[User]]):
|
|
@@ -579,9 +629,6 @@ def test_preference_models(session_and_user: dict[str, Session | list[User]]):
|
|
|
579
629
|
assert from_db_bounds.user == user
|
|
580
630
|
assert from_db_ref_point.user == user
|
|
581
631
|
|
|
582
|
-
assert from_db_bounds.solutions == []
|
|
583
|
-
assert from_db_ref_point.solutions == []
|
|
584
|
-
|
|
585
632
|
|
|
586
633
|
def test_rpm_state(session_and_user: dict[str, Session | list[User]]):
|
|
587
634
|
"""Test the RPM state that it works correctly."""
|
|
@@ -609,30 +656,26 @@ def test_rpm_state(session_and_user: dict[str, Session | list[User]]):
|
|
|
609
656
|
problem,
|
|
610
657
|
asp_levels_1,
|
|
611
658
|
scalarization_options=scalarization_options,
|
|
612
|
-
solver=available_solvers[solver],
|
|
659
|
+
solver=available_solvers[solver]["constructor"],
|
|
613
660
|
solver_options=solver_options,
|
|
614
661
|
)
|
|
615
662
|
|
|
616
663
|
# create preferences
|
|
617
664
|
|
|
618
665
|
rp_1 = ReferencePoint(aspiration_levels=asp_levels_1)
|
|
619
|
-
preferences = PreferenceDB(user_id=user.id, problem_id=problem_db.id, preference=rp_1)
|
|
620
|
-
|
|
621
|
-
session.add(preferences)
|
|
622
|
-
session.commit()
|
|
623
|
-
session.refresh(preferences)
|
|
624
666
|
|
|
625
667
|
# create state
|
|
626
668
|
|
|
627
669
|
rpm_state = RPMState(
|
|
670
|
+
preferences=rp_1,
|
|
628
671
|
scalarization_options=scalarization_options,
|
|
629
672
|
solver=solver,
|
|
630
673
|
solver_options=solver_options,
|
|
631
674
|
solver_results=results,
|
|
632
675
|
)
|
|
633
676
|
|
|
634
|
-
state_1 = StateDB(
|
|
635
|
-
|
|
677
|
+
state_1 = StateDB.create(
|
|
678
|
+
database_session=session, problem_id=problem_db.id, session_id=isession.id, state=rpm_state
|
|
636
679
|
)
|
|
637
680
|
|
|
638
681
|
session.add(state_1)
|
|
@@ -641,8 +684,6 @@ def test_rpm_state(session_and_user: dict[str, Session | list[User]]):
|
|
|
641
684
|
|
|
642
685
|
asp_levels_2 = {"f_1": 0.6, "f_2": 0.4, "f_3": 0.5}
|
|
643
686
|
|
|
644
|
-
problem = Problem.from_problemdb(problem_db)
|
|
645
|
-
|
|
646
687
|
scalarization_options = None
|
|
647
688
|
solver = "pyomo_bonmin"
|
|
648
689
|
solver_options = None
|
|
@@ -651,31 +692,36 @@ def test_rpm_state(session_and_user: dict[str, Session | list[User]]):
|
|
|
651
692
|
problem,
|
|
652
693
|
asp_levels_2,
|
|
653
694
|
scalarization_options=scalarization_options,
|
|
654
|
-
solver=available_solvers[solver],
|
|
695
|
+
solver=available_solvers[solver]["constructor"],
|
|
696
|
+
solver_options=solver_options,
|
|
697
|
+
)
|
|
698
|
+
|
|
699
|
+
# create state
|
|
700
|
+
|
|
701
|
+
rpm_state = RPMState(
|
|
702
|
+
scalarization_options=scalarization_options,
|
|
703
|
+
solver=solver,
|
|
655
704
|
solver_options=solver_options,
|
|
705
|
+
solver_results=results,
|
|
656
706
|
)
|
|
657
707
|
|
|
658
708
|
# create preferences
|
|
659
709
|
|
|
660
710
|
rp_2 = ReferencePoint(aspiration_levels=asp_levels_2)
|
|
661
|
-
preferences = PreferenceDB(user_id=user.id, problem_id=problem_db.id, preference=rp_2)
|
|
662
|
-
|
|
663
|
-
session.add(preferences)
|
|
664
|
-
session.commit()
|
|
665
|
-
session.refresh(preferences)
|
|
666
711
|
|
|
667
712
|
# create state
|
|
668
713
|
|
|
669
714
|
rpm_state = RPMState(
|
|
715
|
+
preferences=rp_2,
|
|
670
716
|
scalarization_options=scalarization_options,
|
|
671
717
|
solver=solver,
|
|
672
718
|
solver_options=solver_options,
|
|
673
719
|
solver_results=results,
|
|
674
720
|
)
|
|
675
721
|
|
|
676
|
-
state_2 = StateDB(
|
|
722
|
+
state_2 = StateDB.create(
|
|
723
|
+
database_session=session,
|
|
677
724
|
problem_id=problem_db.id,
|
|
678
|
-
preference_id=preferences.id,
|
|
679
725
|
session_id=isession.id,
|
|
680
726
|
parent_id=state_1.id,
|
|
681
727
|
state=rpm_state,
|
|
@@ -690,8 +736,8 @@ def test_rpm_state(session_and_user: dict[str, Session | list[User]]):
|
|
|
690
736
|
assert len(state_1.children) == 1
|
|
691
737
|
assert state_1.children[0] == state_2
|
|
692
738
|
|
|
693
|
-
assert state_1.
|
|
694
|
-
assert state_2.
|
|
739
|
+
assert state_1.state.preferences == rp_1
|
|
740
|
+
assert state_2.state.preferences == rp_2
|
|
695
741
|
|
|
696
742
|
assert state_2.problem == problem_db
|
|
697
743
|
assert state_2.session.user == user
|
|
@@ -699,3 +745,435 @@ def test_rpm_state(session_and_user: dict[str, Session | list[User]]):
|
|
|
699
745
|
assert state_2.children == []
|
|
700
746
|
assert state_2.parent.problem == problem_db
|
|
701
747
|
assert state_2.parent.session.user == user
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
def test_problem_metadata(session_and_user: dict[str, Session | list[User]]):
|
|
751
|
+
"""Test that the problem metadata can be put into database and brought back."""
|
|
752
|
+
session = session_and_user["session"]
|
|
753
|
+
user = session_and_user["user"]
|
|
754
|
+
|
|
755
|
+
# Just some test problem to attach the metadata to
|
|
756
|
+
problem = ProblemDB.from_problem(dtlz2(5, 3), user=user)
|
|
757
|
+
|
|
758
|
+
session.add(problem)
|
|
759
|
+
session.commit()
|
|
760
|
+
session.refresh(problem)
|
|
761
|
+
|
|
762
|
+
representative_name = "Test solutions"
|
|
763
|
+
representative_description = "These solutions are used for testing"
|
|
764
|
+
representative_variables = {"x_1": [1.1, 2.2, 3.3], "x_2": [-1.1, -2.2, -3.3]}
|
|
765
|
+
representative_objectives = {"f_1": [0.1, 0.5, 0.9], "f_2": [-0.1, 0.2, 199.2], "f_1_min": [], "f_2_min": []}
|
|
766
|
+
solution_data = representative_variables | representative_objectives
|
|
767
|
+
representative_ideal = {"f_1": 0.1, "f_2": -0.1}
|
|
768
|
+
representative_nadir = {"f_1": 0.9, "f_2": 199.2}
|
|
769
|
+
|
|
770
|
+
metadata = ProblemMetaDataDB(
|
|
771
|
+
problem_id=problem.id,
|
|
772
|
+
)
|
|
773
|
+
|
|
774
|
+
session.add(metadata)
|
|
775
|
+
session.commit()
|
|
776
|
+
session.refresh(metadata)
|
|
777
|
+
|
|
778
|
+
forest_metadata = ForestProblemMetaData(
|
|
779
|
+
metadata_id=metadata.id,
|
|
780
|
+
map_json="type: string",
|
|
781
|
+
schedule_dict={"type": "dict"},
|
|
782
|
+
years=["type:", "list", "of", "strings"],
|
|
783
|
+
stand_id_field="type: string",
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
repr_metadata = RepresentativeNonDominatedSolutions(
|
|
787
|
+
metadata_id=metadata.id,
|
|
788
|
+
name=representative_name,
|
|
789
|
+
description=representative_description,
|
|
790
|
+
solution_data=solution_data,
|
|
791
|
+
ideal=representative_ideal,
|
|
792
|
+
nadir=representative_nadir,
|
|
793
|
+
)
|
|
794
|
+
|
|
795
|
+
session.add(forest_metadata)
|
|
796
|
+
session.add(repr_metadata)
|
|
797
|
+
session.commit()
|
|
798
|
+
session.refresh(forest_metadata)
|
|
799
|
+
session.refresh(repr_metadata)
|
|
800
|
+
|
|
801
|
+
statement = select(ProblemMetaDataDB).where(ProblemMetaDataDB.problem_id == problem.id)
|
|
802
|
+
from_db_metadata = session.exec(statement).first()
|
|
803
|
+
|
|
804
|
+
assert from_db_metadata.id is not None
|
|
805
|
+
assert from_db_metadata.problem_id == problem.id
|
|
806
|
+
|
|
807
|
+
metadata_forest = from_db_metadata.forest_metadata[0]
|
|
808
|
+
|
|
809
|
+
assert isinstance(metadata_forest, ForestProblemMetaData)
|
|
810
|
+
assert metadata_forest.map_json == "type: string"
|
|
811
|
+
assert metadata_forest.schedule_dict == {"type": "dict"}
|
|
812
|
+
assert metadata_forest.years == ["type:", "list", "of", "strings"]
|
|
813
|
+
assert metadata_forest.stand_id_field == "type: string"
|
|
814
|
+
|
|
815
|
+
metadata_representative = from_db_metadata.representative_nd_metadata[0]
|
|
816
|
+
|
|
817
|
+
assert isinstance(metadata_representative, RepresentativeNonDominatedSolutions)
|
|
818
|
+
assert metadata_representative.name == representative_name
|
|
819
|
+
assert metadata_representative.solution_data == solution_data
|
|
820
|
+
assert metadata_representative.ideal == representative_ideal
|
|
821
|
+
assert metadata_representative.nadir == representative_nadir
|
|
822
|
+
|
|
823
|
+
assert problem.problem_metadata == from_db_metadata
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
def test_group(session_and_user: dict[str, Session | list[User]]):
|
|
827
|
+
"""なに?!ちょっとまって。。。ドクメンタはどこですか???"""
|
|
828
|
+
session: Session = session_and_user["session"]
|
|
829
|
+
user: User = session_and_user["user"]
|
|
830
|
+
|
|
831
|
+
group = Group(
|
|
832
|
+
name="TestGroup",
|
|
833
|
+
owner_id=user.id,
|
|
834
|
+
user_ids=[user.id],
|
|
835
|
+
problem_id=1,
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
session.add(group)
|
|
839
|
+
session.commit()
|
|
840
|
+
session.refresh(group)
|
|
841
|
+
|
|
842
|
+
assert group.id == 1
|
|
843
|
+
assert group.user_ids[0] == user.id
|
|
844
|
+
assert group.name == "TestGroup"
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
def test_gnimbus_datas(session_and_user: dict[str, Session | list[User]]):
|
|
848
|
+
session: Session = session_and_user["session"]
|
|
849
|
+
user: User = session_and_user["user"]
|
|
850
|
+
|
|
851
|
+
group = Group(
|
|
852
|
+
name="TestGroup",
|
|
853
|
+
owner_id=user.id,
|
|
854
|
+
user_ids=[user.id],
|
|
855
|
+
problem_id=1,
|
|
856
|
+
)
|
|
857
|
+
|
|
858
|
+
session.add(group)
|
|
859
|
+
session.commit()
|
|
860
|
+
session.refresh(group)
|
|
861
|
+
|
|
862
|
+
giter = GroupIteration(
|
|
863
|
+
problem_id=1,
|
|
864
|
+
group_id=group.id,
|
|
865
|
+
info_container=OptimizationPreference(
|
|
866
|
+
set_preferences={},
|
|
867
|
+
),
|
|
868
|
+
notified={},
|
|
869
|
+
parent_id=None,
|
|
870
|
+
parent=None,
|
|
871
|
+
child=None,
|
|
872
|
+
)
|
|
873
|
+
session.add(giter)
|
|
874
|
+
session.commit()
|
|
875
|
+
session.refresh(giter)
|
|
876
|
+
|
|
877
|
+
assert type(giter.info_container) is OptimizationPreference
|
|
878
|
+
assert giter.problem_id == 1
|
|
879
|
+
assert giter.group_id == group.id
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
def test_enautilus_state(session_and_user: dict[str, Session | list[User]]):
|
|
883
|
+
"""Test the E-NAUTILUS state that it works correctly."""
|
|
884
|
+
session = session_and_user["session"]
|
|
885
|
+
user = session_and_user["user"]
|
|
886
|
+
|
|
887
|
+
# create interactive session
|
|
888
|
+
isession = InteractiveSessionDB(user_id=user.id)
|
|
889
|
+
|
|
890
|
+
session.add(isession)
|
|
891
|
+
session.commit()
|
|
892
|
+
session.refresh(isession)
|
|
893
|
+
|
|
894
|
+
# use dummy problem
|
|
895
|
+
dummy_problem = Problem(
|
|
896
|
+
name="Synthetic-4D",
|
|
897
|
+
description="Unit-test Problem for E-NAUTILUS",
|
|
898
|
+
variables=[Variable(name="x", symbol="x", variable_type=VariableTypeEnum.real)],
|
|
899
|
+
objectives=[
|
|
900
|
+
Objective(name="f1", symbol="f1", maximize=False),
|
|
901
|
+
Objective(name="f2", symbol="f2", maximize=True),
|
|
902
|
+
Objective(name="f3", symbol="f3", maximize=False),
|
|
903
|
+
Objective(name="f4", symbol="f4", maximize=True),
|
|
904
|
+
],
|
|
905
|
+
)
|
|
906
|
+
|
|
907
|
+
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
|
|
908
|
+
f1 = np.array([0.40, 0.60, 0.50, 0.70, 0.45, 0.55, 0.65, 0.48])
|
|
909
|
+
f2 = np.array([4.00, 3.80, 4.10, 3.70, 4.05, 3.90, 3.60, 4.20])
|
|
910
|
+
f3 = np.array([1.00, 1.30, 1.10, 1.40, 1.05, 1.20, 1.35, 1.15])
|
|
911
|
+
f4 = np.array([2.50, 2.30, 2.60, 2.20, 2.55, 2.40, 2.10, 2.65])
|
|
912
|
+
|
|
913
|
+
nadir = {"f1": np.max(f1), "f2": np.min(f2), "f3": np.max(f3), "f4": np.min(f4)}
|
|
914
|
+
ideal = {"f1": np.min(f1), "f2": np.max(f2), "f3": np.min(f3), "f4": np.max(f4)}
|
|
915
|
+
|
|
916
|
+
non_dom_data = {
|
|
917
|
+
"x": x.tolist(),
|
|
918
|
+
"f1": f1.tolist(),
|
|
919
|
+
"f1_min": f1.tolist(),
|
|
920
|
+
"f2": f2.tolist(),
|
|
921
|
+
"f2_min": (-f2).tolist(),
|
|
922
|
+
"f3": f3.tolist(),
|
|
923
|
+
"f3_min": f3.tolist(),
|
|
924
|
+
"f4": f4.tolist(),
|
|
925
|
+
"f4_min": (-f4).tolist(),
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
# add problem to DB and refresh it
|
|
929
|
+
problemdb = ProblemDB.from_problem(dummy_problem, user)
|
|
930
|
+
|
|
931
|
+
session.add(problemdb)
|
|
932
|
+
session.commit()
|
|
933
|
+
session.refresh(problemdb)
|
|
934
|
+
|
|
935
|
+
metadata = ProblemMetaDataDB(
|
|
936
|
+
problem_id=problemdb.id,
|
|
937
|
+
)
|
|
938
|
+
|
|
939
|
+
# add metadata to DB
|
|
940
|
+
session.add(metadata)
|
|
941
|
+
session.commit()
|
|
942
|
+
session.refresh(metadata)
|
|
943
|
+
|
|
944
|
+
reprdata = RepresentativeNonDominatedSolutions(
|
|
945
|
+
metadata_id=metadata.id,
|
|
946
|
+
name="Dummy data",
|
|
947
|
+
description="Dummy data for a problem",
|
|
948
|
+
solution_data=non_dom_data,
|
|
949
|
+
ideal=ideal,
|
|
950
|
+
nadir=nadir,
|
|
951
|
+
)
|
|
952
|
+
|
|
953
|
+
# add reprdata to DB
|
|
954
|
+
session.add(reprdata)
|
|
955
|
+
session.commit()
|
|
956
|
+
session.refresh(reprdata)
|
|
957
|
+
|
|
958
|
+
# test the nautilus step state
|
|
959
|
+
# first iteration
|
|
960
|
+
selected_point = nadir
|
|
961
|
+
reachable_indices = list(range(len(x))) # entire front reachable
|
|
962
|
+
|
|
963
|
+
total_iters = 2 # DM first thinks 2 iterations are enough
|
|
964
|
+
n_points = 3 # DM wants to see 3 points at first
|
|
965
|
+
current = 0
|
|
966
|
+
|
|
967
|
+
# First iteration
|
|
968
|
+
res = enautilus_step(
|
|
969
|
+
problem=dummy_problem,
|
|
970
|
+
non_dominated_points=non_dom_data,
|
|
971
|
+
current_iteration=current,
|
|
972
|
+
iterations_left=total_iters - current,
|
|
973
|
+
selected_point=selected_point,
|
|
974
|
+
reachable_point_indices=reachable_indices,
|
|
975
|
+
number_of_intermediate_points=n_points,
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
enautilus_state = ENautilusState(
|
|
979
|
+
non_dominated_solutions_id=reprdata.id,
|
|
980
|
+
current_iteration=current,
|
|
981
|
+
iterations_left=total_iters - current,
|
|
982
|
+
selected_point=selected_point,
|
|
983
|
+
reachable_point_indices=reachable_indices,
|
|
984
|
+
number_of_intermediate_points=n_points,
|
|
985
|
+
enautilus_results=res,
|
|
986
|
+
)
|
|
987
|
+
|
|
988
|
+
state_1 = StateDB.create(
|
|
989
|
+
database_session=session,
|
|
990
|
+
problem_id=problemdb.id,
|
|
991
|
+
session_id=isession.id,
|
|
992
|
+
parent_id=None,
|
|
993
|
+
state=enautilus_state,
|
|
994
|
+
)
|
|
995
|
+
|
|
996
|
+
session.add(state_1)
|
|
997
|
+
session.commit()
|
|
998
|
+
session.refresh(state_1)
|
|
999
|
+
|
|
1000
|
+
# Second iteration
|
|
1001
|
+
res_2 = enautilus_step(
|
|
1002
|
+
problem=dummy_problem,
|
|
1003
|
+
non_dominated_points=non_dom_data,
|
|
1004
|
+
current_iteration=res.current_iteration,
|
|
1005
|
+
iterations_left=res.iterations_left,
|
|
1006
|
+
selected_point=res.intermediate_points[0],
|
|
1007
|
+
reachable_point_indices=res.reachable_point_indices[0],
|
|
1008
|
+
number_of_intermediate_points=n_points,
|
|
1009
|
+
)
|
|
1010
|
+
|
|
1011
|
+
enautilus_state_2 = ENautilusState(
|
|
1012
|
+
non_dominated_solutions_id=reprdata.id,
|
|
1013
|
+
current_iteration=res.current_iteration,
|
|
1014
|
+
iterations_left=res.iterations_left,
|
|
1015
|
+
selected_point=res.intermediate_points[0],
|
|
1016
|
+
reachable_point_indices=res.reachable_point_indices[0],
|
|
1017
|
+
number_of_intermediate_points=n_points,
|
|
1018
|
+
enautilus_results=res_2,
|
|
1019
|
+
)
|
|
1020
|
+
|
|
1021
|
+
state_2 = StateDB.create(
|
|
1022
|
+
database_session=session,
|
|
1023
|
+
problem_id=problemdb.id,
|
|
1024
|
+
session_id=isession.id,
|
|
1025
|
+
parent_id=enautilus_state.id,
|
|
1026
|
+
state=enautilus_state_2,
|
|
1027
|
+
)
|
|
1028
|
+
|
|
1029
|
+
session.add(state_2)
|
|
1030
|
+
session.commit()
|
|
1031
|
+
session.refresh(state_2)
|
|
1032
|
+
|
|
1033
|
+
assert state_1.problem_id == problemdb.id
|
|
1034
|
+
assert state_2.problem_id == problemdb.id
|
|
1035
|
+
|
|
1036
|
+
assert state_1.session_id == isession.id
|
|
1037
|
+
assert state_2.session_id == isession.id
|
|
1038
|
+
|
|
1039
|
+
assert state_1.parent is None
|
|
1040
|
+
assert state_2.parent == state_1
|
|
1041
|
+
|
|
1042
|
+
assert len(state_1.children) == 1
|
|
1043
|
+
assert state_1.children[0] == state_2
|
|
1044
|
+
assert state_2.children == []
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
def test_nimbus_models(session_and_user: dict[str, Session | list[User]]):
|
|
1048
|
+
"""Test that the NIMBUS models are in working order."""
|
|
1049
|
+
session: Session = session_and_user["session"]
|
|
1050
|
+
user: User = session_and_user["user"]
|
|
1051
|
+
problem_db = user.problems[0]
|
|
1052
|
+
problem = Problem.from_problemdb(problem_db)
|
|
1053
|
+
|
|
1054
|
+
isession = InteractiveSessionDB(user_id=user.id)
|
|
1055
|
+
|
|
1056
|
+
session.add(isession)
|
|
1057
|
+
session.commit()
|
|
1058
|
+
session.refresh(isession)
|
|
1059
|
+
|
|
1060
|
+
# 1. Initialize the NIMBUS problem (NIMBUSInitializationState)
|
|
1061
|
+
results_1 = generate_starting_point(
|
|
1062
|
+
problem=problem,
|
|
1063
|
+
)
|
|
1064
|
+
nimbus_init_state = NIMBUSInitializationState(solver_results=results_1)
|
|
1065
|
+
|
|
1066
|
+
state_1 = StateDB.create(
|
|
1067
|
+
database_session=session, problem_id=problem_db.id, session_id=isession.id, state=nimbus_init_state
|
|
1068
|
+
)
|
|
1069
|
+
|
|
1070
|
+
session.add(state_1)
|
|
1071
|
+
session.commit()
|
|
1072
|
+
session.refresh(state_1)
|
|
1073
|
+
|
|
1074
|
+
actual_state_1: NIMBUSInitializationState = state_1.state
|
|
1075
|
+
|
|
1076
|
+
assert type(actual_state_1) is NIMBUSInitializationState
|
|
1077
|
+
assert np.allclose(
|
|
1078
|
+
[x for _, x in actual_state_1.solver_results.optimal_objectives.items()],
|
|
1079
|
+
[x for _, x in results_1.optimal_objectives.items()],
|
|
1080
|
+
0.001,
|
|
1081
|
+
)
|
|
1082
|
+
|
|
1083
|
+
# 2. Solve sub problems (NIMBUSClassificationState)
|
|
1084
|
+
aspirations = {"f_1": 0.1, "f_2": 0.9, "f_3": 0.6}
|
|
1085
|
+
|
|
1086
|
+
results_2 = solve_sub_problems(
|
|
1087
|
+
problem=problem, current_objectives=results_1.optimal_objectives, reference_point=aspirations, num_desired=4
|
|
1088
|
+
)
|
|
1089
|
+
nimbus_classification_state = NIMBUSClassificationState(
|
|
1090
|
+
preferences=ReferencePoint(aspiration_levels=aspirations),
|
|
1091
|
+
current_objectives=results_1.optimal_objectives,
|
|
1092
|
+
previous_preferences=ReferencePoint(aspiration_levels=aspirations),
|
|
1093
|
+
solver_results=results_2,
|
|
1094
|
+
)
|
|
1095
|
+
|
|
1096
|
+
state_2 = StateDB.create(
|
|
1097
|
+
database_session=session, problem_id=problem_db.id, session_id=isession.id, state=nimbus_classification_state
|
|
1098
|
+
)
|
|
1099
|
+
|
|
1100
|
+
session.add(state_2)
|
|
1101
|
+
session.commit()
|
|
1102
|
+
session.refresh(state_2)
|
|
1103
|
+
|
|
1104
|
+
actual_state_2: NIMBUSClassificationState = state_2.state
|
|
1105
|
+
|
|
1106
|
+
assert type(actual_state_2) is NIMBUSClassificationState
|
|
1107
|
+
assert np.allclose(
|
|
1108
|
+
[x for _, x in actual_state_2.preferences.aspiration_levels.items()], [x for _, x in aspirations.items()], 0.001
|
|
1109
|
+
)
|
|
1110
|
+
assert np.allclose(
|
|
1111
|
+
[x for _, x in actual_state_2.solver_results[0].optimal_objectives.items()],
|
|
1112
|
+
[x for _, x in results_2[0].optimal_objectives.items()],
|
|
1113
|
+
0.001,
|
|
1114
|
+
)
|
|
1115
|
+
|
|
1116
|
+
# 3. (TODO) Save a found solution (NIMBUSSaveState)
|
|
1117
|
+
# 4. Finalize the NIMBUS process (NIMBUSFinalState)
|
|
1118
|
+
nimbus_final_state = NIMBUSFinalState(
|
|
1119
|
+
solution_origin_state_id=state_2.state.id,
|
|
1120
|
+
solution_result_index=0,
|
|
1121
|
+
solver_results=results_2[0]
|
|
1122
|
+
)
|
|
1123
|
+
|
|
1124
|
+
state_3 = StateDB.create(
|
|
1125
|
+
database_session=session, problem_id=problem_db.id, session_id=isession.id, state=nimbus_final_state
|
|
1126
|
+
)
|
|
1127
|
+
|
|
1128
|
+
session.add(state_3)
|
|
1129
|
+
session.commit()
|
|
1130
|
+
session.refresh(state_3)
|
|
1131
|
+
|
|
1132
|
+
actual_state_3: NIMBUSFinalState = state_3.state
|
|
1133
|
+
assert type(actual_state_3) is NIMBUSFinalState
|
|
1134
|
+
assert np.allclose(
|
|
1135
|
+
[x for _, x in actual_state_3.solver_results.optimal_objectives.items()],
|
|
1136
|
+
[x for _, x in results_2[0].optimal_objectives.items()],
|
|
1137
|
+
0.01,
|
|
1138
|
+
)
|
|
1139
|
+
assert np.allclose(
|
|
1140
|
+
[x for _, x in actual_state_3.solver_results.optimal_variables.items()],
|
|
1141
|
+
[x for _, x in results_2[0].optimal_variables.items()],
|
|
1142
|
+
0.01,
|
|
1143
|
+
)
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
def test_nimbus_initialize_w_multidimensional_constraints(session_and_user: dict[str, Session | list[User]]):
|
|
1147
|
+
"""Test that the NIMBUS initialization model works with multidimensional constraints."""
|
|
1148
|
+
session: Session = session_and_user["session"]
|
|
1149
|
+
user: User = session_and_user["user"]
|
|
1150
|
+
problem = multi_valued_constraint_problem()
|
|
1151
|
+
|
|
1152
|
+
problem_db = ProblemDB.from_problem(problem, user)
|
|
1153
|
+
isession = InteractiveSessionDB(user_id=user.id)
|
|
1154
|
+
|
|
1155
|
+
session.add(isession)
|
|
1156
|
+
session.add(problem_db)
|
|
1157
|
+
session.commit()
|
|
1158
|
+
session.refresh(isession)
|
|
1159
|
+
session.refresh(problem_db)
|
|
1160
|
+
|
|
1161
|
+
results_1 = generate_starting_point(problem=problem, solver=PyomoBonminSolver)
|
|
1162
|
+
nimbus_init_state = NIMBUSInitializationState(solver_results=results_1)
|
|
1163
|
+
|
|
1164
|
+
state_1 = StateDB.create(
|
|
1165
|
+
database_session=session, problem_id=problem_db.id, session_id=isession.id, state=nimbus_init_state
|
|
1166
|
+
)
|
|
1167
|
+
|
|
1168
|
+
session.add(state_1)
|
|
1169
|
+
session.commit()
|
|
1170
|
+
session.refresh(state_1)
|
|
1171
|
+
|
|
1172
|
+
actual_state_1: NIMBUSInitializationState = state_1.state
|
|
1173
|
+
|
|
1174
|
+
assert type(actual_state_1) is NIMBUSInitializationState
|
|
1175
|
+
assert np.allclose(
|
|
1176
|
+
[x for _, x in actual_state_1.solver_results.optimal_objectives.items()],
|
|
1177
|
+
[x for _, x in results_1.optimal_objectives.items()],
|
|
1178
|
+
0.001,
|
|
1179
|
+
)
|