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.
Files changed (126) hide show
  1. desdeo/adm/ADMAfsar.py +551 -0
  2. desdeo/adm/ADMChen.py +414 -0
  3. desdeo/adm/BaseADM.py +119 -0
  4. desdeo/adm/__init__.py +11 -0
  5. desdeo/api/__init__.py +6 -6
  6. desdeo/api/app.py +38 -28
  7. desdeo/api/config.py +65 -44
  8. desdeo/api/config.toml +23 -12
  9. desdeo/api/db.py +10 -8
  10. desdeo/api/db_init.py +12 -6
  11. desdeo/api/models/__init__.py +220 -20
  12. desdeo/api/models/archive.py +16 -27
  13. desdeo/api/models/emo.py +128 -0
  14. desdeo/api/models/enautilus.py +69 -0
  15. desdeo/api/models/gdm/gdm_aggregate.py +139 -0
  16. desdeo/api/models/gdm/gdm_base.py +69 -0
  17. desdeo/api/models/gdm/gdm_score_bands.py +114 -0
  18. desdeo/api/models/gdm/gnimbus.py +138 -0
  19. desdeo/api/models/generic.py +104 -0
  20. desdeo/api/models/generic_states.py +401 -0
  21. desdeo/api/models/nimbus.py +158 -0
  22. desdeo/api/models/preference.py +44 -6
  23. desdeo/api/models/problem.py +274 -64
  24. desdeo/api/models/session.py +4 -1
  25. desdeo/api/models/state.py +419 -52
  26. desdeo/api/models/user.py +7 -6
  27. desdeo/api/models/utopia.py +25 -0
  28. desdeo/api/routers/_EMO.backup +309 -0
  29. desdeo/api/routers/_NIMBUS.py +6 -3
  30. desdeo/api/routers/emo.py +497 -0
  31. desdeo/api/routers/enautilus.py +237 -0
  32. desdeo/api/routers/gdm/gdm_aggregate.py +234 -0
  33. desdeo/api/routers/gdm/gdm_base.py +420 -0
  34. desdeo/api/routers/gdm/gdm_score_bands/gdm_score_bands_manager.py +398 -0
  35. desdeo/api/routers/gdm/gdm_score_bands/gdm_score_bands_routers.py +377 -0
  36. desdeo/api/routers/gdm/gnimbus/gnimbus_manager.py +698 -0
  37. desdeo/api/routers/gdm/gnimbus/gnimbus_routers.py +591 -0
  38. desdeo/api/routers/generic.py +233 -0
  39. desdeo/api/routers/nimbus.py +705 -0
  40. desdeo/api/routers/problem.py +201 -4
  41. desdeo/api/routers/reference_point_method.py +20 -44
  42. desdeo/api/routers/session.py +50 -26
  43. desdeo/api/routers/user_authentication.py +180 -26
  44. desdeo/api/routers/utils.py +187 -0
  45. desdeo/api/routers/utopia.py +230 -0
  46. desdeo/api/schema.py +10 -4
  47. desdeo/api/tests/conftest.py +94 -2
  48. desdeo/api/tests/test_enautilus.py +330 -0
  49. desdeo/api/tests/test_models.py +550 -72
  50. desdeo/api/tests/test_routes.py +902 -43
  51. desdeo/api/utils/_database.py +263 -0
  52. desdeo/api/utils/database.py +28 -266
  53. desdeo/api/utils/emo_database.py +40 -0
  54. desdeo/core.py +7 -0
  55. desdeo/emo/__init__.py +154 -24
  56. desdeo/emo/hooks/archivers.py +18 -2
  57. desdeo/emo/methods/EAs.py +128 -5
  58. desdeo/emo/methods/bases.py +9 -56
  59. desdeo/emo/methods/templates.py +111 -0
  60. desdeo/emo/operators/crossover.py +544 -42
  61. desdeo/emo/operators/evaluator.py +10 -14
  62. desdeo/emo/operators/generator.py +127 -24
  63. desdeo/emo/operators/mutation.py +212 -41
  64. desdeo/emo/operators/scalar_selection.py +202 -0
  65. desdeo/emo/operators/selection.py +956 -214
  66. desdeo/emo/operators/termination.py +124 -16
  67. desdeo/emo/options/__init__.py +108 -0
  68. desdeo/emo/options/algorithms.py +435 -0
  69. desdeo/emo/options/crossover.py +164 -0
  70. desdeo/emo/options/generator.py +131 -0
  71. desdeo/emo/options/mutation.py +260 -0
  72. desdeo/emo/options/repair.py +61 -0
  73. desdeo/emo/options/scalar_selection.py +66 -0
  74. desdeo/emo/options/selection.py +127 -0
  75. desdeo/emo/options/templates.py +383 -0
  76. desdeo/emo/options/termination.py +143 -0
  77. desdeo/gdm/__init__.py +22 -0
  78. desdeo/gdm/gdmtools.py +45 -0
  79. desdeo/gdm/score_bands.py +114 -0
  80. desdeo/gdm/voting_rules.py +50 -0
  81. desdeo/mcdm/__init__.py +23 -1
  82. desdeo/mcdm/enautilus.py +338 -0
  83. desdeo/mcdm/gnimbus.py +484 -0
  84. desdeo/mcdm/nautilus_navigator.py +7 -6
  85. desdeo/mcdm/reference_point_method.py +70 -0
  86. desdeo/problem/__init__.py +5 -1
  87. desdeo/problem/external/__init__.py +18 -0
  88. desdeo/problem/external/core.py +356 -0
  89. desdeo/problem/external/pymoo_provider.py +266 -0
  90. desdeo/problem/external/runtime.py +44 -0
  91. desdeo/problem/infix_parser.py +2 -2
  92. desdeo/problem/pyomo_evaluator.py +25 -6
  93. desdeo/problem/schema.py +69 -48
  94. desdeo/problem/simulator_evaluator.py +65 -15
  95. desdeo/problem/testproblems/__init__.py +26 -11
  96. desdeo/problem/testproblems/benchmarks_server.py +120 -0
  97. desdeo/problem/testproblems/cake_problem.py +185 -0
  98. desdeo/problem/testproblems/dmitry_forest_problem_discrete.py +71 -0
  99. desdeo/problem/testproblems/forest_problem.py +77 -69
  100. desdeo/problem/testproblems/multi_valued_constraints.py +119 -0
  101. desdeo/problem/testproblems/{river_pollution_problem.py → river_pollution_problems.py} +28 -22
  102. desdeo/problem/testproblems/single_objective.py +289 -0
  103. desdeo/problem/testproblems/zdt_problem.py +4 -1
  104. desdeo/tools/__init__.py +39 -21
  105. desdeo/tools/desc_gen.py +22 -0
  106. desdeo/tools/generics.py +22 -2
  107. desdeo/tools/group_scalarization.py +3090 -0
  108. desdeo/tools/indicators_binary.py +107 -1
  109. desdeo/tools/indicators_unary.py +3 -16
  110. desdeo/tools/message.py +33 -2
  111. desdeo/tools/non_dominated_sorting.py +4 -3
  112. desdeo/tools/patterns.py +9 -7
  113. desdeo/tools/pyomo_solver_interfaces.py +48 -35
  114. desdeo/tools/reference_vectors.py +118 -351
  115. desdeo/tools/scalarization.py +340 -1413
  116. desdeo/tools/score_bands.py +491 -328
  117. desdeo/tools/utils.py +117 -49
  118. desdeo/tools/visualizations.py +67 -0
  119. desdeo/utopia_stuff/utopia_problem.py +1 -1
  120. desdeo/utopia_stuff/utopia_problem_old.py +1 -1
  121. {desdeo-2.0.0.dist-info → desdeo-2.1.0.dist-info}/METADATA +46 -28
  122. desdeo-2.1.0.dist-info/RECORD +180 -0
  123. {desdeo-2.0.0.dist-info → desdeo-2.1.0.dist-info}/WHEEL +1 -1
  124. desdeo-2.0.0.dist-info/RECORD +0 -120
  125. /desdeo/api/utils/{logger.py → _logger.py} +0 -0
  126. {desdeo-2.0.0.dist-info → desdeo-2.1.0.dist-info/licenses}/LICENSE +0 -0
