-
Notifications
You must be signed in to change notification settings - Fork 110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor control handling in everest config #9805
base: main
Are you sure you want to change the base?
Conversation
❌ 1 Tests Failed:
View the full list of 1 ❄️ flaky tests
To view more test analytics, go to the Test Analytics Dashboard |
7416b93
to
cd0bc4e
Compare
CodSpeed Performance ReportMerging #9805 will not alter performanceComparing Summary
|
cd0bc4e
to
a2b0a49
Compare
a2b0a49
to
1ffd97d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! everest2ropt is indeed much cleaner like this. I have some minor comments that you might want to look at before merging.
@property | ||
def objective_names(self) -> list[str]: | ||
return [objective.name for objective in self.objective_functions] | ||
|
||
@cached_property | ||
@property |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering, method seems unchanged and result doesn't seem to change, is there a reason we remove caching here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At some point I ran into an issue where @cached_property
did not work properly. EverestConfig
is not immutable and if you change it afterwards by assigning to it the cache is not updated. So that is a bit dangerous. There is currently an effort to make it immutable again, then we could use @cached_property
.
src/everest/config/utils.py
Outdated
var_dict["sampler_idx"] = len(self._samplers) - 1 | ||
else: | ||
if control.sampler is not None and control_sampler_idx < 0: | ||
self._samplers.append(control.sampler) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious code complexity is not checked for this (I guess pre-commit doesn't do this or there is nothing related to this that's checked), but this nesting (of if- and for-code blocks) seems quite excessive in some parts, we could split some of it up for readability, but maybe it's not worth it? Just wondering what you think!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is indeed a lot of nesting, I will have a look to reduce that.
src/everest/config/utils.py
Outdated
if control.sampler is not None and control_sampler_idx < 0: | ||
self._samplers.append(control.sampler) | ||
control_sampler_idx = len(self._samplers) - 1 | ||
var_dict["sampler_idx"] = control_sampler_idx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it ever happen that control.sampler is not None when the variable also doesn't have it's own sampler (I guess not)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I misunderstand the question, but it works like this:
- If no variable sampler is given, the control sampler will be used
- If no variable sampler is given and no controls sampler is given, that variable will not be perturbed
- If no samplers are given at all anywhere, a default sampler is used for everything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, thanks :)!
return | ||
|
||
formatted_names = [ | ||
( | ||
f"{control_name[0]}.{control_name[1]}-{control_name[2]}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have this logic twice (depending on the control_name size), is it worth making a separate class out of it (to have the logic in one place) that has a __str__
which we could use here? Maybe not necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe just have it as a property of everest config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but I think we should do this in the context of this issue: #9816
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That issue points out that the formatting is not consistent, and for input constraints it is defined here. When that issue is resolved, it could become a property of the config.
formatted_names, | ||
): | ||
if not input_constraints: | ||
def _parse_input_constraints(ever_config: EverestConfig, ropt_config): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember there was an issue some time back refactoring code to avoid using the full Everest config as function arguments. Is that not still an issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if it is an issue, but since that seems to be our policy now, I will fix it.
1ffd97d
to
4d44cab
Compare
@StephanDeHoop , @DanSava : did some refactoring, I will hold off a bit before merging in case you want to have a look. |
Looks good, thanks :)! |
Issue
The parsing code in
everest2ropt
for the controls is extremely convoluted, due to the nested character of the controls section in the configuration. This PR simplifies the parsing code by creating an intermediate class that stores the controls and its properties in a linear fashion. The relevant code ineverest2ropt
is rewritten accordingly, becoming much more easy to understand.Approach
Short description of the approach
(Screenshot of new behavior in GUI if applicable)
git rebase -i main --exec 'pytest tests/ert/unit_tests -n auto -m "not integration_test"'
)When applicable