ert 16.0.9__py3-none-any.whl → 19.0.0rc2__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.
- _ert/events.py +19 -2
- _ert/forward_model_runner/client.py +6 -2
- _ert/forward_model_runner/fm_dispatch.py +9 -6
- _ert/forward_model_runner/reporting/event.py +1 -0
- _ert/forward_model_runner/runner.py +1 -2
- _ert/utils.py +12 -0
- ert/__main__.py +58 -38
- ert/analysis/_enif_update.py +8 -4
- ert/analysis/_es_update.py +19 -6
- ert/analysis/_update_commons.py +16 -6
- ert/base_model_context.py +1 -1
- ert/cli/main.py +17 -12
- ert/cli/monitor.py +7 -0
- ert/config/__init__.py +17 -6
- ert/config/_create_observation_dataframes.py +118 -21
- ert/config/_get_num_cpu.py +1 -1
- ert/config/_observations.py +91 -2
- ert/config/_read_summary.py +74 -328
- ert/config/design_matrix.py +62 -23
- ert/config/distribution.py +1 -1
- ert/config/ensemble_config.py +9 -17
- ert/config/ert_config.py +155 -58
- ert/config/everest_control.py +234 -0
- ert/config/{everest_constraints_config.py → everest_response.py} +27 -15
- ert/config/field.py +99 -90
- ert/config/forward_model_step.py +122 -17
- ert/config/gen_data_config.py +5 -10
- ert/config/gen_kw_config.py +11 -41
- ert/config/known_response_types.py +14 -0
- ert/config/parameter_config.py +1 -33
- ert/config/parsing/_option_dict.py +10 -2
- ert/config/parsing/config_errors.py +1 -1
- ert/config/parsing/config_keywords.py +2 -1
- ert/config/parsing/config_schema.py +23 -11
- ert/config/parsing/config_schema_deprecations.py +3 -3
- ert/config/parsing/config_schema_item.py +26 -11
- ert/config/parsing/context_values.py +3 -3
- ert/config/parsing/file_context_token.py +1 -1
- ert/config/parsing/observations_parser.py +6 -2
- ert/config/parsing/queue_system.py +9 -0
- ert/config/parsing/schema_item_type.py +1 -0
- ert/config/queue_config.py +42 -50
- ert/config/response_config.py +0 -8
- ert/config/rft_config.py +275 -0
- ert/config/summary_config.py +3 -8
- ert/config/surface_config.py +73 -26
- ert/config/workflow_fixtures.py +2 -1
- ert/config/workflow_job.py +135 -54
- ert/dark_storage/client/__init__.py +2 -2
- ert/dark_storage/client/_session.py +4 -4
- ert/dark_storage/client/client.py +2 -2
- ert/dark_storage/common.py +12 -3
- ert/dark_storage/compute/misfits.py +11 -7
- ert/dark_storage/endpoints/compute/misfits.py +6 -4
- ert/dark_storage/endpoints/ensembles.py +4 -0
- ert/dark_storage/endpoints/experiment_server.py +30 -24
- ert/dark_storage/endpoints/experiments.py +2 -2
- ert/dark_storage/endpoints/observations.py +8 -6
- ert/dark_storage/endpoints/parameters.py +4 -12
- ert/dark_storage/endpoints/responses.py +24 -5
- ert/dark_storage/json_schema/ensemble.py +3 -0
- ert/dark_storage/json_schema/experiment.py +1 -1
- ert/data/_measured_data.py +6 -5
- ert/ensemble_evaluator/__init__.py +8 -1
- ert/ensemble_evaluator/config.py +2 -1
- ert/ensemble_evaluator/evaluator.py +81 -29
- ert/ensemble_evaluator/event.py +6 -0
- ert/ensemble_evaluator/snapshot.py +3 -1
- ert/ensemble_evaluator/state.py +1 -0
- ert/field_utils/__init__.py +8 -0
- ert/field_utils/field_utils.py +228 -15
- ert/field_utils/grdecl_io.py +1 -1
- ert/field_utils/roff_io.py +1 -1
- ert/gui/__init__.py +5 -2
- ert/gui/ertnotifier.py +1 -1
- ert/gui/ertwidgets/__init__.py +23 -16
- ert/gui/ertwidgets/analysismoduleedit.py +2 -2
- ert/gui/ertwidgets/checklist.py +1 -1
- ert/gui/ertwidgets/closabledialog.py +2 -0
- ert/gui/ertwidgets/copyablelabel.py +2 -0
- ert/gui/ertwidgets/create_experiment_dialog.py +3 -1
- ert/gui/ertwidgets/ensembleselector.py +2 -2
- ert/gui/ertwidgets/listeditbox.py +2 -0
- ert/gui/ertwidgets/models/__init__.py +2 -0
- ert/gui/ertwidgets/models/activerealizationsmodel.py +5 -1
- ert/gui/ertwidgets/models/path_model.py +1 -1
- ert/gui/ertwidgets/models/targetensemblemodel.py +5 -1
- ert/gui/ertwidgets/models/text_model.py +4 -1
- ert/gui/ertwidgets/pathchooser.py +0 -3
- ert/gui/ertwidgets/searchbox.py +17 -4
- ert/gui/ertwidgets/stringbox.py +2 -0
- ert/gui/{suggestor → ertwidgets/suggestor}/_suggestor_message.py +13 -4
- ert/gui/{suggestor → ertwidgets/suggestor}/suggestor.py +63 -30
- ert/gui/main.py +41 -13
- ert/gui/main_window.py +3 -7
- ert/gui/model/fm_step_list.py +3 -0
- ert/gui/model/real_list.py +1 -0
- ert/gui/model/snapshot.py +1 -0
- ert/gui/simulation/combobox_with_description.py +3 -0
- ert/gui/simulation/ensemble_experiment_panel.py +8 -2
- ert/gui/simulation/ensemble_information_filter_panel.py +7 -2
- ert/gui/simulation/ensemble_smoother_panel.py +8 -2
- ert/gui/simulation/evaluate_ensemble_panel.py +17 -7
- ert/gui/simulation/experiment_panel.py +18 -6
- ert/gui/simulation/manual_update_panel.py +35 -10
- ert/gui/simulation/multiple_data_assimilation_panel.py +13 -9
- ert/gui/simulation/run_dialog.py +47 -20
- ert/gui/simulation/single_test_run_panel.py +6 -3
- ert/gui/simulation/view/progress_widget.py +2 -0
- ert/gui/simulation/view/realization.py +5 -1
- ert/gui/simulation/view/update.py +2 -0
- ert/gui/summarypanel.py +20 -1
- ert/gui/tools/event_viewer/panel.py +3 -4
- ert/gui/tools/event_viewer/tool.py +2 -0
- ert/gui/tools/load_results/load_results_panel.py +1 -1
- ert/gui/tools/load_results/load_results_tool.py +2 -0
- ert/gui/tools/manage_experiments/export_dialog.py +136 -0
- ert/gui/tools/manage_experiments/manage_experiments_panel.py +2 -0
- ert/gui/tools/manage_experiments/storage_info_widget.py +121 -16
- ert/gui/tools/manage_experiments/storage_widget.py +4 -3
- ert/gui/tools/plot/customize/color_chooser.py +5 -2
- ert/gui/tools/plot/customize/customize_plot_dialog.py +2 -0
- ert/gui/tools/plot/customize/default_customization_view.py +4 -0
- ert/gui/tools/plot/customize/limits_customization_view.py +3 -0
- ert/gui/tools/plot/customize/statistics_customization_view.py +3 -0
- ert/gui/tools/plot/customize/style_chooser.py +2 -0
- ert/gui/tools/plot/customize/style_customization_view.py +3 -0
- ert/gui/tools/plot/data_type_keys_widget.py +2 -0
- ert/gui/tools/plot/data_type_proxy_model.py +3 -0
- ert/gui/tools/plot/plot_api.py +50 -28
- ert/gui/tools/plot/plot_ensemble_selection_widget.py +17 -10
- ert/gui/tools/plot/plot_widget.py +15 -2
- ert/gui/tools/plot/plot_window.py +41 -19
- ert/gui/tools/plot/plottery/plot_config.py +2 -0
- ert/gui/tools/plot/plottery/plot_context.py +14 -0
- ert/gui/tools/plot/plottery/plots/__init__.py +2 -0
- ert/gui/tools/plot/plottery/plots/cesp.py +3 -1
- ert/gui/tools/plot/plottery/plots/distribution.py +6 -1
- ert/gui/tools/plot/plottery/plots/ensemble.py +13 -5
- ert/gui/tools/plot/plottery/plots/gaussian_kde.py +12 -2
- ert/gui/tools/plot/plottery/plots/histogram.py +3 -1
- ert/gui/tools/plot/plottery/plots/misfits.py +436 -0
- ert/gui/tools/plot/plottery/plots/observations.py +18 -4
- ert/gui/tools/plot/plottery/plots/statistics.py +62 -20
- ert/gui/tools/plot/plottery/plots/std_dev.py +3 -1
- ert/gui/tools/plot/widgets/clearable_line_edit.py +9 -0
- ert/gui/tools/plot/widgets/filter_popup.py +2 -0
- ert/gui/tools/plot/widgets/filterable_kw_list_model.py +3 -0
- ert/gui/tools/plugins/plugin.py +1 -1
- ert/gui/tools/plugins/plugins_tool.py +2 -0
- ert/gui/tools/plugins/process_job_dialog.py +3 -0
- ert/gui/tools/workflows/workflow_dialog.py +2 -0
- ert/gui/tools/workflows/workflows_tool.py +2 -0
- ert/libres_facade.py +5 -7
- ert/logging/__init__.py +4 -1
- ert/mode_definitions.py +2 -0
- ert/plugins/__init__.py +4 -6
- ert/plugins/hook_implementations/workflows/csv_export.py +2 -3
- ert/plugins/hook_implementations/workflows/gen_data_rft_export.py +10 -2
- ert/plugins/hook_specifications/__init__.py +0 -10
- ert/plugins/hook_specifications/jobs.py +0 -9
- ert/plugins/plugin_manager.py +53 -124
- ert/resources/forward_models/run_reservoirsimulator.py +8 -4
- ert/resources/forward_models/template_render.py +10 -10
- ert/resources/shell_scripts/delete_directory.py +2 -2
- ert/run_models/__init__.py +24 -6
- ert/run_models/_create_run_path.py +133 -38
- ert/run_models/ensemble_experiment.py +10 -4
- ert/run_models/ensemble_information_filter.py +8 -1
- ert/run_models/ensemble_smoother.py +9 -3
- ert/run_models/evaluate_ensemble.py +8 -6
- ert/run_models/event.py +7 -3
- ert/run_models/everest_run_model.py +337 -113
- ert/run_models/initial_ensemble_run_model.py +25 -24
- ert/run_models/manual_update.py +6 -3
- ert/run_models/manual_update_enif.py +37 -0
- ert/run_models/model_factory.py +78 -18
- ert/run_models/multiple_data_assimilation.py +22 -11
- ert/run_models/run_model.py +72 -73
- ert/run_models/single_test_run.py +7 -4
- ert/run_models/update_run_model.py +4 -2
- ert/runpaths.py +5 -6
- ert/sample_prior.py +9 -4
- ert/scheduler/__init__.py +10 -5
- ert/scheduler/driver.py +40 -0
- ert/scheduler/event.py +3 -1
- ert/scheduler/job.py +23 -13
- ert/scheduler/lsf_driver.py +15 -5
- ert/scheduler/openpbs_driver.py +10 -4
- ert/scheduler/scheduler.py +5 -0
- ert/scheduler/slurm_driver.py +20 -5
- ert/services/__init__.py +2 -2
- ert/services/_base_service.py +37 -20
- ert/services/_storage_main.py +20 -18
- ert/services/ert_server.py +317 -0
- ert/shared/_doc_utils/__init__.py +4 -2
- ert/shared/_doc_utils/ert_jobs.py +1 -4
- ert/shared/net_utils.py +43 -18
- ert/shared/storage/connection.py +3 -3
- ert/shared/version.py +3 -3
- ert/storage/__init__.py +14 -1
- ert/storage/local_ensemble.py +44 -13
- ert/storage/local_experiment.py +54 -34
- ert/storage/local_storage.py +90 -58
- ert/storage/migration/to10.py +3 -2
- ert/storage/migration/to11.py +9 -10
- ert/storage/migration/to12.py +19 -20
- ert/storage/migration/to13.py +28 -27
- ert/storage/migration/to14.py +3 -3
- ert/storage/migration/to15.py +25 -0
- ert/storage/migration/to16.py +38 -0
- ert/storage/migration/to17.py +42 -0
- ert/storage/migration/to18.py +11 -0
- ert/storage/migration/to19.py +34 -0
- ert/storage/migration/to20.py +23 -0
- ert/storage/migration/to21.py +25 -0
- ert/storage/migration/to6.py +3 -2
- ert/storage/migration/to7.py +12 -13
- ert/storage/migration/to8.py +9 -11
- ert/storage/migration/to9.py +5 -4
- ert/storage/realization_storage_state.py +7 -7
- ert/substitutions.py +12 -28
- ert/validation/active_range.py +7 -7
- ert/validation/ensemble_realizations_argument.py +4 -2
- ert/validation/rangestring.py +16 -16
- ert/workflow_runner.py +6 -3
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/METADATA +21 -15
- ert-19.0.0rc2.dist-info/RECORD +524 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/WHEEL +1 -1
- everest/api/everest_data_api.py +14 -1
- everest/assets/everest_logo.svg +406 -0
- everest/bin/config_branch_script.py +30 -14
- everest/bin/everconfigdump_script.py +2 -10
- everest/bin/everest_script.py +53 -33
- everest/bin/everlint_script.py +3 -5
- everest/bin/kill_script.py +7 -5
- everest/bin/main.py +11 -24
- everest/bin/monitor_script.py +64 -35
- everest/bin/utils.py +58 -43
- everest/bin/visualization_script.py +23 -13
- everest/config/__init__.py +4 -1
- everest/config/control_config.py +81 -6
- everest/config/control_variable_config.py +4 -3
- everest/config/everest_config.py +102 -79
- everest/config/forward_model_config.py +5 -3
- everest/config/install_data_config.py +7 -5
- everest/config/install_job_config.py +45 -3
- everest/config/install_template_config.py +3 -3
- everest/config/optimization_config.py +19 -6
- everest/config/output_constraint_config.py +8 -2
- everest/config/server_config.py +6 -55
- everest/config/simulator_config.py +62 -17
- everest/config/utils.py +25 -105
- everest/config/validation_utils.py +34 -15
- everest/config_file_loader.py +30 -21
- everest/detached/__init__.py +0 -6
- everest/detached/client.py +7 -52
- everest/detached/everserver.py +19 -45
- everest/everest_storage.py +24 -40
- everest/gui/everest_client.py +2 -3
- everest/gui/main_window.py +2 -2
- everest/optimizer/everest2ropt.py +68 -42
- everest/optimizer/opt_model_transforms.py +15 -20
- everest/optimizer/utils.py +0 -29
- everest/plugins/hook_specs.py +0 -24
- everest/strings.py +1 -6
- everest/util/__init__.py +3 -1
- ert/config/everest_objective_config.py +0 -95
- ert/config/ext_param_config.py +0 -107
- ert/gui/tools/export/__init__.py +0 -3
- ert/gui/tools/export/export_panel.py +0 -83
- ert/gui/tools/export/export_tool.py +0 -67
- ert/gui/tools/export/exporter.py +0 -36
- ert/plugins/hook_specifications/ecl_config.py +0 -29
- ert/services/storage_service.py +0 -127
- ert/summary_key_type.py +0 -234
- ert-16.0.9.dist-info/RECORD +0 -521
- everest/bin/everexport_script.py +0 -53
- everest/config/sampler_config.py +0 -103
- everest/simulator/__init__.py +0 -88
- everest/simulator/everest_to_ert.py +0 -252
- /ert/gui/{suggestor → ertwidgets/suggestor}/__init__.py +0 -0
- /ert/gui/{suggestor → ertwidgets/suggestor}/_colors.py +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/entry_points.txt +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/licenses/COPYING +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/top_level.txt +0 -0
everest/config/control_config.py
CHANGED
|
@@ -12,13 +12,12 @@ from typing import (
|
|
|
12
12
|
from pydantic import AfterValidator, BaseModel, ConfigDict, Field, model_validator
|
|
13
13
|
from ropt.enums import PerturbationType, VariableType
|
|
14
14
|
|
|
15
|
-
from ert.config import
|
|
15
|
+
from ert.config import EverestControl, SamplerConfig
|
|
16
16
|
|
|
17
17
|
from .control_variable_config import (
|
|
18
18
|
ControlVariableConfig,
|
|
19
19
|
ControlVariableGuessListConfig,
|
|
20
20
|
)
|
|
21
|
-
from .sampler_config import SamplerConfig
|
|
22
21
|
from .validation_utils import (
|
|
23
22
|
control_variables_validation,
|
|
24
23
|
no_dots_in_string,
|
|
@@ -167,7 +166,8 @@ class ControlConfig(BaseModel):
|
|
|
167
166
|
"""
|
|
168
167
|
),
|
|
169
168
|
)
|
|
170
|
-
perturbation_magnitude: float = Field(
|
|
169
|
+
perturbation_magnitude: float | None = Field(
|
|
170
|
+
default=None,
|
|
171
171
|
description=dedent(
|
|
172
172
|
"""
|
|
173
173
|
The magnitude of the perturbation of all control variables in the
|
|
@@ -186,6 +186,8 @@ class ControlConfig(BaseModel):
|
|
|
186
186
|
and `min` fields.
|
|
187
187
|
|
|
188
188
|
This default value can be overridden at the variable level.
|
|
189
|
+
|
|
190
|
+
This field is required unless it is explicitly set for all variables.
|
|
189
191
|
"""
|
|
190
192
|
),
|
|
191
193
|
)
|
|
@@ -248,6 +250,19 @@ class ControlConfig(BaseModel):
|
|
|
248
250
|
)
|
|
249
251
|
return values
|
|
250
252
|
|
|
253
|
+
@model_validator(mode="after")
|
|
254
|
+
def validate_perturbation_magnitude(self) -> Self:
|
|
255
|
+
if self.perturbation_magnitude is None and any(
|
|
256
|
+
variable
|
|
257
|
+
for variable in self.variables
|
|
258
|
+
if variable.perturbation_magnitude is None
|
|
259
|
+
):
|
|
260
|
+
raise ValueError(
|
|
261
|
+
"A default perturbation_magnitude for all variables must be set "
|
|
262
|
+
"when not all variables define it explicitly."
|
|
263
|
+
)
|
|
264
|
+
return self
|
|
265
|
+
|
|
251
266
|
@model_validator(mode="after")
|
|
252
267
|
def validate_variables(self) -> Self:
|
|
253
268
|
if self.variables is None:
|
|
@@ -274,7 +289,7 @@ class ControlConfig(BaseModel):
|
|
|
274
289
|
def __hash__(self) -> int:
|
|
275
290
|
return hash(self.name)
|
|
276
291
|
|
|
277
|
-
def __eq__(self, other:
|
|
292
|
+
def __eq__(self, other: object) -> bool:
|
|
278
293
|
return isinstance(other, self.__class__) and other.name == self.name
|
|
279
294
|
|
|
280
295
|
@property
|
|
@@ -313,9 +328,69 @@ class ControlConfig(BaseModel):
|
|
|
313
328
|
extra="forbid",
|
|
314
329
|
)
|
|
315
330
|
|
|
316
|
-
def to_ert_parameter_config(self) ->
|
|
317
|
-
|
|
331
|
+
def to_ert_parameter_config(self) -> EverestControl:
|
|
332
|
+
types = []
|
|
333
|
+
initial_guesses = []
|
|
334
|
+
control_types = []
|
|
335
|
+
enabled = []
|
|
336
|
+
mins = []
|
|
337
|
+
maxs = []
|
|
338
|
+
perturbation_types = []
|
|
339
|
+
perturbation_magnitudes = []
|
|
340
|
+
scaled_ranges = []
|
|
341
|
+
samplers = []
|
|
342
|
+
|
|
343
|
+
def _parse_variable(
|
|
344
|
+
variable: ControlVariableConfig | ControlVariableGuessListConfig,
|
|
345
|
+
initial_guess: float | None = None,
|
|
346
|
+
) -> None:
|
|
347
|
+
types.append(self.type)
|
|
348
|
+
initial_guesses.append(
|
|
349
|
+
initial_guess
|
|
350
|
+
if initial_guess is not None
|
|
351
|
+
else variable.initial_guess
|
|
352
|
+
if variable.initial_guess is not None
|
|
353
|
+
else self.initial_guess
|
|
354
|
+
)
|
|
355
|
+
control_types.append(self.control_type)
|
|
356
|
+
enabled.append(
|
|
357
|
+
variable.enabled if variable.enabled is not None else self.enabled
|
|
358
|
+
)
|
|
359
|
+
mins.append(variable.min if variable.min is not None else self.min)
|
|
360
|
+
maxs.append(variable.max if variable.max is not None else self.max)
|
|
361
|
+
perturbation_types.append(variable.perturbation_type)
|
|
362
|
+
perturbation_magnitudes.append(
|
|
363
|
+
variable.perturbation_magnitude
|
|
364
|
+
if variable.perturbation_magnitude is not None
|
|
365
|
+
else self.perturbation_magnitude
|
|
366
|
+
)
|
|
367
|
+
scaled_ranges.append(
|
|
368
|
+
variable.scaled_range
|
|
369
|
+
if variable.scaled_range is not None
|
|
370
|
+
else self.scaled_range
|
|
371
|
+
)
|
|
372
|
+
samplers.append(variable.sampler or self.sampler)
|
|
373
|
+
|
|
374
|
+
for variable in self.variables:
|
|
375
|
+
if isinstance(variable, ControlVariableConfig):
|
|
376
|
+
_parse_variable(variable)
|
|
377
|
+
else:
|
|
378
|
+
for initial_guess in variable.initial_guess:
|
|
379
|
+
_parse_variable(variable, initial_guess=initial_guess)
|
|
380
|
+
|
|
381
|
+
return EverestControl(
|
|
318
382
|
name=self.name,
|
|
319
383
|
input_keys=self.formatted_control_names,
|
|
384
|
+
input_keys_dotdash=self.formatted_control_names_dotdash,
|
|
320
385
|
output_file=self.name + ".json",
|
|
386
|
+
types=types,
|
|
387
|
+
initial_guesses=initial_guesses,
|
|
388
|
+
control_types=control_types,
|
|
389
|
+
enabled=enabled,
|
|
390
|
+
min=mins,
|
|
391
|
+
max=maxs,
|
|
392
|
+
perturbation_types=perturbation_types,
|
|
393
|
+
perturbation_magnitudes=perturbation_magnitudes,
|
|
394
|
+
scaled_ranges=scaled_ranges,
|
|
395
|
+
samplers=samplers,
|
|
321
396
|
)
|
|
@@ -12,7 +12,8 @@ from pydantic import (
|
|
|
12
12
|
)
|
|
13
13
|
from ropt.enums import VariableType
|
|
14
14
|
|
|
15
|
-
from .
|
|
15
|
+
from ert.config import SamplerConfig
|
|
16
|
+
|
|
16
17
|
from .validation_utils import no_dots_in_string, valid_range
|
|
17
18
|
|
|
18
19
|
|
|
@@ -200,7 +201,7 @@ class ControlVariableConfig(_ControlVariable):
|
|
|
200
201
|
def __hash__(self) -> int:
|
|
201
202
|
return hash(self.name) + hash(self.index)
|
|
202
203
|
|
|
203
|
-
def __eq__(self, other:
|
|
204
|
+
def __eq__(self, other: object) -> bool:
|
|
204
205
|
return (
|
|
205
206
|
isinstance(other, self.__class__)
|
|
206
207
|
and other.name == self.name
|
|
@@ -233,7 +234,7 @@ class ControlVariableGuessListConfig(_ControlVariable):
|
|
|
233
234
|
def __hash__(self) -> int:
|
|
234
235
|
return hash(self.name)
|
|
235
236
|
|
|
236
|
-
def __eq__(self, other:
|
|
237
|
+
def __eq__(self, other: object) -> bool:
|
|
237
238
|
return isinstance(other, self.__class__) and other.name == self.name
|
|
238
239
|
|
|
239
240
|
@property
|
everest/config/everest_config.py
CHANGED
|
@@ -2,7 +2,7 @@ import logging
|
|
|
2
2
|
import os
|
|
3
3
|
from argparse import ArgumentParser
|
|
4
4
|
from copy import copy
|
|
5
|
-
from
|
|
5
|
+
from enum import StrEnum
|
|
6
6
|
from itertools import chain
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from sys import float_info
|
|
@@ -12,6 +12,8 @@ from typing import (
|
|
|
12
12
|
Any,
|
|
13
13
|
Optional,
|
|
14
14
|
Self,
|
|
15
|
+
TextIO,
|
|
16
|
+
TypeVar,
|
|
15
17
|
no_type_check,
|
|
16
18
|
)
|
|
17
19
|
|
|
@@ -27,10 +29,17 @@ from pydantic.json_schema import SkipJsonSchema
|
|
|
27
29
|
from pydantic_core import ErrorDetails
|
|
28
30
|
from pydantic_core.core_schema import ValidationInfo
|
|
29
31
|
from ruamel.yaml import YAML, YAMLError
|
|
30
|
-
|
|
31
|
-
from
|
|
32
|
-
|
|
33
|
-
from ert.
|
|
32
|
+
from ruamel.yaml.nodes import ScalarNode
|
|
33
|
+
from ruamel.yaml.representer import Representer
|
|
34
|
+
|
|
35
|
+
from ert.base_model_context import BaseModelWithContextSupport, use_runtime_plugins
|
|
36
|
+
from ert.config import (
|
|
37
|
+
ConfigWarning,
|
|
38
|
+
EverestConstraintsConfig,
|
|
39
|
+
EverestObjectivesConfig,
|
|
40
|
+
QueueSystem,
|
|
41
|
+
)
|
|
42
|
+
from ert.plugins import get_site_plugins
|
|
34
43
|
from everest.config.install_template_config import InstallTemplateConfig
|
|
35
44
|
from everest.config.server_config import ServerConfig
|
|
36
45
|
from everest.config.validation_utils import (
|
|
@@ -60,7 +69,11 @@ from .forward_model_config import (
|
|
|
60
69
|
)
|
|
61
70
|
from .input_constraint_config import InputConstraintConfig
|
|
62
71
|
from .install_data_config import InstallDataConfig
|
|
63
|
-
from .install_job_config import
|
|
72
|
+
from .install_job_config import (
|
|
73
|
+
InstallForwardModelStepConfig,
|
|
74
|
+
InstallJobConfig,
|
|
75
|
+
InstallWorkflowJobConfig,
|
|
76
|
+
)
|
|
64
77
|
from .model_config import ModelConfig
|
|
65
78
|
from .objective_function_config import ObjectiveFunctionConfig
|
|
66
79
|
from .optimization_config import OptimizationConfig
|
|
@@ -125,9 +138,7 @@ def _convert_to_everest_validation_error(
|
|
|
125
138
|
"""
|
|
126
139
|
everest_validation_error = EverestValidationError()
|
|
127
140
|
|
|
128
|
-
file_content =
|
|
129
|
-
with open(config_path, encoding="utf-8") as f:
|
|
130
|
-
file_content = f.readlines()
|
|
141
|
+
file_content = Path(config_path).read_text(encoding="utf-8").splitlines()
|
|
131
142
|
|
|
132
143
|
for error in validation_error.errors(
|
|
133
144
|
include_context=True, include_input=True, include_url=False
|
|
@@ -164,6 +175,9 @@ def _find_loc(loc: tuple[int | str, ...] | None, file_content: list[str]) -> int
|
|
|
164
175
|
return None
|
|
165
176
|
|
|
166
177
|
|
|
178
|
+
InstallJobConfigSubclass = TypeVar("InstallJobConfigSubclass", bound=InstallJobConfig)
|
|
179
|
+
|
|
180
|
+
|
|
167
181
|
class EverestConfig(BaseModelWithContextSupport):
|
|
168
182
|
controls: Annotated[list[ControlConfig], AfterValidator(unique_items)] = Field(
|
|
169
183
|
description=dedent(
|
|
@@ -177,18 +191,18 @@ class EverestConfig(BaseModelWithContextSupport):
|
|
|
177
191
|
```yaml
|
|
178
192
|
controls:
|
|
179
193
|
- name: point
|
|
180
|
-
|
|
181
|
-
|
|
194
|
+
type: generic_control
|
|
195
|
+
min: -1.0
|
|
196
|
+
max: 1.0
|
|
197
|
+
initial_guess: 0.1
|
|
198
|
+
perturbation_magnitude: 0.001
|
|
199
|
+
variables:
|
|
200
|
+
- name: x
|
|
201
|
+
initial_guess: 0.5
|
|
202
|
+
- name: y
|
|
203
|
+
min: 0.0
|
|
182
204
|
max: 1.0
|
|
183
|
-
|
|
184
|
-
perturbation_magnitude: 0.001
|
|
185
|
-
variables:
|
|
186
|
-
- name: x
|
|
187
|
-
initial_guess: 0.5
|
|
188
|
-
- name: y
|
|
189
|
-
min: 0.0
|
|
190
|
-
max: 1.0
|
|
191
|
-
- name: z
|
|
205
|
+
- name: z
|
|
192
206
|
```
|
|
193
207
|
|
|
194
208
|
This defines a group of controls names `point`, with variables `x`,
|
|
@@ -210,17 +224,18 @@ class EverestConfig(BaseModelWithContextSupport):
|
|
|
210
224
|
```yaml
|
|
211
225
|
controls:
|
|
212
226
|
- name: point
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
227
|
+
max: 1.0
|
|
228
|
+
min: -1.0
|
|
229
|
+
initial_guess: 0.25
|
|
230
|
+
perturbation_magnitude: 0.001
|
|
231
|
+
type: generic_control
|
|
232
|
+
variables:
|
|
233
|
+
- name: x
|
|
234
|
+
index: 1
|
|
235
|
+
- name: x
|
|
236
|
+
index: 2
|
|
237
|
+
- name: x
|
|
238
|
+
index: 3
|
|
224
239
|
```
|
|
225
240
|
|
|
226
241
|
This defines three variables `point.x.1`, `point.x.2` and
|
|
@@ -236,12 +251,13 @@ class EverestConfig(BaseModelWithContextSupport):
|
|
|
236
251
|
```yaml
|
|
237
252
|
controls:
|
|
238
253
|
- name: point
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
254
|
+
max: 1.0
|
|
255
|
+
min: -1.0
|
|
256
|
+
perturbation_magnitude: 0.001
|
|
257
|
+
type: generic_control
|
|
258
|
+
variables:
|
|
259
|
+
- name: x
|
|
260
|
+
initial_guess: [0.25, 0.25, 0.25]
|
|
245
261
|
```
|
|
246
262
|
"""
|
|
247
263
|
),
|
|
@@ -365,7 +381,7 @@ class EverestConfig(BaseModelWithContextSupport):
|
|
|
365
381
|
"""
|
|
366
382
|
),
|
|
367
383
|
)
|
|
368
|
-
install_jobs: list[
|
|
384
|
+
install_jobs: list[InstallForwardModelStepConfig] = Field(
|
|
369
385
|
default_factory=list,
|
|
370
386
|
description=dedent(
|
|
371
387
|
"""
|
|
@@ -377,7 +393,7 @@ class EverestConfig(BaseModelWithContextSupport):
|
|
|
377
393
|
),
|
|
378
394
|
validate_default=True,
|
|
379
395
|
)
|
|
380
|
-
install_workflow_jobs: list[
|
|
396
|
+
install_workflow_jobs: list[InstallWorkflowJobConfig] = Field(
|
|
381
397
|
default_factory=list,
|
|
382
398
|
description=dedent(
|
|
383
399
|
"""
|
|
@@ -624,7 +640,7 @@ class EverestConfig(BaseModelWithContextSupport):
|
|
|
624
640
|
|
|
625
641
|
@model_validator(mode="after")
|
|
626
642
|
def validate_job_executables(self) -> Self: # pylint: disable=E0213
|
|
627
|
-
def _check_jobs(jobs: list[
|
|
643
|
+
def _check_jobs(jobs: list[InstallJobConfigSubclass]) -> list[str]:
|
|
628
644
|
errors = []
|
|
629
645
|
for job in jobs:
|
|
630
646
|
if job.executable is None:
|
|
@@ -1017,31 +1033,6 @@ to read summary data from forward model, do:
|
|
|
1017
1033
|
|
|
1018
1034
|
return the_dict
|
|
1019
1035
|
|
|
1020
|
-
@classmethod
|
|
1021
|
-
def with_defaults(cls, **kwargs: Any) -> Self:
|
|
1022
|
-
"""
|
|
1023
|
-
Creates an Everest config with default values. Useful for initializing a config
|
|
1024
|
-
without having to provide empty defaults.
|
|
1025
|
-
"""
|
|
1026
|
-
defaults = {
|
|
1027
|
-
"controls": [
|
|
1028
|
-
{
|
|
1029
|
-
"name": "default_group",
|
|
1030
|
-
"type": "generic_control",
|
|
1031
|
-
"initial_guess": 0.5,
|
|
1032
|
-
"perturbation_magnitude": 0.01,
|
|
1033
|
-
"variables": [
|
|
1034
|
-
{"name": "default_name", "min": 0, "max": 1},
|
|
1035
|
-
],
|
|
1036
|
-
}
|
|
1037
|
-
],
|
|
1038
|
-
"objective_functions": [{"name": "default"}],
|
|
1039
|
-
"config_path": ".",
|
|
1040
|
-
"model": {"realizations": [0]},
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
return cls.with_plugins({**defaults, **kwargs}) # type: ignore
|
|
1044
|
-
|
|
1045
1036
|
@staticmethod
|
|
1046
1037
|
def lint_config_dict(config: ConfigDict) -> list[ErrorDetails]:
|
|
1047
1038
|
try:
|
|
@@ -1073,7 +1064,7 @@ to read summary data from forward model, do:
|
|
|
1073
1064
|
|
|
1074
1065
|
@classmethod
|
|
1075
1066
|
def with_plugins(cls, config_dict: dict[str, Any] | ConfigDict) -> Self:
|
|
1076
|
-
with
|
|
1067
|
+
with use_runtime_plugins(get_site_plugins()):
|
|
1077
1068
|
return cls(**config_dict)
|
|
1078
1069
|
|
|
1079
1070
|
@staticmethod
|
|
@@ -1095,26 +1086,58 @@ to read summary data from forward model, do:
|
|
|
1095
1086
|
except ValueError as e:
|
|
1096
1087
|
parser.error(f"Loading config file <{config_path}> failed with: {e}")
|
|
1097
1088
|
|
|
1098
|
-
def
|
|
1099
|
-
|
|
1100
|
-
|
|
1089
|
+
def write_to_file(
|
|
1090
|
+
self, output_file: str | Path | TextIO, drop_config_path: bool = False
|
|
1091
|
+
) -> None:
|
|
1092
|
+
dictconf = self.to_dict()
|
|
1093
|
+
if drop_config_path:
|
|
1094
|
+
del dictconf["config_path"]
|
|
1095
|
+
if isinstance(output_file, str):
|
|
1096
|
+
output_file = Path(output_file)
|
|
1097
|
+
self.write_dict_to_file(dictconf, output_file)
|
|
1101
1098
|
|
|
1102
|
-
|
|
1099
|
+
@staticmethod
|
|
1100
|
+
def write_dict_to_file(
|
|
1101
|
+
config: dict[str, Any], output_file: Path | TextIO, safe_and_pure: bool = True
|
|
1102
|
+
) -> None:
|
|
1103
|
+
yaml = YAML(typ="safe", pure=True) if safe_and_pure else YAML()
|
|
1104
|
+
yaml.indent(mapping=2, sequence=4, offset=2)
|
|
1105
|
+
yaml.preserve_quotes = True
|
|
1103
1106
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
if fname is None:
|
|
1107
|
-
with StringIO() as sio:
|
|
1108
|
-
yaml.dump(stripped_conf, sio)
|
|
1109
|
-
return sio.getvalue()
|
|
1107
|
+
def strenum_representer(dumper: Representer, data: StrEnum) -> ScalarNode:
|
|
1108
|
+
return dumper.represent_str(data.value)
|
|
1110
1109
|
|
|
1111
|
-
|
|
1112
|
-
yaml.dump(stripped_conf, out)
|
|
1110
|
+
yaml.representer.add_multi_representer(StrEnum, strenum_representer)
|
|
1113
1111
|
|
|
1114
|
-
|
|
1112
|
+
yaml.default_flow_style = False
|
|
1113
|
+
yaml.dump(config, output_file)
|
|
1115
1114
|
|
|
1116
1115
|
@property
|
|
1117
1116
|
def server_queue_system(self) -> QueueSystem:
|
|
1118
1117
|
assert self.server is not None
|
|
1119
1118
|
assert self.server.queue_system is not None
|
|
1120
1119
|
return self.server.queue_system.name
|
|
1120
|
+
|
|
1121
|
+
def create_ert_objectives_config(self) -> EverestObjectivesConfig:
|
|
1122
|
+
objective_names = [o.name for o in self.objective_functions]
|
|
1123
|
+
return EverestObjectivesConfig(
|
|
1124
|
+
keys=objective_names,
|
|
1125
|
+
input_files=objective_names,
|
|
1126
|
+
weights=[o.weight for o in self.objective_functions],
|
|
1127
|
+
scales=[o.scale for o in self.objective_functions],
|
|
1128
|
+
objective_types=[o.type for o in self.objective_functions],
|
|
1129
|
+
)
|
|
1130
|
+
|
|
1131
|
+
def create_ert_output_constraints_config(self) -> EverestConstraintsConfig | None:
|
|
1132
|
+
if len(self.output_constraints) == 0:
|
|
1133
|
+
return None
|
|
1134
|
+
|
|
1135
|
+
constraint_names = [c.name for c in self.output_constraints]
|
|
1136
|
+
return EverestConstraintsConfig(
|
|
1137
|
+
keys=constraint_names,
|
|
1138
|
+
input_files=constraint_names,
|
|
1139
|
+
scales=[c.scale for c in self.output_constraints],
|
|
1140
|
+
targets=[c.target for c in self.output_constraints],
|
|
1141
|
+
upper_bounds=[c.upper_bound for c in self.output_constraints],
|
|
1142
|
+
lower_bounds=[c.lower_bound for c in self.output_constraints],
|
|
1143
|
+
)
|
|
@@ -9,7 +9,9 @@ from pydantic import (
|
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
from ert.base_model_context import BaseModelWithContextSupport
|
|
12
|
-
from ert.config import
|
|
12
|
+
from ert.config import (
|
|
13
|
+
SiteOrUserForwardModelStep,
|
|
14
|
+
)
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
class ForwardModelResult(BaseModelWithContextSupport):
|
|
@@ -74,8 +76,8 @@ class ForwardModelStepConfig(BaseModelWithContextSupport):
|
|
|
74
76
|
return values
|
|
75
77
|
|
|
76
78
|
def to_ert_forward_model_step(
|
|
77
|
-
self, installed_fm_steps: dict[str,
|
|
78
|
-
) ->
|
|
79
|
+
self, installed_fm_steps: dict[str, SiteOrUserForwardModelStep]
|
|
80
|
+
) -> SiteOrUserForwardModelStep:
|
|
79
81
|
fm_name, *arglist = self.job.split()
|
|
80
82
|
match fm_name:
|
|
81
83
|
# All three reservoir simulator fm_steps map to
|
|
@@ -9,11 +9,13 @@ from typing import Any
|
|
|
9
9
|
|
|
10
10
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
11
11
|
|
|
12
|
-
from ert.config import
|
|
12
|
+
from ert.config.forward_model_step import (
|
|
13
|
+
SiteOrUserForwardModelStep,
|
|
14
|
+
)
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
def _is_dir_all_model(source: str, model_realizations: list[int]) -> bool:
|
|
16
|
-
"""Expands <
|
|
18
|
+
"""Expands <REALIZATION_ID> for all realizations and if:
|
|
17
19
|
- all are directories, returns True,
|
|
18
20
|
- all are files, returns False,
|
|
19
21
|
- some are non-existing, raises an AssertionError
|
|
@@ -21,7 +23,7 @@ def _is_dir_all_model(source: str, model_realizations: list[int]) -> bool:
|
|
|
21
23
|
|
|
22
24
|
is_dir = []
|
|
23
25
|
for model_realization in model_realizations:
|
|
24
|
-
model_source = source.replace("<
|
|
26
|
+
model_source = source.replace("<REALIZATION_ID>", str(model_realization))
|
|
25
27
|
if not os.path.exists(model_source):
|
|
26
28
|
msg = (
|
|
27
29
|
"Expected source to exist for data installation, "
|
|
@@ -126,8 +128,8 @@ class InstallDataConfig(BaseModel):
|
|
|
126
128
|
config_directory: str,
|
|
127
129
|
output_directory: str,
|
|
128
130
|
model_realizations: list[int],
|
|
129
|
-
installed_fm_steps: dict[str,
|
|
130
|
-
) ->
|
|
131
|
+
installed_fm_steps: dict[str, SiteOrUserForwardModelStep],
|
|
132
|
+
) -> SiteOrUserForwardModelStep:
|
|
131
133
|
target = self.target
|
|
132
134
|
|
|
133
135
|
def _missing_fm_msg(fm_name: str) -> str:
|
|
@@ -5,7 +5,12 @@ from textwrap import dedent
|
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field, model_validator
|
|
7
7
|
|
|
8
|
-
from ert.config import
|
|
8
|
+
from ert.config import (
|
|
9
|
+
ExecutableWorkflow,
|
|
10
|
+
UserInstalledForwardModelStep,
|
|
11
|
+
forward_model_step_from_config_contents,
|
|
12
|
+
workflow_job_from_file,
|
|
13
|
+
)
|
|
9
14
|
|
|
10
15
|
|
|
11
16
|
class InstallJobConfig(BaseModel, extra="forbid"):
|
|
@@ -44,12 +49,24 @@ class InstallJobConfig(BaseModel, extra="forbid"):
|
|
|
44
49
|
raise ValueError("Either source or executable must be provided")
|
|
45
50
|
return self
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
@model_validator(mode="after")
|
|
53
|
+
def validate_source_exists(self) -> InstallJobConfig:
|
|
54
|
+
if self.source is not None and not Path(self.source).is_file():
|
|
55
|
+
raise ValueError(f"No such file or directory: {self.source}")
|
|
56
|
+
return self
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class InstallForwardModelStepConfig(InstallJobConfig):
|
|
60
|
+
def to_ert_forward_model_step(
|
|
61
|
+
self, config_directory: str
|
|
62
|
+
) -> UserInstalledForwardModelStep:
|
|
48
63
|
if self.executable is not None:
|
|
49
64
|
executable = Path(self.executable)
|
|
50
65
|
if not executable.is_absolute():
|
|
51
66
|
executable = Path(config_directory) / executable
|
|
52
|
-
return
|
|
67
|
+
return UserInstalledForwardModelStep(
|
|
68
|
+
name=self.name, executable=str(executable)
|
|
69
|
+
)
|
|
53
70
|
else:
|
|
54
71
|
assert (
|
|
55
72
|
self.source is not None
|
|
@@ -59,3 +76,28 @@ class InstallJobConfig(BaseModel, extra="forbid"):
|
|
|
59
76
|
config_file=self.source,
|
|
60
77
|
name=self.name,
|
|
61
78
|
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class InstallWorkflowJobConfig(InstallJobConfig):
|
|
82
|
+
def to_ert_executable_workflow(self, config_directory: str) -> ExecutableWorkflow:
|
|
83
|
+
if self.executable is not None:
|
|
84
|
+
executable = Path(self.executable)
|
|
85
|
+
if not executable.is_absolute():
|
|
86
|
+
executable = Path(config_directory) / executable
|
|
87
|
+
return ExecutableWorkflow(
|
|
88
|
+
name=self.name,
|
|
89
|
+
min_args=None,
|
|
90
|
+
max_args=None,
|
|
91
|
+
arg_types=[],
|
|
92
|
+
executable=str(executable),
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
assert self.source is not None
|
|
96
|
+
workflow = workflow_job_from_file(
|
|
97
|
+
config_file=str(Path(config_directory) / self.source),
|
|
98
|
+
name=self.name,
|
|
99
|
+
origin="user",
|
|
100
|
+
)
|
|
101
|
+
if not isinstance(workflow, ExecutableWorkflow):
|
|
102
|
+
raise ValueError(f"Workflow must be an executable: {self.source}")
|
|
103
|
+
return workflow
|
|
@@ -4,7 +4,7 @@ from textwrap import dedent
|
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
|
-
from ert.config import
|
|
7
|
+
from ert.config import SiteOrUserForwardModelStep
|
|
8
8
|
from everest.strings import EVEREST
|
|
9
9
|
|
|
10
10
|
|
|
@@ -38,9 +38,9 @@ class InstallTemplateConfig(BaseModel, extra="forbid"):
|
|
|
38
38
|
def to_ert_forward_model_step(
|
|
39
39
|
self,
|
|
40
40
|
control_names: list[str],
|
|
41
|
-
installed_fm_steps: dict[str,
|
|
41
|
+
installed_fm_steps: dict[str, SiteOrUserForwardModelStep],
|
|
42
42
|
well_path: str,
|
|
43
|
-
) ->
|
|
43
|
+
) -> SiteOrUserForwardModelStep:
|
|
44
44
|
fm_step_instance = copy.deepcopy(installed_fm_steps.get("template_render"))
|
|
45
45
|
if fm_step_instance is None:
|
|
46
46
|
raise KeyError(
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import importlib
|
|
1
2
|
import logging
|
|
2
3
|
from textwrap import dedent
|
|
3
4
|
from typing import Any, Self
|
|
4
5
|
|
|
5
6
|
from pydantic import BaseModel, Field, model_validator
|
|
7
|
+
from ropt.workflow import find_optimizer_plugin, validate_optimizer_options
|
|
6
8
|
|
|
7
9
|
from everest.config.cvar_config import CVaRConfig
|
|
8
|
-
from everest.optimizer.utils import get_ropt_plugin_manager
|
|
9
10
|
from everest.strings import EVEREST
|
|
10
11
|
|
|
11
12
|
|
|
@@ -346,15 +347,27 @@ class OptimizationConfig(BaseModel, extra="forbid"):
|
|
|
346
347
|
else f"{self.backend}/{self.algorithm}"
|
|
347
348
|
)
|
|
348
349
|
|
|
349
|
-
|
|
350
|
-
|
|
350
|
+
try:
|
|
351
|
+
plugin_name = find_optimizer_plugin(algorithm)
|
|
352
|
+
except ValueError:
|
|
353
|
+
raise
|
|
354
|
+
except Exception as exc:
|
|
355
|
+
ert_version = importlib.metadata.version("ert")
|
|
356
|
+
ropt_version = importlib.metadata.version("ropt")
|
|
357
|
+
msg = (
|
|
358
|
+
f"Error while initializing ropt:\n\n{exc}.\n\n"
|
|
359
|
+
"There may a be version mismatch between "
|
|
360
|
+
f"ERT ({ert_version}) and ropt ({ropt_version})\n"
|
|
361
|
+
"If the installation is correct, please report this as a bug."
|
|
362
|
+
)
|
|
363
|
+
raise RuntimeError(msg) from exc
|
|
351
364
|
if plugin_name is None:
|
|
352
365
|
raise ValueError(f"Optimizer algorithm '{algorithm}' not found")
|
|
353
366
|
self._optimization_plugin_name = plugin_name
|
|
354
367
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
368
|
+
options = self.options or self.backend_options
|
|
369
|
+
if options:
|
|
370
|
+
validate_optimizer_options(algorithm, options)
|
|
358
371
|
|
|
359
372
|
self.backend = None
|
|
360
373
|
self.algorithm = algorithm
|
|
@@ -74,10 +74,16 @@ class OutputConstraintConfig(BaseModel, extra="forbid"):
|
|
|
74
74
|
@model_validator(mode="before")
|
|
75
75
|
@classmethod
|
|
76
76
|
def validate_target_or_bounds(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
77
|
-
if "target"
|
|
77
|
+
if (values.get("target") is not None) and (
|
|
78
|
+
"lower_bound" in values or "upper_bound" in values
|
|
79
|
+
):
|
|
78
80
|
raise ValueError("Can not combine target and bounds")
|
|
79
81
|
elif not any(
|
|
80
|
-
(
|
|
82
|
+
(
|
|
83
|
+
(values.get("target") is not None),
|
|
84
|
+
"lower_bound" in values,
|
|
85
|
+
"upper_bound" in values,
|
|
86
|
+
)
|
|
81
87
|
):
|
|
82
88
|
raise ValueError("Must provide target or lower_bound/upper_bound")
|
|
83
89
|
return values
|