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

Renaming hotstart option and hist fields of optimization result #191

Merged
merged 3 commits into from
Sep 4, 2024
Merged
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 ego/examples/mopta08.rs
Original file line number Diff line number Diff line change
@@ -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()
20 changes: 10 additions & 10 deletions ego/src/egor.rs
Original file line number Diff line number Diff line change
@@ -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 {
@@ -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,
}
};
@@ -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]];
@@ -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");
@@ -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}"));
@@ -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();
2 changes: 1 addition & 1 deletion ego/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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
//!
10 changes: 5 additions & 5 deletions ego/src/solver/egor_config.rs
Original file line number Diff line number Diff line change
@@ -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.
@@ -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(),
@@ -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
@@ -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
}

2 changes: 1 addition & 1 deletion ego/src/solver/egor_solver.rs
Original file line number Diff line number Diff line change
@@ -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() {
6 changes: 3 additions & 3 deletions ego/src/types.rs
Original file line number Diff line number Diff line change
@@ -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>,
}
8 changes: 4 additions & 4 deletions python/egobox/tests/test_egor.py
Original file line number Diff line number Diff line change
@@ -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"):
@@ -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)
@@ -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(
34 changes: 17 additions & 17 deletions src/egor.rs
Original file line number Diff line number Diff line change
@@ -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)
@@ -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>,
}

@@ -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]
@@ -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)]
@@ -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());
@@ -246,7 +246,7 @@ impl Egor {
n_optmod,
target,
outdir,
hot_start,
warm_start,
seed,
}
}
@@ -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(),
})
}

@@ -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,
}
}
}
@@ -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);
};
Loading