Skip to content

Commit

Permalink
Egor ask-and-tell interface (#116)
Browse files Browse the repository at this point in the history
* Implement suggest in dedicated EgorService

* Refactor Egor configuration

* Create EgorConfig
* Add configure method to Egor builders

* Add an example of optimization as a service

* Fix doc tests

* Move random_seed setting in configuration

* Fix poetry config

* Rename n_iter in max_iters

* Rename n_iter in max_iters in Python code

* Make Egor.suggest available in Python

* Adjust Python tests to new API

* Refactoring

* Add get_result for ask-and-tell interface

* Add exmaple Egor as a service
  • Loading branch information
relf authored Nov 30, 2023
1 parent a1384e1 commit 2227e1b
Show file tree
Hide file tree
Showing 17 changed files with 1,821 additions and 1,291 deletions.
1,388 changes: 759 additions & 629 deletions doc/Egor_Tutorial.ipynb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions doe/src/lhs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,10 @@ impl<F: Float, R: Rng + Clone> Lhs<F, R> {
lhs.mapv(F::cast)
}

fn _maximin_lhs(&self, ns: usize, centered: bool, n_iter: usize) -> Array2<F> {
fn _maximin_lhs(&self, ns: usize, centered: bool, max_iters: usize) -> Array2<F> {
let mut max_dist = F::zero();
let mut lhs = self._classic_lhs(ns);
for _ in 0..n_iter {
for _ in 0..max_iters {
if centered {
lhs = self._centered_lhs(ns);
} else {
Expand Down
13 changes: 8 additions & 5 deletions ego/examples/ackley.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ fn ackley(x: &ArrayView2<f64>) -> Array2<f64> {
fn main() {
let xlimits = array![[-32.768, 32.768], [-32.768, 32.768], [-32.768, 32.768]];
let res = EgorBuilder::optimize(ackley)
.configure(|config| {
config
.regression_spec(RegressionSpec::CONSTANT)
.correlation_spec(CorrelationSpec::ABSOLUTEEXPONENTIAL)
.infill_strategy(InfillStrategy::WB2S)
.max_iters(200)
.target(5e-1)
})
.min_within(&xlimits)
.regression_spec(RegressionSpec::CONSTANT)
.correlation_spec(CorrelationSpec::ABSOLUTEEXPONENTIAL)
.infill_strategy(InfillStrategy::WB2S)
.n_iter(200)
.target(5e-1)
.run()
.expect("Minimize failure");
println!("Ackley minimum y = {} at x = {}", res.y_opt, res.x_opt);
Expand Down
50 changes: 50 additions & 0 deletions ego/examples/g24.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use egobox_doe::{Lhs, SamplingMethod};
use egobox_ego::EgorServiceBuilder;
use ndarray::{array, concatenate, Array2, ArrayBase, ArrayView2, Axis, Data, Ix1, Zip};

// Objective
fn g24(x: &ArrayBase<impl Data<Elem = f64>, Ix1>) -> f64 {
// Function G24: 1 global optimum y_opt = -5.5080 at x_opt =(2.3295, 3.1785)
-x[0] - x[1]
}

// Constraints < 0
fn g24_c1(x: &ArrayBase<impl Data<Elem = f64>, Ix1>) -> f64 {
-2.0 * x[0].powf(4.0) + 8.0 * x[0].powf(3.0) - 8.0 * x[0].powf(2.0) + x[1] - 2.0
}

fn g24_c2(x: &ArrayBase<impl Data<Elem = f64>, Ix1>) -> f64 {
-4.0 * x[0].powf(4.0) + 32.0 * x[0].powf(3.0) - 88.0 * x[0].powf(2.0) + 96.0 * x[0] + x[1]
- 36.0
}

fn f_g24(x: &ArrayView2<f64>) -> Array2<f64> {
let mut y = Array2::zeros((x.nrows(), 3));
Zip::from(y.rows_mut())
.and(x.rows())
.for_each(|mut yi, xi| {
yi.assign(&array![g24(&xi), g24_c1(&xi), g24_c2(&xi)]);
});
y
}

fn main() {
let xlimits = array![[0., 3.], [0., 4.]];
let mut doe = Lhs::new(&xlimits).sample(3);

// We use Egor optimizer as a service
let egor = EgorServiceBuilder::optimize()
.configure(|config| config.n_cstr(2).random_seed(42))
.min_within(&xlimits);

let mut y_doe = f_g24(&doe.view());
for _i in 0..10 {
// We tell function values and ask for next x location
let x_suggested = egor.suggest(&doe, &y_doe);

doe = concatenate![Axis(0), doe, x_suggested];
y_doe = f_g24(&doe.view());
}

println!("G24 optim x suggestion history = {doe:?}");
}
29 changes: 16 additions & 13 deletions ego/examples/mopta08.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ fn main() -> anyhow::Result<()> {
let dim = args.dim;
let outdir = args.outdir;
let n_doe = 2 * dim;
let n_iter = 2 * dim;
let max_iters = 2 * dim;
const N_CSTR: usize = 68;
let cstr_tol = Array1::from_elem(N_CSTR, 1e-4);
let kpls_dim = 3;
Expand All @@ -262,19 +262,22 @@ fn main() -> anyhow::Result<()> {
xlimits.column_mut(1).assign(&Array1::ones(dim));

let res = EgorBuilder::optimize(mopta_func(dim))
.configure(|config| {
config
.n_cstr(N_CSTR)
.cstr_tol(&cstr_tol)
.n_clusters(1)
.n_start(50)
.n_doe(n_doe)
.max_iters(max_iters)
.regression_spec(RegressionSpec::CONSTANT)
.correlation_spec(CorrelationSpec::SQUAREDEXPONENTIAL)
.infill_optimizer(InfillOptimizer::Slsqp)
.kpls_dim(kpls_dim)
.outdir(outdir)
.hot_start(true)
})
.min_within(&xlimits)
.n_cstr(N_CSTR)
.cstr_tol(&cstr_tol)
.n_clusters(1)
.n_start(50)
.n_doe(n_doe)
.n_iter(n_iter)
.regression_spec(RegressionSpec::CONSTANT)
.correlation_spec(CorrelationSpec::SQUAREDEXPONENTIAL)
.infill_optimizer(InfillOptimizer::Slsqp)
.kpls_dim(kpls_dim)
.outdir(outdir)
.hot_start(true)
.run()
.expect("Minimize failure");
println!(
Expand Down
3 changes: 1 addition & 2 deletions ego/examples/rosenbrock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ fn rosenbrock(x: &ArrayView2<f64>) -> Array2<f64> {
fn main() {
let xlimits = array![[-2., 2.], [-2., 2.]];
let res = EgorBuilder::optimize(rosenbrock)
.configure(|config| config.max_iters(100).target(1e-2))
.min_within(&xlimits)
.n_iter(100)
.target(1e-2)
.run()
.expect("Minimize failure");
println!("Rosenbrock minimum y = {} at x = {}", res.y_opt, res.x_opt);
Expand Down
Loading

0 comments on commit 2227e1b

Please sign in to comment.