desdeo/api/config.py CHANGED
@@ -1,10 +1,12 @@
1
1
  """Defines dataclasses to store configurations loaded from 'config.toml'."""
2
2
 
3
3
  import tomllib
4
+ import os
5
+ import json
4
6
  from pathlib import Path
5
- from typing import ClassVar
7
+ from typing import List
6
8
 
7
- from pydantic import BaseModel
9
+ from pydantic_settings import BaseSettings
8
10
 
9
11
  # Load the config data once
10
12
  config_path = Path(__file__).resolve().parent / "config.toml"
@@ -12,58 +14,77 @@ with config_path.open("rb") as fp:
12
14
  config_data = tomllib.load(fp)
13
15
 
14
16
 
15
- class SettingsConfig(BaseModel):
17
+ class GeneralSettings(BaseSettings):
16
18
  """General settings."""
17
19
 
18
- debug: ClassVar[bool] = config_data["settings"]["debug"]
20
+ debug: bool = config_data["settings"]["debug"]
19
21
 
20
22
 
21
- class ServerDebugConfig(BaseModel):
23
+ SettingsConfig = GeneralSettings()
24
+
25
+
26
+ class ServerDebugConfig(BaseSettings):
22
27
  """Server setup settings (development)."""
23
28
 
24
- test_user_analyst_name: ClassVar[str] = config_data["server-debug"]["test_user_analyst_name"]
25
- test_user_analyst_password: ClassVar[str] = config_data["server-debug"]["test_user_analyst_password"]
26
- test_user_dm1_name: ClassVar[str] = config_data["server-debug"]["test_user_dm1_name"]
27
- test_user_dm1_password: ClassVar[str] = config_data["server-debug"]["test_user_dm1_password"]
28
- test_user_dm2_name: ClassVar[str] = config_data["server-debug"]["test_user_dm2_name"]
29
- test_user_dm2_password: ClassVar[str] = config_data["server-debug"]["test_user_dm2_password"]
29
+ test_user_analyst_name: str = config_data["server-debug"]["test_user_analyst_name"]
30
+ test_user_analyst_password: str = config_data["server-debug"]["test_user_analyst_password"]
31
+ test_user_dm1_name: str = config_data["server-debug"]["test_user_dm1_name"]
32
+ test_user_dm1_password: str = config_data["server-debug"]["test_user_dm1_password"]
33
+ test_user_dm2_name: str = config_data["server-debug"]["test_user_dm2_name"]
34
+ test_user_dm2_password: str = config_data["server-debug"]["test_user_dm2_password"]
30
35
 
