Skip to content

Commit

Permalink
Renaming hotstart option and hist fields of optimization result (#…
Browse files Browse the repository at this point in the history
…191)

* Renaming hot into warm start

Hot start would correspond to argmin checkpointing (not implemented) while warm start is the optimizer starting from existing DOE file

* Renaming x_hist/y_hist inx_doe/y_doe

* Fix py test
  • Loading branch information
relf committed Sep 4, 2024
1 parent 954d24a commit e7aa1ce
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 42 deletions.
2 changes: 1 addition & 1 deletion ego/examples/mopta08.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ fn main() -> anyhow::Result<()> {
.infill_optimizer(InfillOptimizer::Slsqp)
.kpls_dim(kpls_dim)
.outdir(outdir)
.hot_start(true)
.warm_start(true)
})
.min_within(&xlimits)
.run()
Expand Down
20 changes: 10 additions & 10 deletions ego/src/egor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ impl<O: GroupFunc, SB: SurrogateBuilder> Egor<O, SB> {
OptimResult {
x_opt: result.state.get_best_param().unwrap().to_owned(),
y_opt: result.state.get_full_best_cost().unwrap().to_owned(),
x_hist: x_data,
y_hist: y_data,
x_doe: x_data,
y_doe: y_data,
state: result.state,
}
} else {
Expand All @@ -241,8 +241,8 @@ impl<O: GroupFunc, SB: SurrogateBuilder> Egor<O, SB> {
OptimResult {
x_opt: x_opt.row(0).to_owned(),
y_opt: result.state.get_full_best_cost().unwrap().to_owned(),
x_hist: x_data,
y_hist: y_data,
x_doe: x_data,
y_doe: y_data,
state: result.state,
}
};
Expand Down Expand Up @@ -413,8 +413,8 @@ mod tests {

#[test]
#[serial]
fn test_xsinx_with_hotstart_egor_builder() {
let outdir = "target/test_hotstart_01";
fn test_xsinx_with_warmstart_egor_builder() {
let outdir = "target/test_warmstart_01";
let _ = std::fs::remove_file(format!("{outdir}/{DOE_INITIAL_FILE}"));
let _ = std::fs::remove_file(format!("{outdir}/{DOE_FILE}"));
let xlimits = array![[0.0, 25.0]];
Expand All @@ -430,7 +430,7 @@ mod tests {
let doe: Array2<f64> = read_npy(&filepath).expect("file read");

let res = EgorBuilder::optimize(xsinx)
.configure(|config| config.max_iters(3).outdir(outdir).hot_start(true).seed(42))
.configure(|config| config.max_iters(3).outdir(outdir).warm_start(true).seed(42))
.min_within(&xlimits)
.run()
.expect("Egor should minimize xsinx");
Expand Down Expand Up @@ -720,13 +720,13 @@ mod tests {

#[test]
#[serial]
fn test_mixobj_mixint_hotstart_egor_builder() {
fn test_mixobj_mixint_warmstart_egor_builder() {
let env = env_logger::Env::new().filter_or("EGOBOX_LOG", "info");
let mut builder = env_logger::Builder::from_env(env);
let builder = builder.target(env_logger::Target::Stdout);
builder.try_init().ok();

let outdir = "target/test_hotstart_02";
let outdir = "target/test_warmstart_02";
let outfile = format!("{outdir}/{DOE_INITIAL_FILE}");
let _ = std::fs::remove_file(format!("{outdir}/{DOE_INITIAL_FILE}"));
let _ = std::fs::remove_file(format!("{outdir}/{DOE_FILE}"));
Expand All @@ -752,7 +752,7 @@ mod tests {
// Check that with no iteration, obj function is never called
// as the DOE does not need to be evaluated!
EgorBuilder::optimize(|_x| panic!("Should not call objective function!"))
.configure(|config| config.outdir(outdir).hot_start(true).max_iters(0).seed(42))
.configure(|config| config.outdir(outdir).warm_start(true).max_iters(0).seed(42))
.min_within_mixint_space(&xtypes)
.run()
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion ego/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! * specify the initial doe,
//! * parameterize internal optimization,
//! * parameterize mixture of experts,
//! * save intermediate results and allow hot restart,
//! * save intermediate results and allow warm restart,
//!
//! # Examples
//!
Expand Down
10 changes: 5 additions & 5 deletions ego/src/solver/egor_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub struct EgorConfig {
/// Directory to save intermediate results: inital doe + evalutions at each iteration
pub(crate) outdir: Option<String>,
/// If true use `outdir` to retrieve and start from previous results
pub(crate) hot_start: bool,
pub(crate) warm_start: bool,
/// List of x types allowing the handling of discrete input variables
pub(crate) xtypes: Vec<XType>,
/// A random generator seed used to get reproductible results.
Expand Down Expand Up @@ -108,7 +108,7 @@ impl Default for EgorConfig {
n_clusters: 1,
target: f64::NEG_INFINITY,
outdir: None,
hot_start: false,
warm_start: false,
xtypes: vec![],
seed: None,
trego: TregoConfig::default(),
Expand Down Expand Up @@ -248,7 +248,7 @@ impl EgorConfig {
self
}

/// Sets a directory to write optimization history and used as search path for hot start doe
/// Sets a directory to write optimization history and used as search path for warm start doe
pub fn outdir(mut self, outdir: impl Into<String>) -> Self {
self.outdir = Some(outdir.into());
self
Expand All @@ -260,8 +260,8 @@ impl EgorConfig {
}

/// Whether we start by loading last DOE saved in `outdir` as initial DOE
pub fn hot_start(mut self, hot_start: bool) -> Self {
self.hot_start = hot_start;
pub fn warm_start(mut self, warm_start: bool) -> Self {
self.warm_start = warm_start;
self
}

Expand Down
2 changes: 1 addition & 1 deletion ego/src/solver/egor_solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ where
let sampling = Lhs::new(&self.xlimits).with_rng(rng).kind(LhsKind::Maximin);

let hstart_doe: Option<Array2<f64>> =
if self.config.hot_start && self.config.outdir.is_some() {
if self.config.warm_start && self.config.outdir.is_some() {
let path: &String = self.config.outdir.as_ref().unwrap();
let filepath = std::path::Path::new(&path).join(DOE_FILE);
if filepath.is_file() {
Expand Down
6 changes: 3 additions & 3 deletions ego/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ pub struct OptimResult<F: Float> {
/// Optimum y value (e.g. f(x_opt))
pub y_opt: Array1<F>,
/// History of successive x values
pub x_hist: Array2<F>,
/// History of successive y values (e.g f(x_hist))
pub y_hist: Array2<F>,
pub x_doe: Array2<F>,
/// History of successive y values (e.g f(x_doe))
pub y_doe: Array2<F>,
/// EgorSolver final state
pub state: EgorState<F>,
}
Expand Down
8 changes: 4 additions & 4 deletions python/egobox/tests/test_egor.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def test_xsinx_with_reclustering(self):
self.assertAlmostEqual(-15.125, res.y_opt[0], delta=1e-3)
self.assertAlmostEqual(18.935, res.x_opt[0], delta=1e-3)

def test_xsinx_with_hotstart(self):
def test_xsinx_with_warmstart(self):
if os.path.exists("./test_dir/egor_initial_doe.npy"):
os.remove("./test_dir/egor_initial_doe.npy")
if os.path.exists("./test_dir/egor_doe.npy"):
Expand All @@ -99,7 +99,7 @@ def test_xsinx_with_hotstart(self):
self.assertAlmostEqual(-15.125, res.y_opt[0], delta=1e-3)
self.assertAlmostEqual(18.935, res.x_opt[0], delta=1e-3)

egor = egx.Egor(xlimits, outdir="./test_dir", hot_start=True)
egor = egx.Egor(xlimits, outdir="./test_dir", warm_start=True)
res = egor.minimize(xsinx, max_iters=5)
print(f"Optimization f={res.y_opt} at {res.x_opt}")
self.assertAlmostEqual(-15.125, res.y_opt[0], delta=1e-2)
Expand Down Expand Up @@ -129,8 +129,8 @@ def test_g24(self):
self.assertAlmostEqual(-5.5080, res.y_opt[0], delta=1e-2)
self.assertAlmostEqual(2.3295, res.x_opt[0], delta=1e-2)
self.assertAlmostEqual(3.1785, res.x_opt[1], delta=1e-2)
self.assertEqual((n_doe + max_iters, 2), res.x_hist.shape)
self.assertEqual((n_doe + max_iters, 1 + n_cstr), res.y_hist.shape)
self.assertEqual((n_doe + max_iters, 2), res.x_doe.shape)
self.assertEqual((n_doe + max_iters, 1 + n_cstr), res.y_doe.shape)

def test_g24_kpls(self):
egor = egx.Egor(
Expand Down
34 changes: 17 additions & 17 deletions src/egor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ pub(crate) fn to_specs(py: Python, xlimits: Vec<Vec<f64>>) -> PyResult<PyObject>
/// Known optimum used as stopping criterion.
///
/// outdir (String)
/// Directory to write optimization history and used as search path for hot start doe
/// Directory to write optimization history and used as search path for warm start doe
///
/// hot_start (bool)
/// warm_start (bool)
/// Start by loading initial doe from <outdir> directory
///
/// seed (int >= 0)
Expand All @@ -161,7 +161,7 @@ pub(crate) struct Egor {
pub n_optmod: usize,
pub target: f64,
pub outdir: Option<String>,
pub hot_start: bool,
pub warm_start: bool,
pub seed: Option<u64>,
}

Expand All @@ -172,9 +172,9 @@ pub(crate) struct OptimResult {
#[pyo3(get)]
y_opt: Py<PyArray1<f64>>,
#[pyo3(get)]
x_hist: Py<PyArray2<f64>>,
x_doe: Py<PyArray2<f64>>,
#[pyo3(get)]
y_hist: Py<PyArray2<f64>>,
y_doe: Py<PyArray2<f64>>,
}

#[pymethods]
Expand All @@ -199,7 +199,7 @@ impl Egor {
n_optmod = 1,
target = f64::NEG_INFINITY,
outdir = None,
hot_start = false,
warm_start = false,
seed = None
))]
#[allow(clippy::too_many_arguments)]
Expand All @@ -223,7 +223,7 @@ impl Egor {
n_optmod: usize,
target: f64,
outdir: Option<String>,
hot_start: bool,
warm_start: bool,
seed: Option<u64>,
) -> Self {
let doe = doe.map(|x| x.to_owned_array());
Expand All @@ -246,7 +246,7 @@ impl Egor {
n_optmod,
target,
outdir,
hot_start,
warm_start,
seed,
}
}
Expand Down Expand Up @@ -286,13 +286,13 @@ impl Egor {
});
let x_opt = res.x_opt.into_pyarray_bound(py).to_owned();
let y_opt = res.y_opt.into_pyarray_bound(py).to_owned();
let x_hist = res.x_hist.into_pyarray_bound(py).to_owned();
let y_hist = res.y_hist.into_pyarray_bound(py).to_owned();
let x_doe = res.x_doe.into_pyarray_bound(py).to_owned();
let y_doe = res.y_doe.into_pyarray_bound(py).to_owned();
Ok(OptimResult {
x_opt: x_opt.into(),
y_opt: y_opt.into(),
x_hist: x_hist.into(),
y_hist: y_hist.into(),
x_doe: x_doe.into(),
y_doe: y_doe.into(),
})
}

Expand Down Expand Up @@ -367,13 +367,13 @@ impl Egor {
let idx = find_best_result_index(&y_doe, &self.cstr_tol());
let x_opt = x_doe.row(idx).to_pyarray_bound(py).into();
let y_opt = y_doe.row(idx).to_pyarray_bound(py).into();
let x_hist = x_doe.to_pyarray_bound(py).into();
let y_hist = y_doe.to_pyarray_bound(py).into();
let x_doe = x_doe.to_pyarray_bound(py).into();
let y_doe = y_doe.to_pyarray_bound(py).into();
OptimResult {
x_opt,
y_opt,
x_hist,
y_hist,
x_doe,
y_doe,
}
}
}
Expand Down Expand Up @@ -462,7 +462,7 @@ impl Egor {
.trego(self.trego)
.n_optmod(self.n_optmod)
.target(self.target)
.hot_start(self.hot_start); // when used as a service no hotstart
.warm_start(self.warm_start); // when used as a service no warmstart
if let Some(doe) = doe {
config = config.doe(doe);
};
Expand Down

0 comments on commit e7aa1ce

Please sign in to comment.