Skip to content

Commit 2b34020

Browse files
Yngve S. Kristiansenjonathan-eq
authored andcommitted
Use objectives & constraints from ert storage
1 parent 19f5d21 commit 2b34020

5 files changed

Lines changed: 36 additions & 86 deletions

File tree

src/ert/run_models/everest_run_model.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,6 @@ def run_experiment(
720720
)
721721

722722
self._ever_storage.init(
723-
objective_functions=self.objectives_config,
724-
output_constraints=self.output_constraints_config,
725723
realizations=self.model.realizations,
726724
)
727725
optimizer.set_results_callback(self._handle_optimizer_results)

src/everest/api/everest_data_api.py

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,7 @@ def accepted_batches(self) -> list[int]:
3030

3131
@property
3232
def objective_function_names(self) -> list[str]:
33-
if self._ever_storage.objective_functions is None:
34-
return []
35-
return sorted(
36-
self._ever_storage.objective_functions["objective_name"].unique().to_list()
37-
)
33+
return self._ever_storage.objective_functions.keys
3834

3935
@property
4036
def output_constraint_names(self) -> list[str]:
@@ -87,26 +83,22 @@ def control_values(self) -> list[dict[str, Any]]:
8783
@property
8884
def objective_values(self) -> list[dict[str, Any]]:
8985
obj_values = []
86+
87+
objectives = self._ever_storage.objective_functions
9088
for b in self._ever_storage.batches_with_function_results:
9189
for (
9290
model_realization,
9391
simulation_id,
9492
), df in b.realization_objectives.sort(
9593
["realization", "simulation_id"]
9694
).group_by(["realization", "simulation_id"], maintain_order=True):
97-
for obj_dict in (
98-
self._ever_storage.objective_functions.sort(
99-
["objective_name"]
100-
).to_dicts()
101-
if self._ever_storage.objective_functions is not None
102-
else []
95+
for key, scale, weight in zip(
96+
objectives.keys, objectives.scales, objectives.weights, strict=False
10397
):
104-
obj_name = obj_dict["objective_name"]
105-
obj_value = df[obj_name].item()
106-
98+
obj_value = float(df[key].item())
10799
if obj_value is None:
108100
logger.error(
109-
f"Objective {obj_name} has no value for "
101+
f"Objective {key} has no value for "
110102
f"batch {b.batch_id}, "
111103
f"model realization {model_realization},"
112104
f"simulation id {simulation_id}. "
@@ -119,10 +111,10 @@ def objective_values(self) -> list[dict[str, Any]]:
119111
"batch": int(b.batch_id),
120112
"realization": int(model_realization),
121113
"simulation": int(simulation_id),
122-
"function": obj_name,
123-
"scale": float(obj_dict["scale"]),
124-
"value": float(obj_value),
125-
"weight": float(obj_dict["weight"]),
114+
"function": key,
115+
"scale": float(scale) if scale is not None else None,
116+
"value": obj_value,
117+
"weight": float(weight) if weight is not None else None,
126118
}
127119
)
128120

@@ -140,18 +132,16 @@ def single_objective_values(self) -> list[dict[str, Any]]:
140132
)
141133
objectives = self._ever_storage.objective_functions
142134
assert objectives is not None
143-
objective_names = objectives["objective_name"].unique().to_list()
144-
145-
for o in objectives.to_dicts():
146-
batch_datas = batch_datas.with_columns(
147-
pl.col(o["objective_name"]) * o["weight"] / o["scale"]
148-
)
149135

136+
for name, weight, scale in zip(
137+
objectives.keys, objectives.scales, objectives.weights, strict=False
138+
):
139+
batch_datas = batch_datas.with_columns(pl.col(name) * weight / scale)
150140
columns = [
151141
"batch",
152142
"objective",
153143
"accepted",
154-
*(objective_names if len(objective_names) > 1 else []),
144+
*(objectives.keys if len(objectives.keys) > 1 else []),
155145
]
156146

