25 #include<gsl/gsl_odeiv2.h>
26 #include<gsl/gsl_errno.h>
29 #include "../exceptions.h"
31 #include "../population.h"
32 #include "base_stochastic.h"
33 #include "spheres_q.h"
35 static const int nr_input = 8;
36 static const int nr_output = 3;
37 static const int nr_spheres = 3;
38 static const int nr_eq = 21;
39 static const double target_distance2 = 0.25;
40 static const double target_distance = 0.5;
43 static double norm(
double v[3]) {
44 return(std::sqrt(v[0]*v[0] + v[1]*v[1] +v[2]*v[2]));
47 static double norm2(
double v[3]) {
48 return(v[0]*v[0] + v[1]*v[1] +v[2]*v[2]);
51 static void versify(
double v[3]) {
53 if (V<=0) printf(
"Warning zero norm vector passed to versify");
59 static void cross_vector(
double vout[3],
const double vin1[3],
const double vin2[3]) {
60 vout[0] = vin1[1]*vin2[2] - vin1[2]*vin2[1];
61 vout[1] = vin1[2]*vin2[0] - vin1[0]*vin2[2];
62 vout[2] = vin1[0]*vin2[1] - vin1[1]*vin2[0];
68 void q2C(
double Cout[3][3],
const double q[4] )
75 double Nq = w*w + x*x + y*y + z*z;
76 double s = ( (Nq > 0.0) ? (2.0 / Nq) : (0.0) );
81 Cout[0][0] = 1.0 - (y*Y + z*Z);
82 Cout[0][1] = x*Y - w*Z;
83 Cout[0][2] = x*Z + w*Y;
85 Cout[1][0] = x*Y + w*Z;
86 Cout[1][1] = 1.0 - (x*X + z*Z);
87 Cout[1][2] = y*Z - w*X;
89 Cout[2][0] = x*Z - w*Y;
90 Cout[2][1] = y*Z + w*X;
91 Cout[2][2] = 1.0 - (x*X + y*Y);
100 static void matrix_transformation(
double vout[3],
const double R[3][3]) {
102 vout_cp[0] = vout[0]; vout_cp[1] = vout[1]; vout_cp[2] = vout[2];
103 for (
int i=0;i<3;++i) {
104 vout[i] = R[i][0] * vout_cp[0] + R[i][1] * vout_cp[1] + R[i][2] * vout_cp[2];
109 static void matrix_inv_transformation(
double vout[3],
const double R[3][3]) {
111 vout_cp[0] = vout[0]; vout_cp[1] = vout[1]; vout_cp[2] = vout[2];
112 for (
int i=0;i<3;++i) {
113 vout[i] = R[0][i] * vout_cp[0] + R[1][i] * vout_cp[1] + R[2][i] * vout_cp[2];
117 static void quat_dyn(
double dq[4],
const double q[4],
const double w[3]) {
118 dq[0] = 0.5 * (q[1]*w[2] - q[2]*w[1] + q[3]*w[0]);
119 dq[1] = 0.5 * (q[2]*w[0] - q[0]*w[2] + q[3]*w[1]);
120 dq[2] = 0.5 * (q[0]*w[1] - q[1]*w[0] + q[3]*w[2]);
121 dq[3] = -0.5 * (q[0]*w[0] + q[1]*w[1] + q[2]*w[2]);
124 namespace pagmo {
namespace problem {
127 double numerical_precision,
unsigned int seed) :
128 base_stochastic((nr_input + 1) * n_hidden_neurons + (n_hidden_neurons + 1) * nr_output, seed),
129 m_ffnn(nr_input,n_hidden_neurons,nr_output), m_n_evaluations(n_evaluations),
130 m_n_hidden_neurons(n_hidden_neurons), m_numerical_precision(numerical_precision),
136 gsl_odeiv2_system sys = {ode_func,NULL,nr_eq,&m_ffnn};
138 m_gsl_drv_pntr = gsl_odeiv2_driver_alloc_y_new(&m_sys, gsl_odeiv2_step_rk8pd, 1e-6,m_numerical_precision,0.0);
143 m_ffnn(other.m_ffnn),
144 m_n_evaluations(other.m_n_evaluations),m_n_hidden_neurons(other.m_n_hidden_neurons),
145 m_numerical_precision(other.m_numerical_precision),m_ic(other.m_ic)
148 gsl_odeiv2_system sys = {ode_func,NULL,nr_eq,&m_ffnn};
150 m_gsl_drv_pntr = gsl_odeiv2_driver_alloc_y_new(&m_sys, gsl_odeiv2_step_rk8pd, 1e-6,m_numerical_precision,0.0);
154 gsl_odeiv2_driver_free(m_gsl_drv_pntr);
164 double spheres_q::single_fitness(
const std::vector<double> &y,
const ffnn& neural_net)
const {
166 double context[8], vel_f[3], C[3][3];
170 for(
int i = 0; i < nr_spheres; i++ ){
174 for(
int n = 1; n <= nr_spheres - 1; n++ ){
175 for(
int j = 0; j < 3; j++ ){
176 context[k++] = y[i*3 + j] - y[ (i*3 + j + n*3) % 9 ];
182 context[6] = context[0]*context[0] + context[1]*context[1] + context[2]*context[2];
183 context[7] = context[3]*context[3] + context[4]*context[4] + context[5]*context[5];
187 matrix_transformation(&context[0],C);
188 matrix_transformation(&context[3],C);
191 neural_net.eval(vel_f, context);
192 vel_f[0] = vel_f[0] * 2 * 0.3 - 0.3;
193 vel_f[1] = vel_f[1] * 2 * 0.3 - 0.3;
194 vel_f[2] = vel_f[2] * 2 * 0.3 - 0.3;
197 double temp = std::abs(target_distance2 - context[6]);
199 temp = std::abs(target_distance2 - context[7]);
208 int spheres_q::ode_func(
double t,
const double y[],
double f[],
void *params ) {
211 ffnn *ptr_ffnn = (ffnn*)params;
215 double context[nr_input];
216 double out[nr_output];
223 for(
int i = 0; i < nr_spheres; i++ ){
227 for(
int n = 1; n <= nr_spheres - 1; n++ ){
228 for(
int j = 0; j < 3; j++ ){
229 context[k++] = y[i*3 + j] - y[ (i*3 + j + n*3) % 9 ];
235 context[6] = context[0]*context[0] + context[1]*context[1] + context[2]*context[2];
236 context[7] = context[3]*context[3] + context[4]*context[4] + context[5]*context[5];
240 matrix_transformation(&context[0],C);
241 matrix_transformation(&context[3],C);
244 ptr_ffnn->eval(out, context);
245 out[0] = out[0] * 0.3 * 2 - 0.3;
246 out[1] = out[1] * 0.3 * 2 - 0.3;
247 out[2] = out[2] * 0.3 * 2 - 0.3;
250 matrix_inv_transformation(&out[0],C);
261 f[9+i*4] = 0; f[10+i*4] = 0; f[11+i*4] = 0; f[12+i*4] = 0;
267 spheres_q::ffnn::ffnn(
const unsigned int n_inputs,
const unsigned int n_hidden,
const unsigned int n_outputs) :
268 m_n_inputs(n_inputs), m_n_hidden(n_hidden), m_n_outputs(n_outputs),
269 m_weights((n_inputs + 1) * n_hidden + (n_hidden + 1) * n_outputs), m_hidden(n_hidden)
272 void spheres_q::ffnn::set_weights(
const std::vector<double> &weights) {
276 void spheres_q::ffnn::eval(
double out[],
const double in[])
const {
278 unsigned int offset = m_n_hidden * (m_n_inputs + 1);
281 for(
unsigned int i = 0; i < m_n_hidden; i++ ){
283 m_hidden[i] = m_weights[i * (m_n_inputs + 1)];
285 for(
unsigned int j = 0; j < m_n_inputs; j++ ){
287 int ji = i * (m_n_inputs + 1) + (j + 1);
289 m_hidden[i] += m_weights[ji] * in[j];
293 m_hidden[i] = 1.0 / ( 1 + std::exp( -m_hidden[i] ));
297 for(
unsigned int i = 0; i < m_n_outputs; i++ ){
299 out[i] = m_weights[offset + i * (m_n_hidden + 1)];
301 for(
unsigned int j = 0; j < m_n_hidden; j++ ){
303 int ji = offset + i * (m_n_hidden + 1) + (j + 1);
305 out[i] += m_weights[ji] * m_hidden[j];
308 out[i] = 1.0 / ( 1 + std::exp( -out[i] ));
319 m_ffnn.set_weights(x);
322 for (
int count=0;count<m_n_evaluations;++count) {
326 for (
int i=0; i<9; ++i) {
327 m_ic[i] = (
m_drng()*4 - 2);
332 for(
int it = 0; it< nr_spheres; ++it) {
336 double radice = sqrt(1-u1);
337 m_ic[9 + 4*it] = radice*sin(2*u2*M_PI);
338 m_ic[10 + 4*it] = radice*cos(2*u2*M_PI);
340 m_ic[11 + 4*it] = radice*sin(2*u3*M_PI);
341 m_ic[12 + 4*it] = radice*cos(2*u3*M_PI);
348 int status = gsl_odeiv2_driver_apply( m_gsl_drv_pntr, &t0, tf, &m_ic[0] );
350 gsl_odeiv2_driver_reset (m_gsl_drv_pntr);
351 if( status != GSL_SUCCESS ){
352 printf (
"ERROR: gsl_odeiv2_driver_apply returned value = %d\n", status);
355 f[0] += single_fitness(m_ic,m_ffnn);
358 f[0] /= m_n_evaluations;
361 static bool my_sort_function (std::vector<double> i,std::vector<double> j) {
return (i[nr_eq] < j[nr_eq]); }
364 std::vector<double> one_row(nr_eq+1,0.0);
365 std::vector<std::vector<double> > ret(N,one_row);
369 m_ffnn.set_weights(x);
371 for (
int count=0;count<N;++count) {
374 for (
int i=0; i<9; ++i) {
375 m_ic[i] = (
m_drng()*2 - 1);
376 one_row[i] = m_ic[i];
381 for(
int it = 0; it< nr_spheres; ++it) {
385 double radice = sqrt(1-u1);
386 m_ic[9 + 4*it] = radice*sin(2*u2*M_PI);
387 m_ic[10 + 4*it] = radice*cos(2*u2*M_PI);
389 m_ic[11 + 4*it] = radice*sin(2*u3*M_PI);
390 m_ic[12 + 4*it] = radice*cos(2*u3*M_PI);
391 one_row[9+ 4*it] = m_ic[9 + 4*it];
392 one_row[10+ 4*it] = m_ic[10 + 4*it];
393 one_row[11+ 4*it] = m_ic[11 + 4*it];
394 one_row[12+ 4*it] = m_ic[12 + 4*it];
402 int status = gsl_odeiv2_driver_apply( m_gsl_drv_pntr, &t0, tf, &m_ic[0] );
405 if( status != GSL_SUCCESS ){
406 printf (
"ERROR: gsl_odeiv2_driver_apply returned value = %d\n", status);
409 one_row[nr_eq] = single_fitness(m_ic,m_ffnn);
410 ret[count] = one_row;
413 std::sort (ret.begin(), ret.end(), my_sort_function);
418 std::vector<double> y0(ic);
419 std::vector<double> one_row(nr_eq+1,0.0);
420 std::vector<std::vector<double> > ret;
422 m_ffnn.set_weights(x);
429 std::copy(y0.begin(),y0.end(),one_row.begin()+1);
430 ret.push_back(one_row);
432 for(
int i = 1; i <= N; i++ ){
434 int status = gsl_odeiv2_driver_apply( m_gsl_drv_pntr, &t0, ti, &y0[0] );
437 std::copy(y0.begin(),y0.end(),one_row.begin()+1);
438 ret.push_back(one_row);
439 if( status != GSL_SUCCESS ){
440 printf (
"ERROR: gsl_odeiv2_driver_apply returned value = %d\n", status);
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base problem.
std::vector< double > decision_vector
Decision vector type.
spheres_q(int n_evaluations=10, int n_hidden=10, double ode_prec=1E-3, unsigned int seed=0)
Constructor.
rng_double m_drng
Random number generator for double-precision floating point values.
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 > > simulate(const decision_vector &x, const std::vector< double > &ic, int N) const
Performs one "detailed" simulation.
std::vector< double > fitness_vector
Fitness vector type.
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.
Base Stochastic Optimization Problem.
base_ptr clone() const
Clone method.
Evolutionary Neuro-Controller for the MIT Spheres (perception-action defined in the body frame) ...
void objfun_impl(fitness_vector &, const decision_vector &) const
Objective function implementation.