-
Notifications
You must be signed in to change notification settings - Fork 29
APOSMM accepts an initial sample, via ingest #1616
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
APOSMM accepts an initial sample, via ingest #1616
Conversation
… an attempt to make the arg perform an extra receive so the user can pass in those values. add the boilerplate for an extra test
…an happen as expected
…ust pass the data as-is into the gen_f
…ition where aposmm receives until enough have been received, then local_H is updated with the method used when libE has returned points. Then fix something_sent condition. Also the update_local_H_after_receiving resizes local_H in this initialization routine. Then in generators.py, ensure additionally that Work can ingest points without sim_id needing to be in results. Assume that an np.arange is good enough
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## experimental/jlnav_plus_shuds_asktell #1616 +/- ##
=========================================================================
- Coverage 47.95% 47.66% -0.29%
=========================================================================
Files 80 80
Lines 8079 8125 +46
Branches 1222 1234 +12
=========================================================================
- Hits 3874 3873 -1
- Misses 3985 4032 +47
Partials 220 220 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
0dfae0a to
5dc5155
Compare
…, primarily displaying a series of warnings about the characteristics of vocs
…interacting with the aposmm class may fail. add supported globus_compute_sdk version to dev env
|
This should work import numpy as np
from xopt import Xopt
from libensemble.gen_classes.aposmm import APOSMM
from xopt import Evaluator
from gest_api.vocs import VOCS
import pdb_si
def six_hump_camel(H, _, sim_specs):
"""Six-Hump Camel sim_f."""
batch = len(H["x"]) # Num evaluations each sim_f call.
H_o = np.zeros(batch, dtype=sim_specs["out"]) # Define output array H
for i, x in enumerate(H["x"]):
H_o["f"][i] = six_hump_camel_func(x) # Function evaluations placed into H
return H_o
def six_hump_camel_func(x):
"""Six-Hump Camel function definition"""
x1 = x[0]
x2 = x[1]
term1 = (4 - 2.1 * x1**2 + (x1**4) / 3) * x1**2
term2 = x1 * x2
term3 = (-4 + 4 * x2**2) * x2**2
return term1 + term2 + term3
def evaluator_function(inputs):
return {"f": six_hump_camel_func([inputs["x0"], inputs["x1"]])}
evaluator = Evaluator(function=evaluator_function)
vocs = VOCS(
variables={
"x0": [-2.0,2.0],
"x1": [-1.0,1.0],
"x0_on_cube": [0.0,1.0],
"x1_on_cube": [0.0,1.0],
},
objectives={"f": "MINIMIZE"},
)
variables_mapping = {
"x": ["x0", "x1"],
"x_on_cube": ["x0_on_cube", "x1_on_cube"],
}
max_active_runs = 1
initial_sample_size = 20
gen = APOSMM(vocs=vocs, max_active_runs=max_active_runs, initial_sample_size=initial_sample_size, variables_mapping=variables_mapping)
X = Xopt(vocs=vocs, evaluator=evaluator, generator=gen)
X.random_evaluate(10)
X.step()
for i in range(30):
print(i)
X.step()
Also should work if use suggest instead of ingest, unless we decided not. We can put a |
| initial_sample_size=6, | ||
| variables_mapping=variables_mapping, | ||
| ... | ||
| do_not_produce_sample_points=True, |
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 dont actually want to call it this
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.
And when using aposmm.py i think it should default to True.
Or maybe call generate_sample and True default in persistent_aposmm but sets to false by default in aposm.py
libensemble/gen_classes/aposmm.py
Outdated
| do_not_produce_sample_points: bool = False | ||
| If `True`, APOSMM can ingest sample points (with matching objective values) |
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.
what about suggest?
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.
Do we support them starting with suggest.
| """ | ||
|
|
||
| def _validate_vocs(self, vocs: VOCS): | ||
| if len(vocs.constraints): |
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 aposmm support constraints
| def _validate_vocs(self, vocs: VOCS): | ||
| if len(vocs.constraints): | ||
| warnings.warn("APOSMM's constraints are provided as keyword arguments on initialization.") | ||
| if len(vocs.constants): |
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.
same for constants.
| UNEXPECTED_SIMID_ERR = """APOSMM received unexpected input data. | ||
| APOSMM *typically* expects to provide sample points itself following initialization. | ||
| If you wish to provide sample points with matching objective values to APOSMM, |
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 would say evaluated points, "matching objective values" is a bit confusing. Matching with what...
|
Does it support the rule, once a suggest() is called, you cannot give more pre-evaluated points (points with no _id). |
|
How is "_id" not overwritten still in calling structure?
for entry in list_dicts:
if "_id" in entry:
entry["sim_id"] = entry.pop("_id")which overwrites the structure in user space. Did you look at using if "sim_id" not in self.variables_mapping:
self.variables_mapping["sim_id"] = ["_id"]in generators.py? |
|
"Fix various circumstances and conditions where specifying sim_id shouldn't be necessary." I know of only one - giving pre-evaluated points. |
…ing message. appends _id to sim_id mapping in generators.py and removes the associated pop in misc.py
|
Given our rule that sample is either all ingest or all suggest. I dont think the |
… using as indexes later). need to accomodate circumstance where we have set up a sim_id <- _id mapping, but no input _id data is appearing, since this is acceptable for an initial sample
…djust tests to match expected behavior
…t or ingest is called first
…eError on unexpected usage instead of failing/returning silently. Additional tests for coverage
…larifying comments
|
why set in not first call??? |
libensemble/gen_classes/aposmm.py
Outdated
| warnings.warn("APOSMM does not support constraints in VOCS. Ignoring.") | ||
| if len(vocs.constants): | ||
| warnings.warn("APOSMM does not support constants in VOCS. Ignoring.") | ||
| if len(vocs.observables): |
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.
aposmm DOES support observables, it may not do anything with them, but we use them in multiple examples, including critically in IBCDFO.
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 actually we do use them as fvec is returned as observables.
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.
And gradients can be also.
libensemble/gen_classes/aposmm.py
Outdated
| def suggest_numpy(self, num_points: int = 0) -> npt.NDArray: | ||
| """Request the next set of points to evaluate, as a NumPy array.""" | ||
|
|
||
| if not self._first_call: |
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.
name should be _first_call_type or _initial_call_type and test should be that its None.
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.
Also I think longer term this should be a option for all libE gens like this so would go in generators.py just before setup is called.
libensemble/gen_classes/aposmm.py
Outdated
| retrieved via `.suggest()`, updated with objective values, and ingested via `.ingest()`. | ||
| ```python | ||
| gen = APOSMM(vocs, max_active_runs=2, initial_sample_size=10, generate_sample_points=True) |
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 thought we dont need this option now.
|
Nevermind I fixed it! |
…o the gen_f. add a initialize_dists_and_inds call upon the initial sample being ingested in, inside update_local_H_after_receiving
|
I think we may have to change using variables_mapping. It maybe that we always convert _id to sim_id and vice versa as this can happen in either direction. E.g. listdicts_2_np xopt ingests on libE gen: libE calls suggest() on gest-api gen: So conversion always needs to happen. We could address that on another branch |
shuds13
left a comment
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.
Will need to resolve conflicts
3daf0c1
into
experimental/jlnav_plus_shuds_asktell
Based on concepts and keyword argument names from shuds' #1615 .
do_not_produce_sample_pointsfield, specifying to APOSMM that user will ingest first.sim_idshouldn't be necessary.initial_sample_sizepoints received. Then updatelocal_Has though "actual" evaluations were received.ingestfirst on an interfacer generator starts the background process.