Commit fab10898 authored by Martin Beseda's avatar Martin Beseda
Browse files

FIX + ENH: Fixed points going outside of domain + added new termination condition.

parent 14671335
add_library(neuron SHARED Neuron/Neuron.cpp Neuron/Neuron.h Neuron/NeuronBinary.cpp Neuron/NeuronBinary.h Neuron/NeuronLinear.cpp Neuron/NeuronLinear.h Neuron/NeuronLogistic.cpp Neuron/NeuronLogistic.h Neuron/NeuronTanh.cpp Neuron/NeuronTanh.h constants.h NetConnection/Connection.cpp NetConnection/Connection.h Network/NeuralNetwork.cpp Network/NeuralNetwork.h Neuron/NeuronNeuralNet.cpp Neuron/NeuronNeuralNet.h NetConnection/ConnectionWeight.cpp NetConnection/ConnectionWeight.h NetConnection/ConnectionWeightIdentity.cpp NetConnection/ConnectionWeightIdentity.h)
add_library(neuron SHARED
Neuron/Neuron.cpp
Neuron/Neuron.h
Neuron/NeuronBinary.cpp
Neuron/NeuronBinary.h
Neuron/NeuronLinear.cpp
Neuron/NeuronLinear.h
Neuron/NeuronLogistic.cpp
Neuron/NeuronLogistic.h
Neuron/NeuronTanh.cpp
Neuron/NeuronTanh.h
constants.h
NetConnection/Connection.cpp
NetConnection/Connection.h
Network/NeuralNetwork.cpp
Network/NeuralNetwork.h
Neuron/NeuronNeuralNet.cpp
Neuron/NeuronNeuralNet.h
NetConnection/ConnectionWeight.cpp
NetConnection/ConnectionWeight.h
NetConnection/ConnectionWeightIdentity.cpp
NetConnection/ConnectionWeightIdentity.h)
add_library(particle_swarm SHARED
LearningMethods/ParticleSwarm.cpp
LearningMethods/ParticleSwarm.h)
add_executable(test_cases main.cpp)
target_link_libraries(test_cases neuron boost_serialization)
\ No newline at end of file
target_link_libraries(test_cases neuron particle_swarm boost_serialization)
\ No newline at end of file
......@@ -5,6 +5,9 @@
* @date 2.7.18 -
*/
#include <cmath>
#include <set>
#include <stdexcept>
#include "ParticleSwarm.h"
Particle::Particle(unsigned int f_dim, double *domain_bounds, double (*F)(double*)) {
......@@ -55,6 +58,10 @@ Particle::~Particle() {
}
double* Particle::get_coordinate() {
return this->coordinate;
}
double Particle::get_optimal_value() {
return this->optimal_value;
}
......@@ -65,31 +72,39 @@ void Particle::get_optimal_coordinate(double *ref_coordinate) {
}
}
double Particle::change_coordinate(double w, double c1, double c2, double *glob_min_coord) {
double Particle::change_coordinate(double w, double c1, double c2, double *glob_min_coord, double penalty_coef) {
/**
* v = w * v + c1r1(p_min_loc - x) + c2r2(p_min_glob - x)
* x = x + v
*/
double vel_mem, output = 0.0;
double vel_mem;
double output;
bool in_domain;
double compensation_coef = 1;
for(unsigned int i = 0; i < this->coordinate_dim; ++i){
vel_mem = w * this->velocity[i] + c1 * this->r1 * (this->optimal_coordinate[i] - this->coordinate[i]) + c2 * this->r2 * (glob_min_coord[i] - this->coordinate[i]);
if( this->coordinate[i] + vel_mem > this->domain_bounds[2 * i + 1] ){
// vel_mem = vel_mem * (-1.0) * (vel_mem - this->domain_bounds[2 * i + 1]) / (this->domain_bounds[2 * i + 1] - this->velocity[i]);
vel_mem = -0.25 * w * vel_mem;
}
else if( this->coordinate[i] + vel_mem < this->domain_bounds[2 * i] ){
// vel_mem = vel_mem * (-1.0) * (this->domain_bounds[2 * i] - vel_mem) / (this->velocity[i] - this->domain_bounds[2 * i]);
vel_mem = -0.25 * w * vel_mem;
}
do{
if (this->coordinate[i] + vel_mem > this->domain_bounds[2 * i + 1]) {
in_domain = false;
vel_mem = -penalty_coef * compensation_coef * w * vel_mem;
compensation_coef /= 2;
} else if (this->coordinate[i] + vel_mem < this->domain_bounds[2 * i]) {
in_domain = false;
vel_mem = penalty_coef * compensation_coef * w * vel_mem;
compensation_coef /= 2;
} else {
in_domain = true;
compensation_coef = 1;
}
}while(!in_domain);
this->velocity[i] = vel_mem;
this->coordinate[i] += vel_mem;
output += vel_mem * vel_mem;
output += std::abs(vel_mem);
}
vel_mem = this->f(this->coordinate);
......@@ -101,8 +116,6 @@ double Particle::change_coordinate(double w, double c1, double c2, double *glob_
}
}
// this->print_coordinate();
return output;
}
......@@ -155,47 +168,86 @@ ParticleSwarm::~ParticleSwarm() {
}
void ParticleSwarm::optimize( double epsilon ) {
epsilon *= epsilon;
/**
*
* @param gamma
* @param epsilon
* @param delta
*/
void ParticleSwarm::optimize( double gamma, double epsilon, double delta) {
if(epsilon < 0 || gamma < 0 || delta < 0) {
throw std::invalid_argument("Parameters 'gamma', 'epsilon' and 'delta' must be greater than or equal to zero!");
}
unsigned int outer_it = 0;
double optimum_step = epsilon * 10;
Particle *particle;
double *p_min_glob = new double[this->func_dim];
double optimal_value;
this->determine_optimal_coordinate_and_value(p_min_glob, optimal_value);
double optimum_prev;
std::set<Particle*> cluster; //!< Particles in a cluster
double* coords;
coords = new double[this->func_dim]; //<! Centroid coordinates
double max_velocity, mem;
printf("%10d: max. velocity^2: %10.8f, optimum: %10.5f\n", outer_it, max_velocity, optimal_value);
while( outer_it < this->iter_max && optimum_step > epsilon ){
double tmp_velocity;
double prev_max_velocity = 0;
double max_velocity;
double max_vel_step = 0;
double prev_max_vel_step;
optimum_prev = optimal_value;
while( outer_it < this->iter_max ) {
max_velocity = 0;
//////////////////////////////////////////////////
// Clustering algorithm - termination condition //
//////////////////////////////////////////////////
particle = this->determine_optimal_coordinate_and_value(p_min_glob, optimal_value);
cluster.insert(particle);
max_velocity = 0.0;
for(unsigned int pi = 0; pi < this->n_particles; ++pi){
particle = this->particle_swarm[pi];
mem = particle->change_coordinate( this->w, this->c1, this->c2, p_min_glob );
for(unsigned int i=0; i < 5; i++) {
if(mem > max_velocity){
max_velocity = mem;
/* Looking for a centroid */
for (auto it : cluster) {
for (unsigned int di = 0; di < this->func_dim; di++) {
coords[di] += it->get_coordinate()[di];
}
}
}
this->determine_optimal_coordinate_and_value(p_min_glob, optimal_value);
for(unsigned int di = 0; di < this->func_dim; di++) {
coords[di] /= cluster.size();
}
for(unsigned int pi=0; pi < this->n_particles; pi++) {
particle = this->particle_swarm[pi];
tmp_velocity = particle->change_coordinate( this->w, this->c1, this->c2, p_min_glob);
if(tmp_velocity > max_velocity) {
prev_max_velocity = max_velocity;
max_velocity = tmp_velocity;
}
/* Looking for nearby particles */
printf("iter: %d, pi: %d, euclidean dist: %f\n", outer_it, pi, this->get_euclidean_distance(particle->get_coordinate(), coords, this->func_dim));
if(this->get_euclidean_distance(particle->get_coordinate(), coords, this->func_dim) < epsilon) {
cluster.insert(particle);
}
}
}
// optimum_step = std::abs( optimal_value - optimum_prev );
optimum_step = max_velocity;
prev_max_vel_step = max_vel_step;
max_vel_step = max_velocity - prev_max_velocity;
printf("%10d: max. velocity^2: %10.8f, optimum: %10.5f\n", outer_it, max_velocity, optimal_value);
/* Check if the particles are near to each other AND the maximal velocity is less than 'gamma' */
// printf("cluster size: %ld, n particles: %d, %f\n", cluster.size(), this->n_particles, double(cluster.size())/this->n_particles);
printf("cluster: %f\n", double(cluster.size())/this->n_particles);
printf("real gamma: %f\n", std::abs(prev_max_vel_step/max_vel_step));
if(double(cluster.size())/this->n_particles > delta && std::abs(prev_max_vel_step/max_vel_step) > gamma) {
break;
}
outer_it++;
// this->w *= 0.999;
// this->w *= 0.99;
}
// printf("\n");
printf("Found optimum in %6d iterations: %10.8f at coordinate: ", outer_it, optimal_value);
for(unsigned int i = 0; i < this->func_dim - 1; ++i){
......@@ -204,13 +256,16 @@ void ParticleSwarm::optimize( double epsilon ) {
printf("%10.8f\n", p_min_glob[this->func_dim - 1]);
delete [] p_min_glob;
delete [] coords;
}
void ParticleSwarm::determine_optimal_coordinate_and_value(double *coord, double &val) {
Particle* ParticleSwarm::determine_optimal_coordinate_and_value(double *coord, double &val) {
Particle* p;
val = this->particle_swarm[0]->get_optimal_value( );
this->particle_swarm[0]->get_optimal_coordinate(coord);
p = this->particle_swarm[0];
for(unsigned int i = 1; i < this->n_particles; ++i){
......@@ -219,6 +274,38 @@ void ParticleSwarm::determine_optimal_coordinate_and_value(double *coord, double
if(val_m < val){
val = val_m;
this->particle_swarm[i]->get_optimal_coordinate(coord);
p = this->particle_swarm[i];
}
}
return p;
}
double* ParticleSwarm::get_centroid_coordinates() {
double* coords = new double[this->func_dim];
double* tmp;
for (unsigned int pi = 0; pi < this->n_particles; pi++) {
tmp = this->particle_swarm[pi]->get_coordinate();
for (unsigned int di = 0; di < this->func_dim; di++) {
coords[di] += tmp[di];
}
}
for(unsigned int di = 0; di < this->func_dim; di++) {
coords[di] /= this->n_particles;
}
return coords;
}
double ParticleSwarm::get_euclidean_distance(double* a, double* b, int n) {
double dist = 0;
for(unsigned int i = 0; i < n; i++) {
if((a[i]-b[i]) * (a[i]-b[i]) > 1000) {
}
dist += ((a[i]-b[i]) * (a[i]-b[i]));
}
return std::sqrt(dist);
}
\ No newline at end of file
......@@ -42,6 +42,12 @@ public:
Particle(unsigned int f_dim, double *domain_bounds, double (*F)(double*));
~Particle( );
/**
*
* @return
*/
double* get_coordinate();
/**
*
* @return
......@@ -60,9 +66,9 @@ public:
* @param c1
* @param c2
* @param glob_min_coord
* @return
* @param penalty_coef
*/
double change_coordinate(double w, double c1, double c2, double* glob_min_coord);
double change_coordinate(double w, double c1, double c2, double* glob_min_coord, double penalty_coef=0.25);
};
......@@ -96,12 +102,29 @@ private:
double *domain_bounds;
protected:
/**
*
* @param coord
* @param val
* @return
*/
Particle* determine_optimal_coordinate_and_value(double *coord, double &val);
/**
*
* @return
*/
double* get_centroid_coordinates();
/**
*
* @param a
* @param b
* @param n
* @return
*/
void determine_optimal_coordinate_and_value(double *coord, double &val);
double get_euclidean_distance(double* a, double* b, int n);
public:
......@@ -122,9 +145,11 @@ public:
/**
*
* @param gamma
* @param epsilon
* @param delta
*/
void optimize( double epsilon );
void optimize( double gamma, double epsilon, double delta=0.7 );
};
......
......@@ -169,7 +169,7 @@ void NeuralNetwork::eval_single(std::vector<double> &input, std::vector<double>
neuron->set_potential(input[i]);
printf("INPUT NEURON %2d, POTENTIAL: %f\n", i, input[i]);
//printf("INPUT NEURON %2d, POTENTIAL: %f\n", i, input[i]);
++i;
}
......@@ -207,7 +207,7 @@ void NeuralNetwork::eval_single(std::vector<double> &input, std::vector<double>
output[i] = neuron->get_state();
printf("OUTPUT NEURON %2d, VALUE: %f\n", i, output[i]);
//printf("OUTPUT NEURON %2d, VALUE: %f\n", i, output[i]);
++i;
}
......
......@@ -90,6 +90,7 @@ void test2() {
<< n2.get_state() << " "
<< n2.activation_function_get_parameter(0) << " "
<< n2.activation_function_get_parameter(1) << std::endl;
}
double particle_swarm_test_function(double *x){
// return x[0] * x[1] - x[0] * x[0] + x[1] * x[2];
......@@ -99,6 +100,7 @@ double particle_swarm_test_function(double *x){
NeuralNetwork net;
std::vector<std::vector<double>*> *train_data_input;
std::vector<std::vector<double>*> *train_data_output;
double test_particle_swarm_neural_net_error_function(double *weights){
net.copy_weights(weights);
......@@ -120,12 +122,13 @@ double test_particle_swarm_neural_net_error_function(double *weights){
}
/*
printf("INPUT: ");
for(unsigned int i = 0; i < dim_in; ++i){
printf("%f ", weights[i]);
}
printf(", ERROR: %f\n", 0.5 * error);
*/
return 0.5 * error;
}
......@@ -178,20 +181,18 @@ void test_particle_swarm_neural_net(){
double (*F)(double*) = &test_particle_swarm_neural_net_error_function;
unsigned int n_edges = 2;
unsigned int dim = n_edges, max_iters = 2;
unsigned int dim = n_edges, max_iters = 2000;
double domain_bounds [4] = {-800.0, 800.0, -800.0, 800.0};
double c1 = 0.5, c2 = 1.5, w = 1.0;
unsigned int n_particles = 2;
double c1 = 0.5, c2 = 1.5, w = 0.8;
double accuracy = 1e-6;
unsigned int n_particles = 10;
ParticleSwarm swarm_01(F, dim, domain_bounds, c1, c2, w, n_particles, max_iters);
swarm_01.optimize(accuracy);
swarm_01.optimize(0.5, 0.02);
/* CLEANUP PHASE */
for( std::vector<double> *input: *train_data_input){
......@@ -222,7 +223,7 @@ void test_particle_swarm(){
ParticleSwarm swarm_01(F, dim, domain_bounds, c1, c2, w, n_particles, max_iters);
swarm_01.optimize(accuracy);
swarm_01.optimize(0.5, accuracy);
}
int main(int argc, char** argv){
......
Markdown is supported
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