Skip to content

Commit

Permalink
Fix doc tests
Browse files Browse the repository at this point in the history
  • Loading branch information
relf committed Nov 18, 2023
1 parent 6bfb21e commit 65508bb
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 64 deletions.
2 changes: 1 addition & 1 deletion ego/src/egor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ impl<O: GroupFunc> EgorBuilder<O> {
};
Egor {
fobj: ObjFunc::new(self.fobj),
solver: EgorSolver::new_with_xtypes(xtypes, rng),
solver: EgorSolver::new_with_xtypes(self.config, xtypes, rng),
}
}
}
Expand Down
61 changes: 33 additions & 28 deletions ego/src/egor_service.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
//! Egor optimizer service implements Egor optimizer with an ask-and-tell interface.
//! Egor optimizer service implements [`Egor`] optimizer with an ask-and-tell interface.
//! It allows to keep the control on the iteration loop by asking for optimum location
//! suggestions and telling objective function values at these points.
//!
//! ```no_run
//! # use ndarray::{array, Array2, ArrayView1, ArrayView2, Zip};
//! # use ndarray::{array, Array2, ArrayView1, ArrayView2, Zip, concatenate, Axis};
//! # use egobox_doe::{Lhs, SamplingMethod};
//! # use egobox_ego::{EgorBuilder, InfillStrategy, InfillOptimizer};
//! # use egobox_ego::{EgorServiceBuilder, InfillStrategy, RegressionSpec, CorrelationSpec};
//!
//! # use rand_xoshiro::Xoshiro256Plus;
//! # use ndarray_rand::rand::SeedableRng;
//! use argmin_testfunctions::rosenbrock;
//!
//! // Rosenbrock test function: minimum y_opt = 0 at x_opt = (1, 1)
//! fn rosenb(x: &ArrayView2<f64>) -> Array2<f64> {
//! let mut y: Array2<f64> = Array2::zeros((x.nrows(), 1));
//! Zip::from(y.rows_mut())
//! .and(x.rows())
//! .par_for_each(|mut yi, xi| yi.assign(&array![rosenbrock(&xi.to_vec(), 1., 100.)]));
//! y
//! fn xsinx(x: &ArrayView2<f64>) -> Array2<f64> {
//! (x - 3.5) * ((x - 3.5) / std::f64::consts::PI).mapv(|v| v.sin())
//! }
//!
//! let xlimits = array![[-2., 2.], [-2., 2.]];
//! // TODO
//! //let res = EgorBuilder::optimize(rosenb)
//! // .min_within(&xlimits)
//! // .infill_strategy(InfillStrategy::EI)
//! // .n_doe(10)
//! // .target(1e-1)
//! // .n_iter(30)
//! // .run()
//! // .expect("Rosenbrock minimization");
//! //println!("Rosenbrock min result = {:?}", res);
//! let egor = EgorServiceBuilder::optimize()
//! .configure(|conf| {
//! conf.regression_spec(RegressionSpec::ALL)
//! .correlation_spec(CorrelationSpec::ALL)
//! .infill_strategy(InfillStrategy::EI)
//! })
//! .random_seed(42)
//! .min_within(&array![[0., 25.]]);
//!
//! let mut doe = array![[0.], [7.], [20.], [25.]];
//! let mut y_doe = xsinx(&doe.view());
//!
//! for _i in 0..10 {
//! // we tell function values and ask for next suggested optimum location
//! let x_suggested = egor.suggest(&doe, &y_doe);
//!
//! // we update the doe
//! doe = concatenate![Axis(0), doe, x_suggested];
//! y_doe = xsinx(&doe.view());
//! }
//!
//! println!("Rosenbrock min result = {:?}", doe);
//! ```
//!
use crate::egor_config::*;
Expand All @@ -42,7 +50,7 @@ use ndarray_rand::rand::SeedableRng;
use rand_xoshiro::Xoshiro256Plus;

/// EGO optimizer service builder allowing to use Egor optimizer
/// with an ask-and-tell interface.
/// as a service.
///
pub struct EgorServiceBuilder {
config: EgorConfig,
Expand Down Expand Up @@ -104,23 +112,20 @@ impl EgorServiceBuilder {
};
EgorService {
config: self.config.clone(),
solver: EgorSolver::new_with_xtypes(xtypes, rng),
solver: EgorSolver::new_with_xtypes(self.config, xtypes, rng),
}
}
}

/// Egor optimizer structure used to parameterize the underlying `argmin::Solver`
/// and trigger the optimization using `argmin::Executor`.
/// Egor optimizer service.
#[derive(Clone)]
pub struct EgorService<SB: SurrogateBuilder> {
#[allow(dead_code)]
config: EgorConfig,
solver: EgorSolver<SB>,
}