31
36
 
32
- class AuthDebugConfig(BaseModel):
33
- """Authentication settings (development)."""
37
+ class AuthDebugConfig(BaseSettings):
38
+ """Authentication settings (debug)."""
34
39
 
35
- authjwt_secret_key: ClassVar[str] = config_data["auth-debug"]["authjwt_secret_key"]
36
- authjwt_algorithm: ClassVar[str] = config_data["auth-debug"]["authjwt_algorithm"]
37
- authjwt_access_token_expires: ClassVar[int] = config_data["auth-debug"]["authjwt_access_token_expires"]
38
- authjwt_refresh_token_expires: ClassVar[int] = config_data["auth-debug"]["authjwt_refresh_token_expires"]
39
- cors_origins: ClassVar[list[str]] = config_data["auth-debug"]["cors_origins"]
40
+ authjwt_secret_key: str = config_data["auth-debug"]["authjwt_secret_key"]
41
+ authjwt_algorithm: str = config_data["auth-debug"]["authjwt_algorithm"]
42
+ authjwt_access_token_expires: int = config_data["auth-debug"]["authjwt_access_token_expires"]
43
+ authjwt_refresh_token_expires: int = config_data["auth-debug"]["authjwt_refresh_token_expires"]
44
+ cors_origins: List[str] = config_data["auth-debug"]["cors_origins"]
45
+ cookie_domain: str = config_data["auth-debug"]["cookie_domain"]
40
46
 
41
47
 
42
- class DatabaseDebugConfig(BaseModel):
48
+ class DatabaseDebugConfig(BaseSettings):
43
49
  """Database setting (development)."""
44
50
 
