25 #include<gsl/gsl_odeiv2.h>
26 #include<gsl/gsl_errno.h>
30 #include "../exceptions.h"
32 #include "../population.h"
33 #include "base_stochastic.h"
36 static const int nr_input = 8;
37 static const int nr_output = 3;
38 static const int nr_spheres = 3;
39 static const int nr_eq = 9;
41 static double norm2(
double v[3]) {
42 return(v[0]*v[0] + v[1]*v[1] +v[2]*v[2]);
45 namespace pagmo {
namespace problem {
48 double numerical_precision,
unsigned int seed,
bool symmetric,
double sim_time,
const std::vector<double>& sides) :
49 base_stochastic((nr_input/(int(symmetric)+1) + 1) * n_hidden_neurons + (n_hidden_neurons + 1) * nr_output, seed),
50 m_ffnn(nr_input,n_hidden_neurons,nr_output), m_n_evaluations(n_evaluations),
51 m_n_hidden_neurons(n_hidden_neurons), m_numerical_precision(numerical_precision),
52 m_ic(nr_eq), m_symm(symmetric), m_sim_time(sim_time), m_sides(sides) {
57 gsl_odeiv2_system sys = {ode_func,NULL,nr_eq,&m_ffnn};
59 m_gsl_drv_pntr = gsl_odeiv2_driver_alloc_y_new(&m_sys, gsl_odeiv2_step_rk8pd, 1e-6,m_numerical_precision,0.0);
61 std::sort(m_sides.begin(),m_sides.end());
62 m_sides[0]*=m_sides[0]; m_sides[1]*=m_sides[1]; m_sides[2]*=m_sides[2];
68 m_n_evaluations(other.m_n_evaluations),m_n_hidden_neurons(other.m_n_hidden_neurons),
69 m_numerical_precision(other.m_numerical_precision),m_ic(other.m_ic), m_symm(other.m_symm), m_sim_time(other.m_sim_time),m_sides(other.m_sides)
72 gsl_odeiv2_system sys = {ode_func,NULL,nr_eq,&m_ffnn};
74 m_gsl_drv_pntr = gsl_odeiv2_driver_alloc_y_new(&m_sys, gsl_odeiv2_step_rk8pd, 1e-6,m_numerical_precision,0.0);
78 gsl_odeiv2_driver_free(m_gsl_drv_pntr);
88 double spheres::single_fitness(
const std::vector<double> &y,
const ffnn& neural_net)
const {
92 double context[8], vel_f[3];
96 for(
int i = 0; i < nr_spheres; i++ ){
100 for(
int n = 1; n <= nr_spheres - 1; n++ ){
101 for(
int j = 0; j < 3; j++ ){
102 context[k++] = y[i*3 + j] - y[ (i*3 + j + n*3) % 9 ];
108 context[6] = context[0]*context[0] + context[1]*context[1] + context[2]*context[2];
109 context[7] = context[3]*context[3] + context[4]*context[4] + context[5]*context[5];
112 neural_net.eval(vel_f, context);
113 vel_f[0] = vel_f[0] * 2 * 0.3 - 0.3;
114 vel_f[1] = vel_f[1] * 2 * 0.3 - 0.3;
115 vel_f[2] = vel_f[2] * 2 * 0.3 - 0.3;
118 fit += 2 *(norm2(vel_f));
128 #define SRT_PAIR(a,b) if ((b)<(a)) {(tmp=a);(a=b);(b=tmp);}
130 double a2 = (y[0]-y[3])*(y[0]-y[3]) + (y[1]-y[4])*(y[1]-y[4]) + (y[2]-y[5])*(y[2]-y[5]);
131 double b2 = (y[0]-y[6])*(y[0]-y[6]) + (y[1]-y[7])*(y[1]-y[7]) + (y[2]-y[8])*(y[2]-y[8]);
132 double c2 = (y[6]-y[3])*(y[6]-y[3]) + (y[7]-y[4])*(y[7]-y[4]) + (y[8]-y[5])*(y[8]-y[5]);
139 fit += (a2-m_sides[0])*(a2-m_sides[0])+(b2-m_sides[1])*(b2-m_sides[1])+(c2-m_sides[2])*(c2-m_sides[2]);
144 int spheres::ode_func(
double t,
const double y[],
double f[],
void *params ) {
147 ffnn *ptr_ffnn = (ffnn*)params;
151 double context[nr_input];
152 double out[nr_output];
158 for(
int i = 0; i < nr_spheres; i++ ){
162 for(
int n = 1; n <= nr_spheres - 1; n++ ){
163 for(
int j = 0; j < 3; j++ ){
164 context[k++] = y[i*3 + j] - y[ (i*3 + j + n*3) % 9 ];
170 context[6] = context[0]*context[0] + context[1]*context[1] + context[2]*context[2];
171 context[7] = context[3]*context[3] + context[4]*context[4] + context[5]*context[5];
174 ptr_ffnn->eval(out, context);
177 f[i*3] = out[0] * 0.3 * 2 - 0.3;
178 f[i*3+1] = out[1] * 0.3 * 2 - 0.3;
179 f[i*3+2] = out[2] * 0.3 * 2 - 0.3;
185 spheres::ffnn::ffnn(
const unsigned int n_inputs,
const unsigned int n_hidden,
const unsigned int n_outputs) :
186 m_n_inputs(n_inputs), m_n_hidden(n_hidden), m_n_outputs(n_outputs),
187 m_weights((n_inputs + 1) * n_hidden + (n_hidden + 1) * n_outputs), m_hidden(n_hidden)
190 void spheres::ffnn::set_weights(
const std::vector<double> &weights) {
194 void spheres::ffnn::eval(
double out[],
const double in[])
const {
196 unsigned int offset = m_n_hidden * (m_n_inputs + 1);
199 for(
unsigned int i = 0; i < m_n_hidden; i++ ){
201 m_hidden[i] = m_weights[i * (m_n_inputs + 1)];
203 for(
unsigned int j = 0; j < m_n_inputs; j++ ){
205 int ji = i * (m_n_inputs + 1) + (j + 1);
207 m_hidden[i] += m_weights[ji] * in[j];
211 m_hidden[i] = 1.0 / ( 1 + std::exp( -m_hidden[i] ));
215 for(
unsigned int i = 0; i < m_n_outputs; i++ ){
217 out[i] = m_weights[offset + i * (m_n_hidden + 1)];
219 for(
unsigned int j = 0; j < m_n_hidden; j++ ){
221 int ji = offset + i * (m_n_hidden + 1) + (j + 1);
223 out[i] += m_weights[ji] * m_hidden[j];
226 out[i] = 1.0 / ( 1 + std::exp( -out[i] ));
237 for (
int count=0;count<m_n_evaluations;++count) {
240 for (
int i=0; i<6; ++i) {
241 m_ic[i] = (
m_drng()*2 - 1);
245 m_ic[6] = - (m_ic[0] + m_ic[3]);
246 m_ic[7] = - (m_ic[1] + m_ic[4]);
247 m_ic[8] = - (m_ic[2] + m_ic[5]);
251 double tf = m_sim_time;
253 int status = gsl_odeiv2_driver_apply( m_gsl_drv_pntr, &t0, tf, &m_ic[0] );
255 gsl_odeiv2_driver_reset (m_gsl_drv_pntr);
256 if( status != GSL_SUCCESS ){
257 printf (
"ERROR: gsl_odeiv2_driver_apply returned value = %d\n", status);
260 f[0] += single_fitness(m_ic,m_ffnn);
263 f[0] /= m_n_evaluations;
266 static bool my_sort_function (std::vector<double> i,std::vector<double> j) {
return (i[9] < j[9]); }
269 std::vector<double> one_row(10,0.0);
270 std::vector<std::vector<double> > ret(N,one_row);
276 for (
int count=0;count<N;++count) {
280 for (
int i=0; i<6; ++i) {
281 m_ic[i] = (
m_drng()*2 - 1);
284 m_ic[6] = - (m_ic[0] + m_ic[3]);
285 m_ic[7] = - (m_ic[1] + m_ic[4]);
286 m_ic[8] = - (m_ic[2] + m_ic[5]);
288 for (
int i=0; i<9; ++i) {
289 one_row[i] = m_ic[i];
294 double tf = m_sim_time;
296 int status = gsl_odeiv2_driver_apply( m_gsl_drv_pntr, &t0, tf, &m_ic[0] );
299 if( status != GSL_SUCCESS ){
300 printf (
"ERROR: gsl_odeiv2_driver_apply returned value = %d\n", status);
303 one_row[9] = single_fitness(m_ic,m_ffnn);
304 ret[count] = one_row;
307 std::sort (ret.begin(), ret.end(), my_sort_function);
314 for(
unsigned int h = 0; h < m_ffnn.m_n_hidden; h++)
316 int start_index = h * 5;
318 for(
int j = 0; j < 4; j++)
320 m_ffnn.m_weights[w] = x[start_index+j]; w++;
323 for(
int j = 1; j <= 3; j++)
325 m_ffnn.m_weights[w] = x[start_index+j]; w++;
328 m_ffnn.m_weights[w] = x[start_index+4]; w++;
330 m_ffnn.m_weights[w] = x[start_index+4]; w++;
333 for(
unsigned int ww = w; ww < m_ffnn.m_weights.size(); ww++)
335 m_ffnn.m_weights[ww] = x[(nr_input/2+1)*m_ffnn.m_n_hidden+ind];
339 m_ffnn.m_weights = x;
344 std::vector<double> y0(ic);
345 std::vector<double> one_row(10,0.0);
346 std::vector<std::vector<double> > ret;
351 double tf = m_sim_time;
355 std::copy(y0.begin(),y0.end(),one_row.begin()+1);
356 ret.push_back(one_row);
358 for(
int i = 1; i <= N; i++ ){
360 int status = gsl_odeiv2_driver_apply( m_gsl_drv_pntr, &t0, ti, &y0[0] );
363 std::copy(y0.begin(),y0.end(),one_row.begin()+1);
364 ret.push_back(one_row);
365 if( status != GSL_SUCCESS ){
366 printf (
"ERROR: gsl_odeiv2_driver_apply returned value = %d\n", status);
377 return m_ffnn.m_weights;
382 return "MIT SPHERES - Neurocontroller Evolution";
391 std::ostringstream oss;
392 oss <<
"\n\tSample Size: " << m_n_evaluations <<
'\n';
393 oss <<
"\tHidden Neurons: " << m_n_hidden_neurons <<
'\n';
394 oss <<
"\tODE precision: " << m_numerical_precision <<
'\n';
395 oss <<
"\tSeed: " <<
m_seed <<
'\n';
396 oss <<
"\tSymmetric Weights: " << m_symm <<
'\n';
397 oss <<
"\tSimulation time: " << m_sim_time <<
'\n';
398 oss <<
"\tTriangle sides (squared): " << m_sides <<
'\n';
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base problem.
std::vector< double > decision_vector
Decision vector type.
base_ptr clone() const
Clone method.
rng_double m_drng
Random number generator for double-precision floating point values.
std::string human_readable_extra() const
Extra human readable info for the problem.
void set_lb(const decision_vector &)
Set lower bounds from pagmo::decision_vector.
unsigned int m_seed
Seed of the random number generator.
void set_ub(const decision_vector &)
Set upper bounds from pagmo::decision_vector.
std::vector< std::vector< double > > post_evaluate(const decision_vector &x, int N=25000, unsigned int seed=0) const
Post evaluation of the neural controller.
std::vector< double > fitness_vector
Fitness vector type.
std::string get_name() const
Get problem's name.
Base Stochastic Optimization Problem.
void objfun_impl(fitness_vector &, const decision_vector &) const
Objective function implementation.
Evolutionary Neuro-Controller for the MIT Spheres (perception-action defined in the absolute frame) ...
std::vector< std::vector< double > > simulate(const decision_vector &x, const std::vector< double > &ic, int N) const
Performs one "detailed" simulation.
std::vector< double > get_nn_weights(decision_vector x) const
Gets the weights of the neural network.
spheres(int n_evaluations=10, int n_hidden=10, double ode_prec=1E-6, unsigned int seed=0, bool symmetric=false, double sim_time=50.0, const std::vector< double > &sides=std::vector< double >(3, 0.5))
Constructor.