Skip to content
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

Consolidate optimizer options and backend_options #9887

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/everest/config/optimization_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class OptimizationConfig(BaseModel, extra="forbid"): # type: ignore
the value to be equal to one.
""",
)
options: list[str] | None = Field(
options: list[str] | dict[str, Any] | None = Field(
default=None,
description="""specifies non-validated, optional
passthrough parameters for the optimizer
Expand Down
34 changes: 22 additions & 12 deletions src/everest/optimizer/everest2ropt.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import os
from typing import Any

Expand All @@ -14,6 +15,7 @@
OutputConstraintConfig,
)
from everest.config.utils import FlattenedControls, control_tuples
from everest.strings import EVEREST


def _parse_controls(ever_controls: list[ControlConfig], ropt_config):
Expand Down Expand Up @@ -279,19 +281,27 @@ def _parse_optimization(
# Handle the backend options. Due to historical reasons there two keywords:
# "options" is used to pass a list of string, "backend_options" is used to
# pass a dict. These are redirected to the same ropt option:
options = ever_opt.options or []
backend_options = ever_opt.backend_options or {}
if options and backend_options:
raise RuntimeError("Only one of 'options' and 'backend_options' allowed.")
if ever_opt.backend_options is not None:
message = (
"optimization.backend_options is deprecated. "
"Please use optimization.options instead, "
"it will accept both objects and lists of strings."
)
print(message)
logging.getLogger(EVEREST).warning(message)

options = ever_opt.options or ever_opt.backend_options or {}
verveerpj marked this conversation as resolved.
Show resolved Hide resolved

alg_const_tol = ever_opt.constraint_tolerance or None
if (
has_output_constraints
and alg_const_tol is not None
and isinstance(options, list)
):
options += [f"constraint_tolerance = {alg_const_tol}"]

# The constraint_tolerance option is only used by Dakota:
if backend == "dakota":
alg_const_tol = ever_opt.constraint_tolerance or None
if has_output_constraints and alg_const_tol is not None:
options += [f"constraint_tolerance = {alg_const_tol}"]
Copy link
Contributor Author

@yngve-sk yngve-sk Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to only be for strs beforehand, should it also be for dicts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do have a problem here. That constraint_tolerance line is dakota specific, so we should only add it if the backend is dakota. For now, do indeed just add it when the options are a list. Not for dicts.

if options:
ropt_optimizer["options"] = options
if backend_options:
ropt_optimizer["options"] = backend_options
ropt_optimizer["options"] = options

parallel = True if ever_opt.parallel is None else ever_opt.parallel
ropt_optimizer["parallel"] = True if parallel is None else parallel
Expand Down
13 changes: 8 additions & 5 deletions tests/everest/test_ropt_initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,17 @@ def test_everest2ropt_backend_options():
ropt_config = everest2ropt(config)
assert ropt_config.optimizer.options == ["test = 1"]

config.optimization.backend = "scipy"
config.optimization.backend_options = {"test": 1}
with pytest.raises(RuntimeError):
_ = everest2ropt(config)
config.optimization.backend_options = {"test": "5"} # should be disregarded
ropt_config = everest2ropt(config)
assert ropt_config.optimizer.options == ["test = 1"]

config.optimization.options = None
ropt_config = everest2ropt(config)
assert ropt_config.optimizer.options["test"] == 1
assert ropt_config.optimizer.options == {"test": "5"}

config.optimization.options = ["hey", "a=b", "c 100"]
ropt_config = everest2ropt(config)
assert ropt_config.optimizer.options == ["hey", "a=b", "c 100"]


def test_everest2ropt_samplers():
Expand Down
Loading