45
- db_host: ClassVar[str] = config_data["database-debug"]["db_host"]
46
- db_port: ClassVar[str] = config_data["database-debug"]["db_port"]
47
- db_database: ClassVar[str] = config_data["database-debug"]["db_database"]
48
- db_username: ClassVar[str] = config_data["database-debug"]["db_username"]
49
- db_password: ClassVar[str] = config_data["database-debug"]["db_password"]
50
- db_pool_size: ClassVar[int] = config_data["database-debug"]["db_pool_size"]
51
- db_max_overflow: ClassVar[int] = config_data["database-debug"]["db_max_overflow"]
52
- db_pool: ClassVar[bool] = config_data["database-debug"]["db_pool"]
53
-
54
-
55
- # class DatabaseDeployConfig(BaseModel):
56
- # # db_host: str = config_data["database-deploy"]["db_host"]
57
- # db_port: str = config_data["database-deploy"]["db_port"]
58
- # db_database: str = config_data["database-deploy"]["db_database"]
59
- # db_username: str = config_data["database-deploy"]["db_username"]
60
- # db_password: str = config_data["database-deploy"]["db_password"]
61
- # db_pool_size: int = config_data["database-deploy"]["db_pool_size"]
62
- # db_max_overflow: int = config_data["database-deploy"]["db_max_overflow"]
63
- # db_pool: bool = config_data["database-deploy"]["db_pool"]
64
-
65
- # class AuthDeployConfig(BaseModel):
66
- # authjwt_algorithm: str = config_data["auth-deploy"]["authjwt_algorithm"]
67
- # authjwt_access_token_expires: int = config_data["auth-deploy"]["authjwt_access_token_expires"]
68
- # authjwt_refresh_token_expires: int = config_data["auth-deploy"]["authjwt_refresh_token_expires"]
69
- # Note: authjwt_secret_key should be retrieved securely in production
51
+ db_host: str = config_data["database-debug"]["db_host"]
52
+ db_port: str = config_data["database-debug"]["db_port"]
53
+ db_database: str = config_data["database-debug"]["db_database"]
54
+ db_username: str = config_data["database-debug"]["db_username"]
55
+ db_password: str = config_data["database-debug"]["db_password"]
56
+ db_pool_size: int = config_data["database-debug"]["db_pool_size"]
57
+ db_max_overflow: int = config_data["database-debug"]["db_max_overflow"]
58
+ db_pool: bool = config_data["database-debug"]["db_pool"]
59
+
60
+
61
+ class DatabaseDeployConfig(BaseSettings):
62
+ """Database setting (deployment)."""
63
+
64
+ db_host: str = os.getenv("DB_HOST")
65
+ db_port: str = os.getenv("DB_PORT")
66
+ db_database: str = os.getenv("DB_NAME")
67
+ db_username: str = os.getenv("DB_USER")
68
+ db_password: str = os.getenv("DB_PASSWORD")
69
+ db_pool_size: int = config_data["database-deploy"]["db_pool_size"]
70
+ db_max_overflow: int = config_data["database-deploy"]["db_max_overflow"]
71
+ db_pool: bool = config_data["database-deploy"]["db_pool"]
72
+ db_driver: str = os.getenv("DB_DRIVER", config_data["database-deploy"]["db_driver"])
73
+
74
+
75
+ class AuthDeployConfig(BaseSettings):
76
+ """Authentication settings (deployment)."""
77
+
78
+ authjwt_secret_key: str = os.getenv("AUTHJWT_SECRET")
79
+ authjwt_algorithm: str = config_data["auth-deploy"]["authjwt_algorithm"]
80
+ authjwt_access_token_expires: int = config_data["auth-deploy"]["authjwt_access_token_expires"]
81
+ authjwt_refresh_token_expires: int = config_data["auth-deploy"]["authjwt_refresh_token_expires"]
82
+ cors_origins: List[str] = json.loads(os.getenv("CORS_ORIGINS", "[]"))
83
+ cookie_domain: str = os.getenv("COOKIE_DOMAIN", "")
84
+
85
+
86
+ AuthConfig = AuthDebugConfig() if SettingsConfig.debug else AuthDeployConfig()
87
+
88
+ DatabaseConfig = DatabaseDebugConfig() if SettingsConfig.debug else DatabaseDeployConfig()
89
+
90
+ ServerConfig = ServerDebugConfig() if SettingsConfig.debug else None
desdeo/api/config.toml CHANGED
@@ -1,4 +1,5 @@
1
1
  [settings]
2
+ # This is ignored if $DESDEO_PRODUCTION env variable is present
2
3
  debug = true
3
4
 
4
5
  # development configs
@@ -18,16 +19,23 @@ authjwt_access_token_expires = 15 # in minutes
18
19
  authjwt_refresh_token_expires = 30 # in minutes
19
20
  cors_origins = [
20
21
  "http://localhost",
21
- "http://localhost:8080",
22
+ "http://localhost:8000",
22
23
  "http://localhost:5173",
24
+ "http://127.0.0.1",
25
+ "http://127.0.0.1:8000",
26
+ "http://127.0.0.1:5173",
23
27
  ]
28
+ cookie_domain = "" # Not needed for testing
24
29
 
25
30
  [auth-deploy]
26
- # TODO
27
31
  # secret key should be read from env DO NOT EXPOSE!!!!
32
+ # authjwt_secret_key = $AUTHJWT_SECRET
28
33
  authjwt_algorithm = "HS256"
29
- authjwt_access_token_expires = 15 # in minutes
30
- authjwt_refresh_token_expires = 30 # in minutes
34
+ authjwt_access_token_expires = 5 # in minutes
35
+ authjwt_refresh_token_expires = 180 # in minutes
36
+ # These are not that sensitive info but read from env regardless
37
+ # cors_origins = $CORS_ORIGINS
38
+ # cookie_domain = $COOKIE_DOMAIN
31
39
 
32
40
  # SQLite setup (enabled for local development)
33
41
  [database-debug]
@@ -39,15 +47,18 @@ db_password = ""
39
47
  db_pool_size = 1
