Commit 46d9713b authored by JB Mouret's avatar JB Mouret Committed by GitHub
Browse files

Merge branch 'master' into doc_versioning

parents ac93dbe0 69bf9002
......@@ -12,13 +12,16 @@
*.log
.lock-waf*
.waf-*
.waf3-*
build
waf_xcode.sh
exp
src/tests/combinations
params_*
benchmark_results
__pycache__
# Ignored folders for the documentation
_build
doxygen_doc
docs/defaults.rst
......@@ -16,28 +16,31 @@ env:
global:
- CI_HOME=`pwd`
matrix:
- LIBCMAES=ON NLOPT=ON TBB=ON EXPERIMENTAL=OFF SFERES=OFF
- LIBCMAES=ON NLOPT=ON TBB=OFF EXPERIMENTAL=OFF SFERES=OFF
- LIBCMAES=ON NLOPT=OFF TBB=ON EXPERIMENTAL=OFF SFERES=OFF
- LIBCMAES=ON NLOPT=OFF TBB=OFF EXPERIMENTAL=OFF SFERES=OFF
- LIBCMAES=OFF NLOPT=ON TBB=ON EXPERIMENTAL=OFF SFERES=OFF
- LIBCMAES=OFF NLOPT=ON TBB=OFF EXPERIMENTAL=OFF SFERES=OFF
- LIBCMAES=OFF NLOPT=OFF TBB=ON EXPERIMENTAL=OFF SFERES=OFF
- LIBCMAES=OFF NLOPT=OFF TBB=OFF EXPERIMENTAL=OFF SFERES=OFF
- LIBCMAES=ON NLOPT=OFF TBB=OFF EXPERIMENTAL=ON SFERES=OFF
- LIBCMAES=OFF NLOPT=OFF TBB=OFF EXPERIMENTAL=ON SFERES=OFF
- LIBCMAES=ON NLOPT=OFF TBB=ON EXPERIMENTAL=ON SFERES=OFF
- LIBCMAES=OFF NLOPT=OFF TBB=ON EXPERIMENTAL=ON SFERES=OFF
- LIBCMAES=ON NLOPT=OFF TBB=OFF EXPERIMENTAL=ON SFERES=ON
- LIBCMAES=OFF NLOPT=OFF TBB=OFF EXPERIMENTAL=ON SFERES=ON
- LIBCMAES=ON NLOPT=OFF TBB=ON EXPERIMENTAL=ON SFERES=ON
- LIBCMAES=OFF NLOPT=OFF TBB=ON EXPERIMENTAL=ON SFERES=ON
- LIBCMAES=ON NLOPT=ON TBB=ON EXPERIMENTAL=OFF SFERES=OFF PYTHON=python3
- LIBCMAES=ON NLOPT=ON TBB=ON EXPERIMENTAL=OFF SFERES=OFF PYTHON=python2
- LIBCMAES=ON NLOPT=ON TBB=OFF EXPERIMENTAL=OFF SFERES=OFF PYTHON=python2
- LIBCMAES=ON NLOPT=OFF TBB=ON EXPERIMENTAL=OFF SFERES=OFF PYTHON=python2
- LIBCMAES=ON NLOPT=OFF TBB=OFF EXPERIMENTAL=OFF SFERES=OFF PYTHON=python2
- LIBCMAES=OFF NLOPT=ON TBB=ON EXPERIMENTAL=OFF SFERES=OFF PYTHON=python2
- LIBCMAES=OFF NLOPT=ON TBB=OFF EXPERIMENTAL=OFF SFERES=OFF PYTHON=python2
- LIBCMAES=OFF NLOPT=OFF TBB=ON EXPERIMENTAL=OFF SFERES=OFF PYTHON=python2
- LIBCMAES=OFF NLOPT=OFF TBB=OFF EXPERIMENTAL=OFF SFERES=OFF PYTHON=python2
- LIBCMAES=ON NLOPT=OFF TBB=OFF EXPERIMENTAL=ON SFERES=OFF PYTHON=python2
- LIBCMAES=OFF NLOPT=OFF TBB=OFF EXPERIMENTAL=ON SFERES=OFF PYTHON=python2
- LIBCMAES=ON NLOPT=OFF TBB=ON EXPERIMENTAL=ON SFERES=OFF PYTHON=python2
- LIBCMAES=OFF NLOPT=OFF TBB=ON EXPERIMENTAL=ON SFERES=OFF PYTHON=python2
- LIBCMAES=ON NLOPT=OFF TBB=OFF EXPERIMENTAL=ON SFERES=ON PYTHON=python2
- LIBCMAES=OFF NLOPT=OFF TBB=OFF EXPERIMENTAL=ON SFERES=ON PYTHON=python2
- LIBCMAES=ON NLOPT=OFF TBB=ON EXPERIMENTAL=ON SFERES=ON PYTHON=python2
- LIBCMAES=OFF NLOPT=OFF TBB=ON EXPERIMENTAL=ON SFERES=ON PYTHON=python2
addons:
apt:
packages:
- libboost1.55-all-dev
- libeigen3-dev
- python
- python3
before_install:
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
......@@ -51,5 +54,5 @@ install:
# Change this to your needs
script:
- if [ "$SFERES" = "OFF" ]; then ./waf configure ; else ./waf configure --sferes=$CI_HOME/sferes2 ; fi
- if [ "$EXPERIMENTAL" = "OFF" ]; then ./waf --tests --alltests -v ; else ./waf --experimental ; fi
- if [ "$SFERES" = "OFF" ]; then $PYTHON ./waf configure ; else $PYTHON ./waf configure --sferes=$CI_HOME/sferes2 ; fi
- if [ "$EXPERIMENTAL" = "OFF" ]; then $PYTHON ./waf --tests --alltests -v ; else $PYTHON ./waf --experimental ; fi
## Coding style
We chose to abide by the following coding style rules.
1. Names representing classes must be in camel case:
`MyClass`
2. Variable and method names must be in lower case, using underscores to separate words:
`my_variable`, `my_method()`
3. Names of protected and private members must start with an underscore:
`_my_private_member`, `_my_private_method()`
4. File names must be in lower case, using underscores to separate words.
A file which contains a class `MyClass` should be named `my_class.hpp`
5. File structure mirrors namespace structure.
For instance `gen::MyClass` is in the file `gen/my_class.hpp`
6. Named constants (including enumeration values) must be placed in the `cst` namespace within the current namespace
```
namespace cst {
static constexpr int a_number = 3529;
}
```
7. Getters should have the name of the attribute:
`this->_objs` should be accessed using `this->objs()`
8. Setters should start with "set\_" followed by the name of the attribute:
`set_objs(const std::vector& ov)`
9. The public section should be the first section of a class
10. Type names defined using typedefs/aliases should end with "\_t": `iterator_t`
## Code formatting
We also follow the coding style rules enforced by `clang-format` and a custom configuration. See the [format_code](https://github.com/resibots/format_code) repository and software to follow this standard.
......@@ -54,11 +54,12 @@ Main features
Scientific articles that use Limbo
--------------------------------
- Cully, A., Clune, J., Tarapore, D., & Mouret, J. B. (2015). [Robots that can adapt like animals](http://www.nature.com/nature/journal/v521/n7553/full/nature14422.html). *Nature*, 521(7553), 503-507.
- Tarapore D, Clune J, Cully A, Mouret JB (2016). [How Do Different Encodings Influence the Performance of the MAP-Elites Algorithm?](https://hal.inria.fr/hal-01302658/document). *In Proc. of Genetic and Evolutionary Computation Conference*.
- Cully, A., Clune, J., Tarapore, D., and Mouret, J.B. (2015). [Robots that can adapt like animals](http://www.nature.com/nature/journal/v521/n7553/full/nature14422.html). *Nature*, 521(7553), 503-507.
- Tarapore, D., Clune, J., Cully, A., and Mouret, J.B. (2016). [How Do Different Encodings Influence the Performance of the MAP-Elites Algorithm?](https://hal.inria.fr/hal-01302658/document). *In Proc. of Genetic and Evolutionary Computation Conference*.
- Chatzilygeroudis, K., Vassiliades, V. and Mouret, J.B. (2016). [Reset-free Trial-and-Error Learning for Data-Efficient Robot Damage Recovery](https://arxiv.org/abs/1610.04213). *arXiv preprint arXiv:1610.04213*.
- Chatzilygeroudis, K., Cully, A. and Mouret, J.B. (2016). [Towards semi-episodic learning for robot damage recovery](https://arxiv.org/abs/1610.01407). *Workshop on AI for Long-Term Autonomy at the IEEE International Conference on Robotics and Automation 2016*.
- Papaspyros V., Chatzilygeroudis K., Vassiliades V., and Mouret JB. (2016). [Safety-Aware Robot Damage Recovery Using Constrained Bayesian Optimization and Simulated Priors](https://arxiv.org/pdf/1611.09419v3). *Workshop on Bayesian Optimization at the Annual Conference on Neural Information Processing Systems (NIPS) 2016.*
- Papaspyros, V., Chatzilygeroudis, K., Vassiliades, V., and Mouret, J.B. (2016). [Safety-Aware Robot Damage Recovery Using Constrained Bayesian Optimization and Simulated Priors](https://arxiv.org/pdf/1611.09419v3). *Workshop on Bayesian Optimization at the Annual Conference on Neural Information Processing Systems (NIPS) 2016.*
- Chatzilygeroudis K., Rama R., Kaushik, R., Goepp, D., Vassiliades, V. and Mouret, J.B. (2017). [Black-Box Data-efficient Policy Search for Robotics](https://arxiv.org/abs/1703.07261). *arXiv preprint arXiv:1703.07261*.
Research projects that use Limbo
--------------------------------
......
Benchmarking with other Bayesian Optimization/Gaussian Processes Libraries
==========================================================================
In this section, we will compared the performance (both in accuracy and speed) of our library to the one of other Bayesian Optimization (BO) and Gaussian Processes (GP) libraries in several test functions.
.. _bench_bayes_opt:
BayesOpt C++ Bayesian Optimization Library
-------------------------------------------
**Last updated: 27/05/2017**
The BayesOpt library and information about it can be found `here <https://bitbucket.org/rmcantin/bayesopt>`_.
Parameters/Setup
~~~~~~~~~~~~~~~~~
Limbo was configured to replicate BayesOpt's default parameters:
+------------------------+---------------------------------------+
| **Kernel\*** | Matern5 (:math:`\sigma^2 = 1, l = 1`) |
+------------------------+---------------------------------------+
|**Acquisition Function**| UCB (:math:`\alpha = 0.125`) |
+------------------------+---------------------------------------+
| **Initialization** | RandomSampling (10 Samples) |
+------------------------+---------------------------------------+
| **Mean function** | Constant (value of 1) +
+------------------------+---------------------------------------+
| **Sample noise** | 1e-10 +
+------------------------+---------------------------------------+
| **Max iterations** | 190 +
+------------------------+---------------------------------------+
**\*** *When the hyperparameters are optimized, the kernel parameters are learnt.*
The acquisition function is optimized as follows: an outer optimization process uses **DIRECT** for :math:`225d` iterations (where :math:`d` is the input dimension) and the solution found is fed as the initial point to an inner optimization process that uses **BOBYQA** for :math:`25d` iterations.
Results
~~~~~~~~
.. figure:: ./pics/benchmark_limbo_bayes_opt.png
:alt: Benchmarks vs BayesOpt C++ library
:target: ./_images/benchmark_limbo_bayes_opt.png
Two configurations are tested: with and without optimization of the hyper-parameters of the Gaussian Process. Each experiment has been replicated 250 times. The median of the data is pictured with a thick dot, while the box represents the first and third quartiles. The most extreme data points are delimited by the whiskers and the outliers are individually depicted as smaller circles. According to the benchmarks we performed (see figure above), Limbo finds solutions with the same level of quality as BayesOpt, within a significantly lower amount of time: for the same accuracy (less than 2.10−3 between the optimized solutions found by Limbo and BayesOpt), Limbo is between 1.47 and 1.76 times faster (median values) than BayesOpt when the hyperparameters are not optimized, and between 2.05 and 2.54 times faster when they are.
......@@ -55,7 +55,7 @@ A GP is fully specified by its mean function :math:`\mu(\mathbf{x})` and covaria
.. math::
k_{SE}(\chi_1, \chi_2) = \sigma_f^2 \cdot \exp\left( \frac{\left|\left|\chi_1, \chi_2\right|\right|^2}{2 l^2} \right)
k_{SE}(\chi_1, \chi_2) = \sigma_f^2 \cdot \exp\left( -\frac{\left|\left|\chi_1 - \chi_2\right|\right|^2}{2 l^2} \right)
For some datasets, it makes sense to hand-tune these parameters (e.g., when there are very few samples). Ideally, our objective should be to learn :math:`l^2` (characteristic length scale) and :math:`\sigma_f^2` (overall variance).
......
......@@ -40,6 +40,7 @@ Contents:
guides/index
api
defaults
benchmarks
faq
......
......@@ -63,7 +63,7 @@ namespace limbo {
Exponential kernel (see :cite:`brochu2010tutorial` p. 9).
.. math::
k(v_1, v_2) = \sigma^2\exp \Big(-\frac{1}{l^2} ||v_1 - v_2||^2\Big)
k(v_1, v_2) = \sigma^2\exp \Big(-\frac{||v_1 - v_2||^2}{2l^2}\Big)
Parameters:
- ``double sigma_sq`` (signal variance)
......
......@@ -61,6 +61,9 @@ namespace limbo {
/// @ingroup opt_defaults
/// number of replicates
BO_PARAM(int, repeats, 10);
/// epsilon of deviation: init + [-epsilon,epsilon]
BO_PARAM(double, epsilon, 1e-2);
};
}
namespace opt {
......@@ -75,14 +78,18 @@ namespace limbo {
template <typename F>
Eigen::VectorXd operator()(const F& f, const Eigen::VectorXd& init, bool bounded) const
{
assert(Params::opt_parallelrepeater::repeats() > 0);
assert(Params::opt_parallelrepeater::epsilon() > 0.);
tools::par::init();
using pair_t = std::pair<Eigen::VectorXd, double>;
auto body = [&](int i) {
// clang-format off
Eigen::VectorXd r_init = tools::random_vector(init.size());
Eigen::VectorXd v = Optimizer()(f, init, bounded);
double lik = opt::eval(f, v);
return std::make_pair(v, lik);
Eigen::VectorXd r_deviation = tools::random_vector(init.size()).array() * 2. * Params::opt_parallelrepeater::epsilon() - Params::opt_parallelrepeater::epsilon();
Eigen::VectorXd v = Optimizer()(f, init + r_deviation, bounded);
double val = opt::eval(f, v);
return std::make_pair(v, val);
// clang-format on
};
......
......@@ -58,7 +58,11 @@ namespace limbo {
namespace defaults {
struct opt_rprop {
/// @ingroup opt_defaults
/// number of max iterations
BO_PARAM(int, iterations, 300);
/// gradient norm epsilon for stopping
BO_PARAM(double, eps_stop, 0.0);
};
}
namespace opt {
......@@ -78,14 +82,15 @@ namespace limbo {
template <typename F>
Eigen::VectorXd operator()(const F& f, const Eigen::VectorXd& init, bool bounded) const
{
// params
assert(Params::opt_rprop::eps_stop() >= 0.);
size_t param_dim = init.size();
double delta0 = 0.1;
double deltamin = 1e-6;
double deltamax = 50;
double etaminus = 0.5;
double etaplus = 1.2;
double eps_stop = 0.0;
double eps_stop = Params::opt_rprop::eps_stop();
Eigen::VectorXd delta = Eigen::VectorXd::Ones(param_dim) * delta0;
Eigen::VectorXd grad_old = Eigen::VectorXd::Zero(param_dim);
......
......@@ -49,7 +49,9 @@
#include <boost/test/unit_test.hpp>
#include <limbo/opt/chained.hpp>
#include <limbo/opt/parallel_repeater.hpp>
#include <limbo/opt/cmaes.hpp>
#include <limbo/opt/rprop.hpp>
#include <limbo/opt/grid_search.hpp>
#include <limbo/opt/random_point.hpp>
#include <limbo/tools/macros.hpp>
......@@ -60,6 +62,15 @@ struct Params {
struct opt_gridsearch {
BO_PARAM(int, bins, 20);
};
struct opt_parallelrepeater {
BO_PARAM(int, repeats, 2);
BO_PARAM(double, epsilon, 0.1);
};
struct opt_rprop : public defaults::opt_rprop {
BO_PARAM(int, iterations, 150);
};
};
// test with a standard function
......@@ -82,6 +93,18 @@ struct FakeAcquiBi {
}
};
// test with gradient
int simple_calls = 0;
bool check_grad = false;
std::vector<Eigen::VectorXd> starting_points;
opt::eval_t simple_func(const Eigen::VectorXd& v, bool eval_grad)
{
assert(!check_grad || eval_grad);
simple_calls++;
starting_points.push_back(v);
return {-(v(0) * v(0) + 2. * v(0)), limbo::tools::make_vector(-(2 * v(0) + 2.))};
}
BOOST_AUTO_TEST_CASE(test_random_mono_dim)
{
using namespace limbo;
......@@ -144,6 +167,44 @@ BOOST_AUTO_TEST_CASE(test_grid_search_bi_dim)
BOOST_CHECK_EQUAL(bidim_calls, (Params::opt_gridsearch::bins() + 1) * (Params::opt_gridsearch::bins() + 1) + 21);
}
BOOST_AUTO_TEST_CASE(test_gradient)
{
using namespace limbo;
opt::Rprop<Params> optimizer;
simple_calls = 0;
check_grad = true;
Eigen::VectorXd best_point = optimizer(simple_func, Eigen::VectorXd::Constant(1, 2.0), false);
BOOST_CHECK_EQUAL(best_point.size(), 1);
BOOST_CHECK(std::abs(best_point(0) + 1.) < 1e-3);
BOOST_CHECK_EQUAL(simple_calls, Params::opt_rprop::iterations());
}
BOOST_AUTO_TEST_CASE(test_parallel_repeater)
{
#ifdef USE_TBB
static tbb::task_scheduler_init init(1);
#endif
using namespace limbo;
opt::ParallelRepeater<Params, opt::Rprop<Params>> optimizer;
simple_calls = 0;
check_grad = false;
starting_points.clear();
Eigen::VectorXd best_point = optimizer(simple_func, Eigen::VectorXd::Constant(1, 2.0), false);
BOOST_CHECK_EQUAL(best_point.size(), 1);
BOOST_CHECK(std::abs(best_point(0) + 1.) < 1e-3);
BOOST_CHECK_EQUAL(simple_calls, Params::opt_parallelrepeater::repeats() * Params::opt_rprop::iterations() + Params::opt_parallelrepeater::repeats());
BOOST_CHECK_EQUAL(starting_points.size(), simple_calls);
BOOST_CHECK(starting_points[0](0) >= 2. - Params::opt_parallelrepeater::epsilon() && starting_points[0](0) <= 2. + Params::opt_parallelrepeater::epsilon());
BOOST_CHECK(starting_points[Params::opt_rprop::iterations() + 1](0) >= 2. - Params::opt_parallelrepeater::epsilon() && starting_points[Params::opt_rprop::iterations() + 1](0) <= 2. + Params::opt_parallelrepeater::epsilon());
#ifdef USE_TBB
tools::par::init();
#endif
}
BOOST_AUTO_TEST_CASE(test_chained)
{
using namespace limbo;
......
......@@ -52,6 +52,7 @@ import time
import threading
import params
import license
from waflib import Logs
from waflib.Tools import waf_unit_test
json_ok = True
......@@ -59,7 +60,7 @@ try:
import simplejson
except:
json_ok = False
print "WARNING simplejson not found some function may not work"
Logs.pprint('YELLOW', 'WARNING: simplejson not found some function may not work')
def add_create_options(opt):
opt.add_option('--dim_in', type='int', dest='dim_in', help='Number of dimensions for the function to optimize [default: 1]')
......@@ -99,7 +100,7 @@ def create_exp(name, opt):
if not os.path.exists('exp'):
os.makedirs('exp')
if os.path.exists('exp/' + name):
print 'ERROR: experiment ' + name + ' already exists. Please remove it if you want to re-create it from scratch.'
Logs.pprint('RED', 'ERROR: experiment \'%s\' already exists. Please remove it if you want to re-create it from scratch.' % name)
return
os.mkdir('exp/' + name)
......@@ -161,7 +162,7 @@ def _sub_script(tpl, conf_file):
ld_lib_path = os.environ['LD_LIBRARY_PATH']
else:
ld_lib_path = "''"
print 'LD_LIBRARY_PATH=' + ld_lib_path
Logs.pprint('NORMAL', 'LD_LIBRARY_PATH=%s' % ld_lib_path)
# parse conf
list_exps = simplejson.load(open(conf_file))
fnames = []
......@@ -200,7 +201,7 @@ def _sub_script(tpl, conf_file):
try:
os.makedirs(directory)
except:
print "WARNING, dir:" + directory + " not be created"
Logs.pprint('YELLOW', 'WARNING: directory \'%s\' could not be created' % directory)
subprocess.call('cp ' + bin_dir + '/' + e + ' ' + directory, shell=True)
src_dir = bin_dir.replace('build/', '')
subprocess.call('cp ' + src_dir + '/params_*.txt ' + directory, shell=True)
......@@ -225,7 +226,7 @@ def _sub_script_local(conf_file):
ld_lib_path = os.environ['LD_LIBRARY_PATH']
else:
ld_lib_path = "''"
print 'LD_LIBRARY_PATH=' + ld_lib_path
Logs.pprint('NORMAL', 'LD_LIBRARY_PATH=%s' % ld_lib_path)
# parse conf
list_exps = simplejson.load(open(conf_file))
fnames = []
......@@ -264,7 +265,7 @@ def _sub_script_local(conf_file):
try:
os.makedirs(directory)
except:
print "WARNING, dir:" + directory + " not be created"
Logs.pprint('YELLOW', 'WARNING: directory \'%s\' could not be created' % directory)
subprocess.call('cp ' + bin_dir + '/' + e + ' ' + '"' + directory + '"', shell=True)
src_dir = bin_dir.replace('build/', '')
subprocess.call('cp ' + src_dir + '/params_*.txt ' + directory, shell=True)
......@@ -282,7 +283,7 @@ def run_local(conf_file, serial = True):
threads = []
for (fname, directory) in fnames:
s = "cd " + '"' + directory + '"' + " && " + "./" + fname + ' ' + arguments
print "Executing " + s
Logs.pprint('NORMAL', "Executing: %s" % s)
if not serial:
t = threading.Thread(target=run_local_one, args=(directory,s,))
threads.append(t)
......@@ -315,9 +316,9 @@ exec @exec
fnames = _sub_script(tpl, conf_file)
for (fname, directory) in fnames:
s = "qsub -d " + directory + " " + fname
print "executing:" + s
Logs.pprint('NORMAL', 'executing: %s' % s)
retcode = subprocess.call(s, shell=True, env=None)
print "qsub returned:" + str(retcode)
Logs.pprint('NORMAL', 'qsub returned: %s' % str(retcode))
def oar(conf_file):
......@@ -329,13 +330,13 @@ def oar(conf_file):
export LD_LIBRARY_PATH=@ld_lib_path
exec @exec
"""
print 'WARNING [oar]: MPI not supported yet'
Logs.pprint('YELLOW', 'WARNING [oar]: MPI not supported yet')
fnames = _sub_script(tpl, conf_file)
for (fname, directory) in fnames:
s = "oarsub -d " + directory + " -S " + fname
print "executing:" + s
Logs.pprint('NORMAL', 'executing: %s' % s)
retcode = subprocess.call(s, shell=True, env=None)
print "oarsub returned:" + str(retcode)
Logs.pprint('NORMAL', 'oarsub returned: %s' % str(retcode))
def output_params(folder):
files = [each for each in os.listdir(folder) if each.endswith('.cpp')]
......
......@@ -295,6 +295,7 @@ class xcode(Build.BuildContext):
cmd = 'xcode'
fun = 'build'
create_shell_script()
def collect_source(self, tg):
source_files = tg.to_nodes(getattr(tg, 'source', []))
plist_files = tg.to_nodes(getattr(tg, 'mac_plist', []))
......@@ -354,5 +355,3 @@ class xcode(Build.BuildContext):
node.mkdir()
node = node.make_node('project.pbxproj')
p.write(open(node.abspath(), 'w'))
......@@ -59,6 +59,7 @@ import os
import subprocess
import limbo
import inspect
from waflib import Logs
from waflib.Build import BuildContext
def options(opt):
......@@ -131,31 +132,32 @@ def configure(conf):
all_flags = common_flags + opt_flags
conf.env['CXXFLAGS'] = conf.env['CXXFLAGS'] + all_flags.split(' ')
print 'CXXFLAGS:', conf.env['CXXFLAGS']
Logs.pprint('NORMAL', 'CXXFLAGS: %s' % conf.env['CXXFLAGS'])
if conf.options.exp:
for i in conf.options.exp.split(','):
print 'configuring for exp: ' + i
Logs.pprint('NORMAL', 'configuring for exp: %s' % i)
conf.recurse('exp/' + i)
conf.recurse('src/benchmarks')
print ''
print 'WHAT TO DO NOW?'
print '---------------'
print '[users] To compile Limbo (inc. unit tests): ./waf build'
print '[users] Read the documentation (inc. tutorials) on http://www.resibots.eu/limbo'
print '[developers] To compile the HTML documentation (this requires sphinx and the resibots theme): ./waf doc'
print '[developers] To compile the benchmarks: ./waf build_benchmarks'
print '[developers] To compile the extensive tests: ./waf build_extensive_tests'
Logs.pprint('NORMAL', '')
Logs.pprint('NORMAL', 'WHAT TO DO NOW?')
Logs.pprint('NORMAL', '---------------')
Logs.pprint('NORMAL', '[users] To compile Limbo: ./waf build')
Logs.pprint('NORMAL', '[users] To compile and run unit tests: ./waf --tests')
Logs.pprint('NORMAL', '[users] Read the documentation (inc. tutorials) on http://www.resibots.eu/limbo')
Logs.pprint('NORMAL', '[developers] To compile the HTML documentation (this requires sphinx and the resibots theme): ./waf docs')
Logs.pprint('NORMAL', '[developers] To compile the benchmarks: ./waf build_benchmark')
Logs.pprint('NORMAL', '[developers] To compile the extensive tests: ./waf build_extensive_tests')
def build(bld):
if bld.options.write_params:
limbo.write_default_params(bld.options.write_params)
print 'default parameters written in ' + bld.options.write_params
Logs.pprint('NORMAL', 'default parameters written in %s' % bld.options.write_params)
bld.recurse('src/')
if bld.options.exp:
for i in bld.options.exp.split(','):
print 'Building exp: ' + i
Logs.pprint('NORMAL', 'Building exp: %d' % i)
bld.recurse('exp/' + i)
limbo.output_params('exp/'+i)
bld.add_post_fun(limbo.summary)
......@@ -171,7 +173,7 @@ def run_extensive_tests(ctx):
for fullname in glob.glob('build/src/tests/combinations/*'):
if os.path.isfile(fullname) and os.access(fullname, os.X_OK):
fpath, fname = os.path.split(fullname)
print "Running: " + fname
Logs.pprint('NORMAL', 'Running: %s' % fname)
s = "cd " + fpath + "; ./" + fname
retcode = subprocess.call(s, shell=True, env=None)
......@@ -181,7 +183,7 @@ def submit_extensive_tests(ctx):
fpath, fname = os.path.split(fullname)
s = "cd " + fpath + ";oarsub -l /nodes=1/core=2,walltime=00:15:00 -n " + fname + " -O " + fname + ".stdout.%jobid%.log -E " + fname + ".stderr.%jobid%.log ./" + fname
retcode = subprocess.call(s, shell=True, env=None)
print "oarsub returned:" + str(retcode)
Logs.pprint('NORMAL', 'oarsub returned: %s' % str(retcode))
def run_benchmark(ctx):
HEADER='\033[95m'
......@@ -190,7 +192,7 @@ def run_benchmark(ctx):
try:
os.makedirs(res_dir)
except:
print "WARNING, dir:" + res_dir + " not be created"
Logs.pprint('YELLOW', 'WARNING: directory \'%s\' could not be created!' % res_dir)
for fullname in glob.glob('build/src/benchmarks/*'):
if os.path.isfile(fullname) and os.access(fullname, os.X_OK):
fpath, fname = os.path.split(fullname)
......@@ -198,7 +200,7 @@ def run_benchmark(ctx):
try:
os.makedirs(directory)
except:
print "WARNING, dir:" + directory + " not be created, the new results will be concatenated to the old ones"
Logs.pprint('YELLOW', 'WARNING: directory \'%s\' could not be created, the new results will be concatenated to the old ones' % directory)
s = "cp " + fullname + " " + directory
retcode = subprocess.call(s, shell=True, env=None)
if ctx.options.nb_rep:
......@@ -206,7 +208,7 @@ def run_benchmark(ctx):
else:
nb_rep = 10
for i in range(0,nb_rep):
print HEADER+" Running: " + fname + " for the "+str(i)+"th time"+NC
Logs.pprint('NORMAL', '%s Running: %s for the %s th time %s' % (HEADER, fname, str(i), NC))
s="cd " + directory +";./" + fname
retcode = subprocess.call(s, shell=True, env=None)
......@@ -226,15 +228,12 @@ def insert_license(ctx):
limbo.insert_license()
def write_default_params(ctx):
print('extracting default params to docs/defaults.rst')
Logs.pprint('NORMAL', 'extracting default params to docs/defaults.rst')
limbo.write_default_params('docs/defaults.rst')
#print("to install sphinx-versioning: sudo pip3 install git+https://github.com/resibots/sphinxcontrib-versioning.git@resibots")
def build_docs(ctx):
print("generating HTML doc with versioning...")
Logs.pprint('NORMAL', "generating HTML doc with versioning...")
s = 'sphinx-versioning -v build -p docs/pre_script.sh --whitelist-branches "(master|doc_versioning|release-*)" docs docs/_build/html'
print(s)
retcode = subprocess.call(s, shell=True, env=None)
class BuildExtensiveTestsContext(BuildContext):
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment