Commit d29de0c3 authored by Konstantinos Chatzilygeroudis's avatar Konstantinos Chatzilygeroudis
Browse files

Merge branch 'master' into local_jobs

Conflicts:
	waf_tools/limbo.py
parents 9867da72 d81d1821
......@@ -19,3 +19,4 @@ src/tests/combinations
# Ignored folders for the documentation
_build
doxygen_doc
language: cpp
os:
- linux
sudo: required
dist: trusty
compiler:
- gcc
- clang
sudo: required
install: sudo apt-get update -qq && sudo apt-get install -qq libboost-all-dev libboost-test-dev libeigen3-dev libtbb-dev
env:
global:
- CI_HOME=`pwd`
matrix:
- LIBCMAES=ON NLOPT=ON TBB=ON
- LIBCMAES=ON NLOPT=ON TBB=OFF
- LIBCMAES=ON NLOPT=OFF TBB=ON
- LIBCMAES=ON NLOPT=OFF TBB=OFF
- LIBCMAES=OFF NLOPT=ON TBB=ON
- LIBCMAES=OFF NLOPT=ON TBB=OFF
- LIBCMAES=OFF NLOPT=OFF TBB=ON
- LIBCMAES=OFF NLOPT=OFF TBB=OFF
addons:
apt:
packages:
- libboost1.55-all-dev
- libeigen3-dev
install:
- if [ "$LIBCMAES" = "ON" ]; then 'ci/install_libcmaes.sh' ; fi
- if [ "$NLOPT" = "ON" ]; then 'ci/install_nlopt.sh' ; fi
- if [ "$TBB" = "ON" ]; then 'ci/install_tbb.sh' ; fi
# Change this to your needs
script:
./waf configure && ./waf
\ No newline at end of file
script:
- ./waf configure
- ./waf --tests --alltests -v
limbo
limbo [![Build Status](https://img.shields.io/travis/resibots/limbo.svg)](https://travis-ci.org/resibots/limbo)
=====
A lightweight framework for Bayesian and model-based optimisation of black-box functions (C++11).
......@@ -13,8 +13,8 @@ Authors
- Antoine Cully (Imperial College): http://www.isir.upmc.fr/?op=view_profil&lang=fr&id=278
- Jean-Baptiste Mouret (Inria): http://pages.isir.upmc.fr/~mouret/website/
- Konstantinos Chatzilygeroudis (Inria)
- Federico Allocai (Inria)
-
- Federico Allocati (Inria)
Main features
-------------
- Bayesian optimisation based on Gaussian processes
......@@ -27,7 +27,7 @@ Main references
- **General introduction:** Brochu, E., Cora, V. M., & De Freitas, N. (2010). A tutorial on Bayesian optimization of expensive cost functions, with application to active user modeling and hierarchical reinforcement learning. *arXiv preprint arXiv:1012.2599*.
- **Gaussian Processes (GP)**: Rasmussen, C. A, Williams C. K. I. (2006). /Gaussian Processes for Machine Learning./ MIT Press.
- **Gaussian Processes (GP)**: Rasmussen, C. A, Williams C. K. I. (2006). /Gaussian Processes for Machine Learning./ MIT Press.
- **Optimizing hyperparameters:** Blum, M., & Riedmiller, M. (2013). Optimization of Gaussian Process Hyperparameters using Rprop. In *European Symposium on Artificial Neural Networks, Computational Intelligence and Machine Learning*.
......@@ -45,4 +45,3 @@ Limbo is a framework for our research that is voluntarily kept small. It is desi
If you need a more full-featured library, check:
- BayesOpt: http://rmcantin.bitbucket.org/html/
- libGP (no optimization): https://github.com/mblum/libgp
sudo apt-get -qq update
sudo apt-get -qq --yes --force-yes install libgtest-dev autoconf automake libtool libgoogle-glog-dev libgflags-dev
cd /usr/src/gtest
sudo mkdir build && cd build
sudo cmake ..
sudo make
sudo cp *.a /usr/lib
cd && git clone https://github.com/beniz/libcmaes.git
cd libcmaes
./autogen.sh
./configure
make
sudo make install
sudo ldconfig
cd $CI_HOME
sudo apt-get -qq update
sudo apt-get -qq --yes --force-yes install autoconf automake
cd && wget http://ab-initio.mit.edu/nlopt/nlopt-2.4.2.tar.gz
tar -zxvf nlopt-2.4.2.tar.gz && cd nlopt-2.4.2
./configure -with-cxx --enable-shared --without-python --without-matlab --without-octave
sudo make install
sudo ldconfig
cd $CI_HOME
sudo apt-get -qq update
sudo apt-get -qq --yes --force-yes install libtbb-dev
This diff is collapsed.
......@@ -51,11 +51,14 @@ help:
clean:
rm -rf $(BUILDDIR)/*
html:
html: doxygen
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
doxygen:
doxygen Doxyfile
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
......
API
============
.. highlight:: c++
Limbo follows a `policy-based design <https://en.wikipedia.org/wiki/Policy-based_design>`_, which allows users to combine high flexibility (almost every part of Limbo can be substituted by a user-defined part) with high performance (the abstraction do not add any overhead, contrary to classic OOP design). These two features are critical for researchers who want to experiment new ideas in Bayesian optimization. This means that changing a part of limbo (e.g. changing the kernel functions) usually corresponds to changing a template parameter of the optimizer.
The parameters of the algorithms (e.g. an epsilon) are given by a template class (usually called Params in our code, and always the first argument). See :doc:`parameters` for details.
To avoid defining each component of an optimizer manually, Limbo provides sensible defaults. In addition, Limbo relies on `Boost.Parameter <http://www.boost.org/doc/libs/1_60_0/libs/parameter/doc/html/index.html>`_ to make it easy to customize a single part. This Boost library allows us to write classes that accept template argument (user-defined custom classes) by name. For instance, to customize the stopping criteria:
::
using namespace limbo;
// here stop_t is a user-defined list of stopping criteria
bayes_opt::BOptimizer<Params, stopcrit<stop_t>> boptimizer;
Or to define a custom acquisition function:
::
using namespace limbo;
// here acqui_t is a user-defined acquisition function
bayes_opt::BOptimizer<Params, acquifun<acqui_t>> boptimizer;
Class Structure
---------------
.. figure:: pics/limbo_uml_v2.png
:alt: UML class diagram
:target: _images/limbo_uml_v2.png
Click on the image to see it bigger.
There is almost no explicit inheritance in Limbo because polymorphism is not used. However, each kind of class follow a similar template (or 'concept'), that is, they have to implement the same methods. For instance, every initialization function must implement a `()` method:
.. code-block:: cpp
template <typename StateFunction, typename AggregatorFunction, typename Opt>
void operator()(const StateFunction& seval, const AggregatorFunction&, Opt& opt) const
However, there is no need to inherit from a particular 'abstract' class.
Every class is parametrized by a :ref:`Params <params-guide>` class that contains all the parameters.
Sequence graph
---------------
.. figure:: pics/limbo_call_graph.png
:alt: Sequence diagram
:target: _images/limbo_call_graph.png
Click on the image to see it bigger.
File Structure
--------------
(see below for a short explanation of the concepts)
::
src
+-- limbo:
+-- acqui: acquisition functions
|-- bayes_opt: bayesian optimizers
|-- init: initialization functions
|-- kernel: kernel functions
|-- mean: mean functions
|-- model: models (Gaussian Processes)
|-- opt: optimizers (Rprop, CMA-ES, etc.)
|-- stat: statistics (to dump data)
|-- stop: stopping criteria
|-- tools: useful macros & small functions
|-- tests: unit tests
|-- benchmarks: a few benchmark functions
|-- examples: a few examples
|-- cmaes: [external] the CMA-ES library, used for inner optimizations -- from https://www.lri.fr/~hansen/cmaesintro.html
|-- ehvi: [external] the Expected HyperVolume Improvement, used for Multi-Objective Optimization -- by Iris Hupkens
Each directory in the `limbo` directory corresponds to a namespace with the same name. There is also a file for each directory called "directory.hpp" (e.g. `acqui.hpp`) that includes the whole namespace.
Bayesian optimizers (bayes_opt)
---------------------------------
.. doxygenclass:: limbo::bayes_opt::BoBase
:members:
.. doxygenclass:: limbo::bayes_opt::BOptimizer
:members:
Acquisition functions (acqui)
------------------------------
An acquisition function is what is optimized to select the next point to try. It usually depends on the model.
Template
^^^^^^^^^^
.. code-block:: cpp
template <typename Params, typename Model>
class AcquiName {
public:
AcquiName(const Model& model, int iteration = 0) : _model(model) {}
size_t dim_in() const { return _model.dim_in(); }
size_t dim_out() const { return _model.dim_out(); }
template <typename AggregatorFunction>
double operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun) const
{
// code
}
};
Available acquisition functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: acqui
:undoc-members:
Default Parameters
^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: Acqui_defaults
:undoc-members:
Init functions (init)
------------------------------
Initialization functions are used to inialize a Bayesian optimization algorithm with a few samples. For instance, we typically start with a dozen of random samples.
Template
^^^^^^^^^^
.. code-block:: cpp
struct InitName {
template <typename StateFunction, typename AggregatorFunction, typename Opt>
void operator()(const StateFunction& seval, const AggregatorFunction&, Opt& opt) const
{
// code
}
Available initializers
^^^^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: init
:undoc-members:
Default Parameters
^^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: init_defaults
:undoc-members:
Optimization functions (opt)
------------------------------
Optimizers are used both to optimize acquisition functions and to optimize hyper-parameters. Some optimizers require the gradient, some don't.
Template
^^^^^^^^^
.. code-block:: cpp
template <typename Params>
struct OptimizerName {
template <typename F>
Eigen::VectorXd operator()(const F& f, const Eigen::VectorXd& init, bool bounded) const
{
// content
}
};
- ``f`` is the function to be optimized. If the gradient is known, the function should look like this:
.. code-block:: cpp
limbo::opt::eval_t my_function(const Eigen::VectorXd& v)
{
double x = <function_value>;
Eigen::VectorXd gradient = <gradient>;
return std::make_pair(x, gradient);
}
- If the gradient of ``f`` is not known:
.. code-block:: cpp
limbo::opt::eval_t my_function(const Eigen::VectorXd& v)
{
double x = <function_value>(v);
return limbo::opt::no_grad(x);
}
- ``init`` is an optionnal starting point (for local optimizers); many optimizers ignore this argument (see the table below): in that case, an assert will fail.
- ``bounded`` is true if the optimization is bounded in [0,1]; many optimizers do not support bounded optimization (see the table below).
+-------------+---------+-------+
|Algo. | bounded | init |
+=============+=========+=======+
|CMA-ES | yes | yes |
+-------------+---------+-------+
| NLOptGrad | ? | ? |
+-------------+---------+-------+
| NLOptNoGrad | ? | ? |
+-------------+---------+-------+
|Rprop | no | ? |
+-------------+---------+-------+
|RandomPoint | yes | no |
+-------------+---------+-------+
Available optimizers
^^^^^^^^^^^^^^^^^^
.. doxygengroup:: opt
:undoc-members:
Default parameters
^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: opt_defaults
:undoc-members:
Utility functions & typedefs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: opt_tools
:members:
Models / Gaussian processes (model)
---------------
Currentl, Limbo only include Gaussian processes as models. More may come in the future.
.. doxygenclass:: limbo::model::GP
:members:
The hyper-parameters of the model (kernel, mean) can be optimized. The following options are possible:
.. doxygengroup:: model_opt
:members:
Kernel functions (kernel)
--------------------------
Template
^^^^^^^^
.. code-block:: cpp
template <typename Params>
struct Kernel {
Kernel(size_t dim = 1) {}
double operator()(const Eigen::VectorXd& v1, const Eigen::VectorXd& v2) const
{
// code
}
};
Available kernels
^^^^^^^^^^^^^^^^^^
.. doxygengroup:: kernel
:members:
Default parameters
^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: Kernel_defaults
:undoc-members:
Mean functions (mean)
--------------------------
Mean functions capture the prior about the function to be optimized.
Template
^^^^^^^^
.. code-block:: cpp
template <typename Params>
struct MeanFunction {
MeanFunction(size_t dim_out = 1) : _dim_out(dim_out) {}
template <typename GP>
Eigen::VectorXd operator()(const Eigen::VectorXd& v, const GP&) const
{
// code
}
protected:
size_t _dim_out;
};
Available mean functions
^^^^^^^^^^^^^^^^^^
.. doxygengroup:: mean
:members:
Default parameters
^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: mean_defaults
:undoc-members:
Stopping criteria (stop)
---------------------------------
Stopping criteria are used to stop the Bayesian optimizer algorithm.
Template
^^^^^^^^
.. code-block:: cpp
template <typename Params>
struct Name {
template <typename BO, typename AggregatorFunction>
bool operator()(const BO& bo, const AggregatorFunction&)
{
// return true if stop
}
};
Available stopping criteria
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: stop
:members:
Default parameters
^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: stop_defaults
:undoc-members:
Internals
^^^^^^^^^^
.. doxygenstruct:: limbo::stop::ChainCriteria
:members:
Statistics (stats)
--------------------------
Statistics are used to report informations about the current state of the algorithm (e.g., the best observation for each iteration). They are typically chained in a `boost::fusion::vector<>`.
Template
^^^^^^^^
.. code-block:: cpp
template <typename Params>
struct Samples : public StatBase<Params> {
template <typename BO, typename AggregatorFunction>
void operator()(const BO& bo, const AggregatorFunction&, bool blacklisted)
{
// code
}
};
.. doxygenstruct:: limbo::stat::StatBase
Available statistics
^^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: stat
:members:
Default parameters
^^^^^^^^^^^^^^^^^^^
.. doxygengroup:: stat_defaults
:undoc-members:
Parallel tools (par)
-----------------------
.. doxygennamespace:: limbo::tools::par
:members:
Misc tools (tools)
-------------------------------
.. doxygennamespace:: limbo::tools
:members:
.. bibliography:: refs.bib
:style: plain
......@@ -34,10 +34,13 @@ extensions = [
'sphinx.ext.todo',
'sphinx.ext.mathjax',
'sphinx.ext.ifconfig',
'sphinxcontrib.bibtex'
'sphinxcontrib.bibtex',
'breathe'
]
breathe_projects = { "limbo": "doxygen_doc/xml/" }
breathe_default_project="limbo"
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
......
......@@ -48,4 +48,4 @@ We have specific needs that mainly revolve around high-performance, minimzing bo
- Long-term use: our libraries will be used for at least 10 years in our group, therefore we want to use a language that will still exist in 10 years and that is not moving too fast (we do not want to rewrite our code every other month).
Modern C++11 appears to be a good choice to fulfill all these criteria: it is reasonably easy to use, very easy to interface with everything, and very high-performance... but we keep a close eye on `Julia <julialang.org>`_, `Scala <www.scala-lang.org>`_, and `Rust <www.rust-lang.org>`_!
Modern C++11 appears to be a good choice to fulfill all these criteria: it is reasonably easy to use, very easy to interface with everything, and very high-performance... but we keep a close eye on `Julia <http://julialang.org>`_, `Scala <http://www.scala-lang.org>`_, and `Rust <http://www.rust-lang.org>`_!
......@@ -60,7 +60,7 @@ The json file should look like this (for both OAR or Torque):
.. code-block:: javascript
{
[{
"exps" : ["hexa_duty_text"],
"bin_dir" : "/nfs/hal01/jmouret/git/sferes2/build/default/exp/hexa_duty_cycle",
"res_dir" : "/nfs/hal01/jmouret/data/maps_hexapod-slippy/",
......@@ -68,7 +68,17 @@ The json file should look like this (for both OAR or Torque):
"wall_time" : "270:00:00",
"nb_runs" : 2,
"nb_cores" : 24,
}
},
{
"exps" : ["hexa_duty_graphic"],
"bin_dir" : "/nfs/hal01/jmouret/git/sferes2/build/default/exp/hexa_duty_cycle",
"res_dir" : "/nfs/hal01/jmouret/data/maps_hexapod-slippy-graphic/",
"email" : "JBM",
"wall_time" : "270:00:00",
"nb_runs" : 2,
"nb_cores" : 24,
}]
Explanations:
......@@ -92,7 +102,7 @@ Explanations:
Variants
--------
A very common use case is to compare variant XX to variant YY of an algorithm. Usually, only a few lines of code are different (like, calling kernel X or kernel Y). Limbo is designed to create a binary for each variant by defining a few constant at the beginning of a source file.
A very common use case is to compare variant XX to variant YY of an algorithm. Usually, only a few lines of code are different (like, calling kernel X or kernel Y). Limbo is designed to create a binary for each variant by using defines (like defining constants at the beginning of each file).
For instance, let's say we have a file called ``multi.cpp`` for which we want to compare two algorithms, ``Parego`` and ``EHVI``:
......@@ -122,12 +132,10 @@ We can create two variants in the ``wscript``, as follows:
'EHVI'])
Limbo will create two files:
- ``multi_parego.cpp``, which is the ``multi.cpp`` file with a ``#define PAREGO`` at the first line
- ``multi_ehvi.cpp``, which is the ``multi.cpp`` file with a ``#define EHVI`` at the first line
Limbo will create two binaries:
**You should never edit these files**: they will be re-generated each time you will compile.
- ``multi_parego``, which is the compilation of ``multi.cpp`` file with a ``#define PAREGO`` at the first line
- ``multi_ehvi``, which is the compilation of ``multi.cpp`` file with a ``#define EHVI`` at the first line
You can add as many defines as you like (or even generate them with python code), for instance:
......@@ -150,4 +158,25 @@ This will create ``multi_parego_mop2_dim2`` and ``multi_ehvi_zdt2_dim6``.
Using ``./waf --exp your_experiment`` will compile all the corresponding libraries. If you want to compile a single variant, you can use the ``--target`` option: ``./waf --exp your_experiment --target parego_mop2_dim2`.
If you have more than one file, you will need to first compile a static library, then link with it in the variant.
If you have more than one file, you have 2 options:
- First compile a static library, then link with it in the variant.
- Add them in sequence in the source input. The name of the first file is used for the variant target names. Example:
.. code-block:: python
#! /usr/bin/env python
import limbo
def build(bld):
limbo.create_variants(bld,
source = 'multi.cpp dep.cpp impl.cpp',
uselib_local = 'limbo',
uselib = 'BOOST EIGEN TBB SFERES',
variants = ['PAREGO',
'EHVI'])
Limbo will create two binaries:
- ``multi_parego``, which is the compilation of ``multi.cpp``, ``dep.cpp`` and ``impl.cpp`` files with a ``#define PAREGO`` at the first line of each file
- ``multi_ehvi``, which is the compilation of ``multi.cpp``, ``dep.cpp`` and ``impl.cpp`` files with a ``#define EHVI`` at the first line of each file
......@@ -9,4 +9,3 @@ Guides
limbo_concepts
framework
parameters
general_concepts
......@@ -45,6 +45,7 @@ Contents:
self
tutorials/index
guides/index
api
faq
......@@ -56,7 +57,3 @@ Contents:
.. * :ref:`search`
TODO list
==========
.. todolist::
docs/pics/limbo_call_graph.png

47.2 KB | W: | H:

docs/pics/limbo_call_graph.png

62.7 KB | W: | H:

docs/pics/limbo_call_graph.png
docs/pics/limbo_call_graph.png
docs/pics/limbo_call_graph.png
docs/pics/limbo_call_graph.png
  • 2-up
  • Swipe
  • Onion skin
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<diagram program="umlet" version="13.3">
<zoom_level>7</zoom_level>
<element>
<id>UMLClass</id>
<coordinates>
<x>525</x>
<y>154</y>
<w>133</w>
<h>35</h>