40
48
  db_max_overflow = 0
41
49
  db_pool = false
50
+ db_driver = "postgresql+asyncpg"
42
51
 
43
52
  # Database configuration (deployment)
44
53
  [database-deploy]
45
54
  # READ FROM ENV!!!
46
- # db_host = "localhost"
47
- # db_port = "5432"
48
- # db_database = "test"
49
- # db_username = "test"
50
- # db_password = "testpw"
51
- # db_pool_size = 20
52
- # db_max_overflow = 20
53
- # db_pool = true
55
+ # db_host = $DB_HOST
56
+ # db_port = $DB_PORT
57
+ # db_database = $DB_NAME
58
+ # db_username = $DB_USER
59
+ # db_password = $DB_PASSWORD
60
+ db_pool_size = 20
61
+ db_max_overflow = 20
62
+ db_pool = true
63
+ # Can be overridden with $DB_DRIVER env variable
64
+ db_driver = "postgresql+asyncpg"
desdeo/api/db.py CHANGED
@@ -2,21 +2,23 @@
2
2
 
3
3
  from sqlmodel import Session, create_engine
4
4
 
5
- from desdeo.api.config import DatabaseDebugConfig, SettingsConfig
5
+ from desdeo.api.config import DatabaseConfig, SettingsConfig
6
6
 
7
7
  if SettingsConfig.debug:
8
8
  # debug and development stuff
9
9
 
10
10
  # SQLite setup
11
- engine = create_engine(DatabaseDebugConfig.db_database, connect_args={"check_same_thread": False})
11
+ engine = create_engine(DatabaseConfig.db_database, connect_args={"check_same_thread": False})
12
12
 
13
13
  else:
14
- # deployment stuff
15
-
16
- # Postgresql setup
17
- # check from config.toml
18
- # SQLALCHEMY_DATABASE_URL = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
19
- pass
14
+ DB_USER = DatabaseConfig.db_username
15
+ DB_PASSWORD = DatabaseConfig.db_password
16
+ DB_HOST = DatabaseConfig.db_host
17
+ DB_PORT = DatabaseConfig.db_port
18
+ DB_NAME = DatabaseConfig.db_database
19
+
20
+ # Now the use of postgres is hardcoded for deployment, which may be fine
21
+ engine = create_engine(f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}")
20
22
 
21
23
 
22
24
  def get_session():
desdeo/api/db_init.py CHANGED
@@ -5,11 +5,13 @@ import warnings
5
5
  from sqlalchemy_utils import database_exists
6
6
  from sqlmodel import Session, SQLModel
7
7
 
8
- from desdeo.api.config import ServerDebugConfig, SettingsConfig
8
+ from desdeo.api.config import ServerConfig, SettingsConfig
9
9
  from desdeo.api.db import engine
10
10
  from desdeo.api.models import ProblemDB, User, UserRole
11
11
  from desdeo.api.routers.user_authentication import get_password_hash
12
- from desdeo.problem.testproblems import river_pollution_problem
12
+ from desdeo.problem.testproblems import dtlz2, river_pollution_problem, simple_knapsack
13
+
14
+ problems = [dtlz2(10, 3), simple_knapsack(), river_pollution_problem()]
13
15
 
14
16
  if __name__ == "__main__":
15
17
  if SettingsConfig.debug:
@@ -21,14 +23,15 @@ if __name__ == "__main__":
21
23
  else:
22
24
  warnings.warn("Database already exists. Clearing it.", stacklevel=1)
23
25
  # Drop all tables
26
+ SQLModel.metadata.reflect(bind=engine)
24
27
  SQLModel.metadata.drop_all(bind=engine)
25
28
  SQLModel.metadata.create_all(engine)
26
29
  print("Database tables created.")
27
30
 
28
31
  with Session(engine) as session:
29
32
  user_analyst = User(
30
- username=ServerDebugConfig.test_user_analyst_name,
31
- password_hash=get_password_hash(ServerDebugConfig.test_user_analyst_password),
33
+ username=ServerConfig.test_user_analyst_name,
34
+ password_hash=get_password_hash(ServerConfig.test_user_analyst_password),
32
35
  role=UserRole.analyst,
33
36
  group="test",
34
37
  )
@@ -36,13 +39,16 @@ if __name__ == "__main__":
36
39
  session.commit()
37
40
  session.refresh(user_analyst)
38
41
 
39
- problem_db = ProblemDB.from_problem(river_pollution_problem(), user_analyst)
42
+ for problem in problems:
43
+ problem_db = ProblemDB.from_problem(problem, user_analyst)
44
+
45
+ session.add(problem_db)
40
46
 
41
- session.add(problem_db)
42
47
  session.commit()
43
48
  session.refresh(problem_db)
44
49
 
45
50
  """
51
+
46
52
  db.add(user_analyst)
47
53
  db.commit()
48
54
  db.refresh(user_analyst)
@@ -1,55 +1,241 @@
1
1
  """Model exports."""
2
2
 
3
- __all__ = [
4
- "ArchiveEntryBase",
5
- "ArchiveEntryDB",
3
+ __all__ = [ # noqa: RUF022
6
4
  "Bounds",
7
5
  "ConstantDB",
8
6
  "ConstraintDB",
9
7
  "CreateSessionRequest",
10
8
  "DiscreteRepresentationDB",
9
+ "EMOSaveState",
10
+ "EMOSolveRequest",
11
+ "EMOIterateState",
12
+ "ENautilusRepresentativeSolutionsResponse",
13
+ "ENautilusState",
14
+ "ENautilusStateResponse",
15
+ "ENautilusStepRequest",
16
+ "ENautilusStepResponse",
11
17
  "ExtraFunctionDB",
18
+ "ForestProblemMetaData",
19
+ "GenericIntermediateSolutionResponse",
12
20
  "GetSessionRequest",
13
- "User",
14
- "UserBase",
15
- "UserPublic",
16
- "UserRole",
21
+ "GNIMBUSOptimizationState",
22
+ "GNIMBUSVotingState",
23
+ "GNIMBUSEndState",
24
+ "InteractiveSessionBase",
25
+ "InteractiveSessionDB",
26
+ "InteractiveSessionInfo",
27
+ "IntermediateSolutionRequest",
28
+ "IntermediateSolutionResponse",
29
+ "IntermediateSolutionState",
30
+ "NIMBUSClassificationRequest",
31
+ "NIMBUSClassificationState",
32
+ "NIMBUSDeleteSaveRequest",
33
+ "NIMBUSDeleteSaveResponse",
34
+ "NIMBUSInitializationRequest",
35
+ "NIMBUSInitializationState",
36
+ "NIMBUSIntermediateSolutionResponse",
37
+ "NIMBUSSaveRequest",
38
+ "NIMBUSClassificationResponse",
39
+ "NIMBUSInitializationResponse",
40
+ "NIMBUSSaveResponse",
41
+ "NIMBUSFinalizeRequest",
42
+ "NIMBUSFinalizeResponse",
43
+ "NIMBUSFinalState",
44
+ "NIMBUSSaveState",
45
+ "NonPreferredSolutions",
17
46
  "ObjectiveDB",
18
- "ScalarizationFunctionDB",
19
- "TensorConstantDB",
20
- "SimulatorDB",
21
- "TensorVariableDB",
22
47
  "PreferenceBase",
23
48
  "PreferenceDB",
24
- "ProblemGetRequest",
49
+ "PreferredSolutions",
50
+ "PreferredRanges",
25
51
  "ProblemDB",
52
+ "ProblemAddFromJSONRequest",
53
+ "ProblemGetRequest",
26
54
  "ProblemInfo",
27
55
  "ProblemInfoSmall",
56
+ "ProblemMetaDataDB",
57
+ "ProblemMetaDataGetRequest",
58
+ "ProblemSelectSolverRequest",
28
59
  "ReferencePoint",
60
+ "RepresentativeNonDominatedSolutions",
29
61
  "RPMSolveRequest",
30
- "VariableDB",
31
- "InteractiveSessionBase",
32
- "InteractiveSessionDB",
33
- "InteractiveSessionInfo",
34
- "RPMBaseState",
35
62
  "RPMState",
63
+ "SavedSolutionReference",
64
+ "ScalarizationFunctionDB",
65
+ "SimulatorDB",
66
+ "State",
36
67
  "StateDB",
68
+ "SolutionInfo",
69
+ "TensorConstantDB",
70
+ "TensorVariableDB",
71
+ "User",
72
+ "UserBase",
73
+ "UserPublic",
74
+ "UserRole",
75
+ "VariableDB",
76
+ "ProblemMetaDataDB",
77
+ "BaseProblemMetaData",
78
+ "ForestProblemMetaData",
79
+ "Group",
80
+ "GroupModifyRequest",
81
+ "GroupCreateRequest",
82
+ "GroupRevertRequest",
83
+ "GroupIteration",
84
+ "GroupPublic",
85
+ "GroupInfoRequest",
86
+ "BaseGroupInfoContainer",
87
+ "ReferencePointDictType",
88
+ "BooleanDictTypeDecorator",
89
+ "EMOSolveRequest",
90
+ "PreferredRanges",
91
+ "PreferedSolutions",
92
+ "NonPreferredSolutions",
93
+ "EMOFetchRequest",
94
+ "EMOFetchResponse",
95
+ "EMOIterateRequest",
96
+ "EMOIterateResponse",
97
+ "EMOSaveRequest",
98
+ "EMOScoreRequest",
99
+ "EMOScoreResponse",
100
+ "Solution",
101
+ "SolutionReference",
102
+ "SolutionReferenceLite",
103
+ "SolutionReferenceResponse",
104
+ "SolverSelectionMetadata",
105
+ "UserSavedEMOResults",
106
+ "UserSavedSolutionDB",
107
+ "UtopiaRequest",
108
+ "UtopiaResponse",
109
+ "VariableDB",
110
+ "ScoreBandsRequest",
111
+ "ScoreBandsResponse",
112
+ "OptimizationPreference",
113
+ "VotingPreference",
114
+ "EndProcessPreference",
115
+ "GNIMBUSResultResponse",
116
+ "FullIteration",
117
+ "GNIMBUSAllIterationsResponse",
118
+ "GNIMBUSSwitchPhaseRequest",
119
+ "GNIMBUSSwitchPhaseResponse",
120
+ "GDMScoreBandsInitializationRequest",
121
+ "GDMSCOREBandInformation",
122
+ "GDMSCOREBandsResponse",
123
+ "GDMScoreBandsVoteRequest",
124
+ "GDMSCOREBandFinalSelection",
125
+ "GDMSCOREBandsDecisionResponse",
126
+ "GDMSCOREBandsRevertRequest",
127
+ "GDMSCOREBandsHistoryResponse",
37
128
  ]
38
129
 
39
- from .archive import ArchiveEntryBase, ArchiveEntryDB
40
- from .preference import Bounds, PreferenceBase, PreferenceDB, ReferencePoint
130
+
131
+ from .archive import UserSavedEMOResults
132
+ from .emo import (
133
+ EMOFetchRequest,
134
+ EMOFetchResponse,
135
+ EMOIterateRequest,
136
+ EMOIterateResponse,
137
+ EMOSaveRequest,
138
+ EMOScoreRequest,
139
+ EMOScoreResponse,
140
+ Solution,
141
+ )
142
+ from .enautilus import (
143
+ ENautilusRepresentativeSolutionsResponse,
144
+ ENautilusStateResponse,
145
+ ENautilusStepRequest,
146
+ ENautilusStepResponse,
147
+ )
148
+ from .gdm.gdm_aggregate import (
149
+ Group,
150
+ GroupCreateRequest,
151
+ GroupInfoRequest,
152
+ GroupIteration,
153
+ GroupModifyRequest,
154
+ GroupPublic,
155
+ GroupRevertRequest,
156
+ )
157
+ from .gdm.gdm_base import (
158
+ BaseGroupInfoContainer,
159
+ BooleanDictTypeDecorator,
160
+ ReferencePointDictType,
161
+ )
162
+ from .gdm.gdm_score_bands import (
163
+ GDMSCOREBandFinalSelection,
164
+ GDMSCOREBandInformation,
165
+ GDMSCOREBandsDecisionResponse,
166
+ GDMSCOREBandsHistoryResponse,
167
+ GDMScoreBandsInitializationRequest,
168
+ GDMSCOREBandsResponse,
169
+ GDMSCOREBandsRevertRequest,
170
+ GDMScoreBandsVoteRequest,
171
+ )
172
+ from .gdm.gnimbus import (
173
+ EndProcessPreference,
174
+ FullIteration,
175
+ GNIMBUSAllIterationsResponse,
176
+ GNIMBUSResultResponse,
177
+ GNIMBUSSwitchPhaseRequest,
178
+ GNIMBUSSwitchPhaseResponse,
179
+ OptimizationPreference,
180
+ VotingPreference,
181
+ )
182
+ from .generic import (
183
+ GenericIntermediateSolutionResponse,
184
+ IntermediateSolutionRequest,
185
+ ScoreBandsRequest,
186
+ ScoreBandsResponse,
187
+ SolutionInfo,
188
+ )
189
+ from .generic_states import (
190
+ SavedSolutionReference,
191
+ SolutionReference,
192
+ SolutionReferenceLite,
193
+ SolutionReferenceResponse,
194
+ State,
195
+ StateDB,
196
+ UserSavedSolutionDB,
197
+ )
198
+ from .nimbus import (
199
+ NIMBUSClassificationRequest,
200
+ NIMBUSClassificationResponse,
201
+ NIMBUSDeleteSaveRequest,
202
+ NIMBUSDeleteSaveResponse,
203
+ NIMBUSFinalizeRequest,
204
+ NIMBUSFinalizeResponse,
205
+ NIMBUSInitializationRequest,
206
+ NIMBUSInitializationResponse,
207
+ NIMBUSIntermediateSolutionResponse,
208
+ NIMBUSSaveRequest,
209
+ NIMBUSSaveResponse,
210
+ )
211
+ from .preference import (
212
+ Bounds,
213
+ NonPreferredSolutions,
214
+ PreferenceBase,
215
+ PreferenceDB,
216
+ PreferredRanges,
217
+ PreferredSolutions,
218
+ ReferencePoint,
219
+ )
41
220
  from .problem import (
42
221
  ConstantDB,
43
222
  ConstraintDB,
44
223
  DiscreteRepresentationDB,
45
224
  ExtraFunctionDB,
225
+ ForestProblemMetaData,
46
226
  ObjectiveDB,
227
+ ProblemAddFromJSONRequest,
47
228
  ProblemDB,
48
229
  ProblemGetRequest,
49
230
  ProblemInfo,
50
231
  ProblemInfoSmall,
232
+ ProblemMetaDataDB,
233
+ ProblemMetaDataGetRequest,
234
+ ProblemSelectSolverRequest,
235
+ RepresentativeNonDominatedSolutions,
51
236
  ScalarizationFunctionDB,
52
237
  SimulatorDB,
238
+ SolverSelectionMetadata,
53
239
  TensorConstantDB,
54
240
  TensorVariableDB,
55
241
  VariableDB,
@@ -62,5 +248,19 @@ from .session import (
62
248
  InteractiveSessionDB,
63
249
  InteractiveSessionInfo,
64
250
  )
65
- from .state import RPMBaseState, RPMState, StateDB
251
+ from .state import (
252
+ EMOIterateState,
253
+ EMOSaveState,
254
+ ENautilusState,
255
+ GNIMBUSEndState,
256
+ GNIMBUSOptimizationState,
257
+ GNIMBUSVotingState,
258
+ IntermediateSolutionState,
259
+ NIMBUSClassificationState,
260
+ NIMBUSFinalState,
261
+ NIMBUSInitializationState,
262
+ NIMBUSSaveState,
263
+ RPMState,
264
+ )
66
265
  from .user import User, UserBase, UserPublic, UserRole
266
+ from .utopia import UtopiaRequest, UtopiaResponse
@@ -1,34 +1,23 @@
1
1
  """Defines models for archiving solutions."""
2
2
 
3
- from typing import TYPE_CHECKING
3
+ from sqlmodel import Field
4
4
 
5
- from sqlmodel import JSON, Column, Field, Relationship, SQLModel
5
+ from desdeo.tools.generics import EMOResult
6
6
 
7
- from .preference import PreferenceDB
8
7
 
9
- if TYPE_CHECKING:
10
- from .problem import ProblemDB
11
- from .user import User
8
+ class UserSavedEMOResults(EMOResult):
9
+ """Defines a schema for storing emo solutions."""
12
10
 
11
+ name: str | None = Field(
12
+ description="An optional name for the solution, useful for archiving purposes.",
13
+ default=None,
14
+ )
13
15
 
14
- class ArchiveEntryBase(SQLModel):
15
- """The base model of an archive entry."""
16
-
17
- variable_values: dict[str, float | list] = Field(sa_column=Column(JSON, nullable=False))
18
- objective_values: dict[str, float] = Field(sa_column=Column(JSON, nullable=False))
19
- constraint_values: dict[str, float] | None = Field(sa_column=Column(JSON), default=None)
20
- extra_func_values: dict[str, float] | None = Field(sa_column=Column(JSON), default=None)
21
-
22
-
23
- class ArchiveEntryDB(ArchiveEntryBase, table=True):
24
- """Database model of an archive entry."""
25
-
26
- id: int | None = Field(primary_key=True, default=None)
27
- user_id: int | None = Field(foreign_key="user.id", default=None)
28
- problem_id: int | None = Field(foreign_key="problemdb.id", default=None)
29
- preference_id: int | None = Field(foreign_key="preferencedb.id", default=None)
30
-
31
- # Back populates
32
- user: "User" = Relationship(back_populates="archive")
33
- preference: "PreferenceDB" = Relationship(back_populates="solutions")
34
- problem: "ProblemDB" = Relationship(back_populates="solutions")
16
+ def to_emo_results(self) -> EMOResult:
17
+ """Convert to SolverResults without the name field."""
18
+ return EMOResult(
19
+ optimal_variables=self.optimal_variables,
20
+ optimal_objectives=self.optimal_objectives,
21
+ constraint_values=self.constraint_values,
22
+ extra_func_values=self.extra_func_values,
23
+ )