-
Notifications
You must be signed in to change notification settings - Fork 18
[WIP] Implement VOCS interface #281
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
base: main
Are you sure you want to change the base?
Conversation
* Internals maintain Optimas data structures * Update sampling tests
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
In updating Optimas generators for the standard, how do we deal with these extra fields in lower_bound: float
upper_bound: float
is_fidelity: Optional[bool] = False
fidelity_target_value: Optional[float] = None
default_value: Optional[float] = None
_is_fixed: bool = PrivateAttr(False) re: https://github.com/optimas-org/optimas/blob/main/optimas/core/parameter.py#L79 In the standard, variables have https://github.com/campa-consortium/generator_standard/blob/main/generator_standard/vocs.py#L16 Do we need
e.g. var1 = VaryingParameter("x0", -50.0, 5.0)
var2 = VaryingParameter("x1", -5.0, 15.0)
# Start with a fixed value of x0.
var1.fix_value(-10.0)
...
exploration.run(n_evals=5)
var1.free_value()
gen.update_parameter(var1)
exploration.run(n_evals=5) could be instructed directly to generator instead - for supporting gens. e.g. gen.fix_var('x0', -10.0) Alternatively, we could add fields to the standard, or create subclasses to Currently, I have used the following generator functions (shown with example calls) to set the Optimas internals for these, without adding to or subclassing
These are used in |
Observables (analysed parameters) in Optimas can specify a type, but this isn’t supported in the standard interface. A type is necessary for constructing a NumPy structured array (for libEnsemble). For example, in this test, the type must be a string. https://github.com/optimas-org/optimas/blob/main/tests/test_env_script.py#L27 In test_template_evaluator.py and test_function_evaluator.py it stores an array and a plot object. I have suggested we allow specifying a type for observables and constants in the standard. The standard does not support arrays generally, but I have made it possible to specify a string or a tuple for observable type, which means numpy arrays can be used. e.g. def test_template_evaluator():
# Define variables and objectives.
vocs = VOCS(
variables={"x0": [-50.0, 5.0], "x1": [-5.0, 15.0]},
objectives={"f": "MAXIMIZE"},
observables={
"p0": (float, (2, 4)),
"p1": "O",
"fig": "O",
},
)
# Define variables and objectives.
gen = RandomSamplingGenerator(vocs=vocs) |
exploration_diagnostics: exploration_diagnostics.py: test_exploration_diagnostics.py: # Check that all possible objective inputs give the same result.
_, trace1 = diags.get_objective_trace()
_, trace2 = diags.get_objective_trace("f1")
# _, trace3 = diags.get_objective_trace(obj) # Can be removed
np.testing.assert_array_equal(trace1, trace2)
# np.testing.assert_array_equal(trace1, trace3) |
Note that |
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
Small point. In outcome_constraints=["p1 <= 30"], becomes: constraints={"p1": ["LESS_THAN", 30.0]}, |
What do we do for test test_ax_single_fidelity_int. Do we need to support this? var1 = VaryingParameter("x0", -50.0, 5.0, dtype=int)
var2 = VaryingParameter("x1", -5.0, 15.0) In vocs this becomes: vocs = VOCS(
variables={"x0": set(range(-50, 6)), "x1": [-5.0, 15.0]},
objectives={"f": "MAXIMIZE"},
) I don't see anything to deal with discrete vars in Optimas, so I have converted to integer type when its a range but that seems hacky. To support this elegantly, we could bring back |
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
self._id_mapping[current_id] = { | ||
"arm_name": arm.name, | ||
"ax_trial_id": trial_index, | ||
"trial_type": trial_type, |
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 got rid of ax_trial_id
and arm_name
as parameters and just held them internally mapped to a single id. We discussed doing this before. But I don't think this works, as we may choose hi-fidelity points from a batch incorporated from previous history. And with this change, we lose that information. I would need to know ax_trial_id
and arm_name
for those historical points.
But this would not fit what vocs currently supports. ax_trial_id would be open ended integer variable, and arm is stored as a string, again open ended (not a discrete set). Maybe the could be observables, but they are created in the gen. They really just need to be known.
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.
Alt. could be for historical points, to find best points from the whole set and issue new arm_id.
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.
This is reason for:
FAILED tests/test_ax_generators.py::test_ax_multitask_with_history
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.
Following discussion, it seems we can add additional parameters to ingest (not restricted to vocs), and so these could be given to generator as extra arguments. In that case using _id
may not be necessary for this gen.
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.
So trial_type (hi/low fidelity) is now declared as a discrete variable in vocs. This is a vocs variable as it is given to each simulation. As string types are not supported in the Optimus internal VaryingParameter
structure, it converts to TrialParameter
internally.
ax_trial_id
(batch id) and arm_name
(point identifier) are set up in the gen and passed back and forth as generator specific values (not part of vocs). I have continued to use TrialParameters
so Optimas stores them in the history array and they can be read back in from previous histories. However, this does mean an Optimas format is being used in the generator.
* This way they are stored and read in from previous history * They are not part of vocs * Using TrialParameter uses already setup format in Optimas * They get put in the libE history array * trial_type is a vocs discrete, but uses TrialParameter internally
varying_parameters=[var1, var2], objectives=[obj] | ||
# TODO: Suggest supporting IntegerVariables in vocs | ||
vocs = VOCS( | ||
variables={"x0": set(range(-50, 6)), "x1": [-5.0, 15.0]}, |
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.
Is there a need for a continuous range of integers?
_, trace1 = diags.get_objective_trace() | ||
_, trace2 = diags.get_objective_trace("f1") | ||
_, trace3 = diags.get_objective_trace(obj) | ||
# _, trace3 = diags.get_objective_trace(obj) # Can be removed |
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 with removing this line (and the associated np.testing.assert_array_equal
below)
if not self._vocs.constraints: | ||
return None | ||
constraints = [] | ||
for const_name, const_spec in self._vocs.constraints.items(): |
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.
Could we raise an exception for now, saying that constraints are not supported in optimas
generators?
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 tests with constraints such as
optimas/tests/test_ax_generators.py
Line 158 in b760144
constraints={"p1": ["LESS_THAN", 30.0]}, |
name=var_name, | ||
lower_bound=sorted_values[0], | ||
upper_bound=sorted_values[-1], | ||
dtype=int, |
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.
Would this work for https://github.com/optimas-org/optimas/pull/281/files#diff-54d05e7e049beb11035069e9030950c2b1080b97631d4fa5d984eb8bfe347638R541 where the discrete variables are string?
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.
The conversion of strings was added to multitask to deal with that case. So currently I think base generator class would not work with strings. Looking at that, I think we could move that conversion to the base class so it supports strings.
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.
String type variables convert to Optimas TrialParameters because, VaryingParameters require upper/lower bounds.
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 have moved that conversion to the generator base class now. That function can be used by any Optimas generator that requires discrete variables.
This implements Step 3 in #269
For first pass, keep internals the same and implement interface:
Implementation:
validate_vocs
functionsvalidate_vocs
functions and incorporate previous check functions.validate_vocs
exceptions_id
and internal mapping - undoneChecks:
Reviewer checks:
validate_vocs
functions