157147
return (

src/everest/everest_storage.py

Lines changed: 8 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import traceback
66
from functools import cached_property
77
from pathlib import Path
8-
from typing import Any, ClassVar, TypedDict
8+
from typing import Any, ClassVar, TypedDict, cast
99
from uuid import UUID
1010

1111
import numpy as np
1212
import polars as pl
1313
from ropt.results import FunctionResults, GradientResults, Results
1414

15-
from ert.config import EverestConstraintsConfig, EverestObjectivesConfig
15+
from ert.config import EverestObjectivesConfig
1616
from ert.storage import LocalEnsemble, LocalExperiment, LocalStorage, open_storage
1717
from ert.storage.local_ensemble import BatchDataframes
1818
from everest.strings import EVEREST
@@ -25,8 +25,6 @@ def try_read_df(path: Path) -> pl.DataFrame | None:
2525

2626

2727
class OptimizationDataframes(TypedDict, total=False):
28-
objective_functions: pl.DataFrame | None
29-
nonlinear_constraints: pl.DataFrame | None
3028
realization_weights: pl.DataFrame | None
3129

3230

@@ -260,8 +258,6 @@ class _GradientResults(TypedDict):
260258

261259
class EverestStorage:
262260
EXPERIMENT_DATAFRAMES: ClassVar[list[str]] = [
263-
"objective_functions",
264-
"nonlinear_constraints",
265261
"realization_weights",
266262
]
267263

@@ -319,8 +315,12 @@ def control_names(self) -> list[str]:
319315
return self.experiment.parameter_keys
320316

321317
@property
322-
def objective_functions(self) -> pl.DataFrame | None:
323-
return pl.read_parquet(self.experiment._path / "objective_functions.parquet")
318+
def objective_functions(self) -> EverestObjectivesConfig:
319+
objectives_config = self.experiment.response_configuration.get(
320+
"everest_objectives"
321+
)
322+
assert objectives_config is not None
323+
return cast(EverestObjectivesConfig, objectives_config)
324324

325325
@property
326326
def nonlinear_constraints(self) -> list[str]:
@@ -483,38 +483,8 @@ def batches(self) -> list[BatchStorageData]:
483483

484484
def init(
485485
self,
486-
objective_functions: EverestObjectivesConfig,
487-
output_constraints: EverestConstraintsConfig | None,
488486
realizations: list[int],
489487
) -> None:
490-
weights = np.fromiter(
491-
(
492-
1.0 if weight is None else weight
493-
for weight in objective_functions.weights
494-
),
495-
dtype=np.float64,
496-
)
497-
498-
objective_functions_dataframe = pl.DataFrame(
499-
{
500-
"objective_name": objective_functions.keys,
501-
"weight": pl.Series(weights / sum(weights), dtype=pl.Float64),
502-
"scale": pl.Series(
503-
[
504-
1.0 if scale is None else scale
505-
for scale in objective_functions.scales
506-
],
507-
dtype=pl.Float64,
508-
),
509-
}
510-
)
511-
512-
nonlinear_constraints = (
513-
pl.DataFrame({"constraint_name": output_constraints.keys})
514-
if output_constraints
515-
else None
516-
)
517-
518488
realization_weights = pl.DataFrame(
519489
{
520490
"realization": pl.Series(realizations, dtype=pl.UInt32),
@@ -523,15 +493,9 @@ def init(
523493

524494
self.save_experiment_dataframes(
525495
dataframes={
526-
"objective_functions": objective_functions_dataframe,
527-
"nonlinear_constraints": nonlinear_constraints,
528496
"realization_weights": realization_weights, # Store in metadata
529497
},
530498
experiment_path=self.experiment._path,
531-
# Note: Write storage is held by ERT runmodel, hence we need to bypass
532-
# the read/write, this should/could be synced better up between ERT /
533-
# everest storage. Ideally Everest would have its own "write" priviliege
534-
# for dumping optimization results.
535499
)
536500

537501
@classmethod

tests/everest/snapshots/test_api_snapshots/test_api_snapshots/config_multiobj.yml/snapshot.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@
111111
"scale": 0.66666667,
112112
"simulation": 0,
113113
"value": -0.75,
114-
"weight": 0.66666667
114+
"weight": 0.5
115115
},
116116
{
117117
"batch": 0,
@@ -120,7 +120,7 @@
120120
"scale": 1.0,
121121
"simulation": 0,
122122
"value": -4.75,
123-
"weight": 0.33333333
123+
"weight": 0.25
124124
},
125125
{
126126
"batch": 1,
@@ -129,7 +129,7 @@
129129
"scale": 0.66666667,
130130
"simulation": 0,
131131
"value": -0.76564598,
132-
"weight": 0.66666667
132+
"weight": 0.5
133133
},
134134
{
135135
"batch": 1,
@@ -138,7 +138,7 @@
138138
"scale": 1.0,
139139
"simulation": 0,
140140
"value": -4.70363998,
141-
"weight": 0.33333333
141+
"weight": 0.25
142142
},
143143
{
144144
"batch": 2,
@@ -147,7 +147,7 @@
147147
"scale": 0.66666667,
148148
"simulation": 0,
149149
"value": -0.50778502,
150-
"weight": 0.66666667
150+
"weight": 0.5
151151
},
152152
{
153153
"batch": 2,
@@ -156,7 +156,7 @@
156156
"scale": 1.0,
157157
"simulation": 0,
158158
"value": -4.47678995,
159-
"weight": 0.33333333
159+
"weight": 0.25
160160
}
161161
],
162162
"optimal_result_json": {
@@ -179,22 +179,22 @@
179179
{
180180
"accepted": 1,
181181
"batch": 0,
182-
"distance_p": -0.75,
183-
"distance_q": -1.58333333,
182+
"distance_p": -1.0,
183+
"distance_q": -19.0,
184184
"objective": -2.08333333
185185
},
186186
{
187187
"accepted": 1,
188188
"batch": 1,
189-
"distance_p": -0.76564598,
190-
"distance_q": -1.56787999,
189+
"distance_p": -1.02086131,
190+
"distance_q": -18.81455994,
191191
"objective": -2.07831065
192192
},
193193
{
194194
"accepted": 1,
195195
"batch": 2,
196-
"distance_p": -0.50778502,
197-
"distance_q": -1.49226332,
196+
"distance_p": -0.6770467,
197+
"distance_q": -17.90715981,
198198
"objective": -1.83078667
199199
}
200200
]

tests/everest/test_everest_storage.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ def test_csv_export(config_file, cached_example, snapshot):
3434
storage_path=config.storage_dir,
3535
)
3636
ever_storage.init(
37-
objective_functions=config.create_ert_objectives_config(),
38-
output_constraints=config.create_ert_output_constraints_config(),
3937
realizations=config.model.realizations,
4038
)
4139
combined_df, pert_real_df, batch_df = ever_storage.export_dataframes()

0 commit comments

Comments
 (0)