impl<SB: SurrogateBuilder> EgorService<SB> {
#[allow(dead_code)]
fn configure<F: FnOnce(EgorConfig) -> EgorConfig>(mut self, init: F) -> Self {
pub fn configure<F: FnOnce(EgorConfig) -> EgorConfig>(mut self, init: F) -> Self {
self.config = init(self.config);
self
}
Expand Down
19 changes: 11 additions & 8 deletions ego/src/egor_solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! ```no_run
//! use ndarray::{array, Array2, ArrayView1, ArrayView2, Zip};
//! use egobox_doe::{Lhs, SamplingMethod};
//! use egobox_ego::{EgorBuilder, InfillStrategy, InfillOptimizer, ObjFunc, EgorSolver};
//! use egobox_ego::{EgorBuilder, EgorConfig, InfillStrategy, InfillOptimizer, ObjFunc, EgorSolver};
//! use egobox_moe::MoeParams;
//! use rand_xoshiro::Xoshiro256Plus;
//! use ndarray_rand::rand::SeedableRng;
Expand All @@ -27,7 +27,8 @@
//! let rng = Xoshiro256Plus::seed_from_u64(42);
//! let xlimits = array![[-2., 2.], [-2., 2.]];
//! let fobj = ObjFunc::new(rosenb);
//! let solver: EgorSolver<MoeParams<f64, Xoshiro256Plus>> = EgorSolver::new(&xlimits, rng);
//! let config = EgorConfig::default();
//! let solver: EgorSolver<MoeParams<f64, Xoshiro256Plus>> = EgorSolver::new(config, &xlimits, rng);
//! let res = Executor::new(fobj, solver)
//! .configure(|state| state.max_iters(20))
//! .run()
Expand All @@ -46,7 +47,7 @@
//! ```no_run
//! use ndarray::{array, Array2, ArrayView1, ArrayView2, Zip};
//! use egobox_doe::{Lhs, SamplingMethod};
//! use egobox_ego::{EgorBuilder, InfillStrategy, InfillOptimizer, ObjFunc, EgorSolver};
//! use egobox_ego::{EgorBuilder, EgorConfig, InfillStrategy, InfillOptimizer, ObjFunc, EgorSolver};
//! use egobox_moe::MoeParams;
//! use rand_xoshiro::Xoshiro256Plus;
//! use ndarray_rand::rand::SeedableRng;
Expand Down Expand Up @@ -84,14 +85,17 @@
//! let doe = Lhs::new(&xlimits).sample(10);
//!
//! let fobj = ObjFunc::new(f_g24);
//! let solver: EgorSolver<MoeParams<f64, Xoshiro256Plus>> =
//! EgorSolver::new(&xlimits, rng)
//!
//! let config = EgorConfig::default()
//! .n_cstr(2)
//! .infill_strategy(InfillStrategy::EI)
//! .infill_optimizer(InfillOptimizer::Cobyla)
//! .doe(&doe)
//! .target(-5.5080);
//!
//! let solver: EgorSolver<MoeParams<f64, Xoshiro256Plus>> =
//! EgorSolver::new(config, &xlimits, rng);
//!
//! let res = Executor::new(fobj, solver)
//! .configure(|state| state.max_iters(40))
//! .run()
Expand Down Expand Up @@ -238,7 +242,7 @@ impl<SB: SurrogateBuilder> EgorSolver<SB> {
///
/// The function `f` should return an objective but also constraint values if any.
/// Design space is specified by a list of types for input variables `x` of `f` (see [`XType`]).
pub fn new_with_xtypes(xtypes: &[XType], rng: Xoshiro256Plus) -> Self {
pub fn new_with_xtypes(config: EgorConfig, xtypes: &[XType], rng: Xoshiro256Plus) -> Self {
let env = Env::new().filter_or("EGOBOX_LOG", "info");
let mut builder = Builder::from_env(env);
let builder = builder.target(env_logger::Target::Stdout);
Expand All @@ -248,7 +252,7 @@ impl<SB: SurrogateBuilder> EgorSolver<SB> {
config: EgorConfig {
xtypes: Some(v_xtypes),
no_discrete: no_discrete(xtypes),
..EgorConfig::default()
..config
},
xlimits: unfold_xtypes_as_continuous_limits(xtypes),
surrogate_builder: SB::new_with_xtypes_rng(xtypes),
Expand Down Expand Up @@ -653,7 +657,6 @@ where
lhs_optim,
) {
Ok(xk) => {
println!(">>>>>>>>>> {}", self.config.n_cstr);
match self.get_virtual_point(&xk, y_data, obj_model.as_ref(), cstr_models) {
Ok(yk) => {
y_dat = concatenate![
Expand Down
42 changes: 15 additions & 27 deletions ego/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
//!
//! // We ask for 10 evaluations of the objective function to get the result
//! let res = EgorBuilder::optimize(xsinx)
//! .configure(|config| config.n_iter(10))
//! .min_within(&array![[0.0, 25.0]])
//! .n_iter(10)
//! .run()
//! .expect("xsinx minimized");
//! println!("Minimum found f(x) = {:?} at x = {:?}", res.x_opt, res.y_opt);
Expand Down Expand Up @@ -100,11 +100,9 @@
//! approximating your objective function.
//!
//! ```no_run
//! # use egobox_ego::{EgorBuilder};
//! # use ndarray::{array, Array2, ArrayView2};
//! # fn fobj(x: &ArrayView2<f64>) -> Array2<f64> { x.to_owned() }
//! # let egor = EgorBuilder::optimize(fobj).min_within(&array![[-1., 1.]]);
//! egor.n_doe(100);
//! # use egobox_ego::{EgorConfig};
//! # let egor_config = EgorConfig::default();
//! egor_config.n_doe(100);
//! ```
//!
//! You can also provide your initial doe though the `egor.doe(your_doe)` method.
Expand All @@ -114,35 +112,27 @@
//! Gaussian process will be built using the `ndim` (usually 3 or 4) main components in the PLS projected space.
//!
//! ```no_run
//! # use egobox_ego::{EgorBuilder};
//! # use ndarray::{array, Array2, ArrayView2};
//! # fn fobj(x: &ArrayView2<f64>) -> Array2<f64> { x.to_owned() }
//! # let egor = EgorBuilder::optimize(fobj).min_within(&array![[-1., 1.]]);
//! egor.kpls_dim(3);
//! # let egor_config = egobox_ego::EgorConfig::default();
//! egor_config.kpls_dim(3);
//! ```
//!
//! * Specifications of constraints (expected to be negative at the end of the optimization)
//! In this example below we specify that 2 constraints will be computed with the objective values meaning
//! the objective function is expected to return an array '\[nsamples, 1 obj value + 2 const values\]'.
//!
//! ```no_run
//! # use egobox_ego::{EgorBuilder};
//! # use ndarray::{array, Array2, ArrayView2};
//! # fn fobj(x: &ArrayView2<f64>) -> Array2<f64> { x.to_owned() }
//! # let egor = EgorBuilder::optimize(fobj).min_within(&array![[-1., 1.]]);
//! egor.n_cstr(2);
//! # let egor_config = egobox_ego::EgorConfig::default();
//! egor_config.n_cstr(2);
//! ```
//!
//! * If the default infill strategy (WB2, Watson and Barnes 2nd criterion),
//! you can switch for either EI (Expected Improvement) or WB2S (scaled version of WB2).
//! See \[[Priem2019](#Priem2019)\]
//!
//! ```no_run
//! # use egobox_ego::{EgorBuilder, InfillStrategy};
//! # use ndarray::{array, Array2, ArrayView2};
//! # fn fobj(x: &ArrayView2<f64>) -> Array2<f64> { x.to_owned() }
//! # let egor = EgorBuilder::optimize(fobj).min_within(&array![[-1., 1.]]);
//! egor.infill_strategy(InfillStrategy::EI);
//! # use egobox_ego::{EgorConfig, InfillStrategy};
//! # let egor_config = EgorConfig::default();
//! egor_config.infill_strategy(InfillStrategy::EI);
//! ```
//!
//! * The default gaussian process surrogate is parameterized with a constant trend and a squared exponential correlation kernel, also
Expand All @@ -151,12 +141,10 @@
//! approximation (quality tested through cross validation).
//!
//! ```no_run
//! # use egobox_ego::{EgorBuilder, RegressionSpec, CorrelationSpec};
//! # use ndarray::{array, Array2, ArrayView2};
//! # fn fobj(x: &ArrayView2<f64>) -> Array2<f64> { x.to_owned() }
//! # let egor = EgorBuilder::optimize(fobj).min_within(&array![[-1., 1.]]);
//! egor.regression_spec(RegressionSpec::CONSTANT | RegressionSpec::LINEAR)
//! .correlation_spec(CorrelationSpec::MATERN32 | CorrelationSpec::MATERN52);
//! # use egobox_ego::{EgorConfig, RegressionSpec, CorrelationSpec};
//! # let egor_config = EgorConfig::default();
//! egor_config.regression_spec(RegressionSpec::CONSTANT | RegressionSpec::LINEAR)
//! .correlation_spec(CorrelationSpec::MATERN32 | CorrelationSpec::MATERN52);
//! ```
//! In the above example all GP with combinations of regression and correlation will be tested and the best combination for
//! each modeled function will be retained. You can also simply specify `RegressionSpec::ALL` and `CorrelationSpec::ALL` to
Expand Down

0 comments on commit 65508bb

Please sign in to comment.