Commit 0802a4da authored by Michal Kravcenko's avatar Michal Kravcenko

Changed the structure and Connections, Neurons and Neural networks to be more...

Changed the structure and Connections, Neurons and Neural networks to be more clean and better suited for solving differential equations

Adjusted the class DESolver to account for the changes
parents 32b7bce3 8770eecd
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -69,7 +69,7 @@ case `uname -s` in
esac
#-------------------------------------------------------------------------
rm -rf build;
rm -rf build CMakeCache.txt;
cmake -G "${MAKEFILE_TYPE}" -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DWITH_TIME_PROFILING:BOOLEAN=${WITH_TIME_PROFILING} .
make VERBOSE=1 && echo "Build complete." || exit -1;
#make install;
# Install script for directory: /home/fluffymoo/4NEURO_BIATCH/4Neuro
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "/usr/local")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "Debug")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Install shared libraries without execute permission?
if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
set(CMAKE_INSTALL_SO_NO_EXE "1")
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()
if(NOT CMAKE_INSTALL_LOCAL_ONLY)
# Include the install script for each subdirectory.
include("/home/fluffymoo/4NEURO_BIATCH/4Neuro/build/cmake_install.cmake")
endif()
if(CMAKE_INSTALL_COMPONENT)
set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
else()
set(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
endif()
string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT
"${CMAKE_INSTALL_MANIFEST_FILES}")
file(WRITE "/home/fluffymoo/4NEURO_BIATCH/4Neuro/${CMAKE_INSTALL_MANIFEST}"
"${CMAKE_INSTALL_MANIFEST_CONTENT}")
......@@ -30,6 +30,16 @@ DataSet::DataSet(std::vector<std::pair<std::vector<double>, std::vector<double>>
//TODO check the complete data set for input/output dimensions
}
DataSet::DataSet(double lower_bound, double upper_bound, unsigned int size, double output) {
std::vector<std::pair<std::vector<double>, std::vector<double>>> new_data_vec;
this->data = new_data_vec;
this->n_elements = size;
this->input_dim = 1;
this->output_dim = 1;
this->add_isotropic_data(lower_bound, upper_bound, size, output);
}
void DataSet::add_data_pair(std::vector<double> inputs, std::vector<double> outputs) {
if(inputs.size() != this->input_dim) {
throw InvalidDimension("Bad input dimension.");
......@@ -41,6 +51,23 @@ void DataSet::add_data_pair(std::vector<double> inputs, std::vector<double> outp
this->data.emplace_back(std::make_pair(inputs, outputs));
}
void DataSet::add_isotropic_data(double lower_bound, double upper_bound, unsigned int size, double output) {
if(this->input_dim != 1 || this->output_dim != 1) {
throw InvalidDimension("Cannot add data with dimensionality 1:1 when the data set "
"is of different dimensionality!");
}
double frac = (upper_bound - lower_bound) / (size - 1);
std::vector<double> inp, out;
out = {output};
for(unsigned int i = 0; i < size; ++i){
inp = {frac*i};
this->data.emplace_back(std::make_pair(inp, out));
}
}
std::vector<std::pair<std::vector<double>, std::vector<double>>>* DataSet::get_data() {
return &(this->data);
}
......
......@@ -149,6 +149,22 @@ public:
*/
DataSet(std::vector<std::pair<std::vector<double>, std::vector<double>>>* data_ptr);
/**
* Creates a new data set with input values equidistantly positioned
* over the certain interval and the output value
* being constant
*
* Both input and output are 1-dimensional
*
* @todo add bounds as vectors for multi-dimensional data-sets
*
* @param lower_bound Lower bound of the input data interval
* @param upper_bound Upper bound of the input data interval
* @param size Number of input-output pairs generated
* @param output Constant output value
*/
DataSet(double lower_bound, double upper_bound, unsigned int size, double output);
/**
* Getter for number of elements
* @return Number of elements in the data set
......@@ -181,6 +197,23 @@ public:
*/
void add_data_pair(std::vector<double> inputs, std::vector<double> outputs);
//TODO expand method to generate multiple data types - chebyshev etc.
/**
* Adds a new data with input values equidistantly positioned
* over the certain interval and the output value
* being constant
*
* Both input and output are 1-dimensional
*
* @param lower_bound Lower bound of the input data interval
* @param upper_bound Upper bound of the input data interval
* @param size Number of input-output pairs generated
* @param output Constant output value
*/
void add_isotropic_data(double lower_bound, double upper_bound, unsigned int size, double output);
//TODO Chebyshev - ch. interpolation points, i-th point = cos(i*alpha) from 0 to pi
/**
* Prints the data set
*/
......
......@@ -5,9 +5,6 @@
* @date 2.7.18 -
*/
#include <cmath>
#include <set>
#include <stdexcept>
#include "ParticleSwarm.h"
#include "../ErrorFunction/ErrorFunctions.h"
......@@ -35,6 +32,7 @@ Particle::Particle(ErrorFunction* ef, double *domain_bounds) {
// this->r2 = (rand() % 100001) / (double) 100000;
this->r1 = 1.0;
this->r2 = 1.0;
this->r3 = 1.0;
this->optimal_coordinate = new double[this->coordinate_dim];
......@@ -72,20 +70,24 @@ double* Particle::get_coordinate() {
return this->coordinate;
}
double Particle::get_current_value() {
return this->current_val;
}
double Particle::get_optimal_value() {
return this->optimal_value;
}
void Particle::get_optimal_coordinate(double *ref_coordinate) {
void Particle::get_optimal_coordinate(std::vector<double> &ref_coordinate) {
for( unsigned int i = 0; i < this->coordinate_dim; ++i ){
ref_coordinate[i] = this->optimal_coordinate[i];
}
}
double Particle::change_coordinate(double w, double c1, double c2, double *glob_min_coord, double penalty_coef) {
double Particle::change_coordinate(double w, double c1, double c2, std::vector<double> glob_min_coord, std::vector<std::vector<double>> global_min_vec, double penalty_coef) {
/**
* v = w * v + c1r1(p_min_loc - x) + c2r2(p_min_glob - x)
* v = w * v + c1r1(p_min_loc - x) + c2r2(p_min_glob - x) + c3r3(random_global_min - x)
* x = x + v
*/
......@@ -93,8 +95,22 @@ double Particle::change_coordinate(double w, double c1, double c2, double *glob_
double output;
bool in_domain;
double compensation_coef = 1;
/* Choose random global minima */
std::vector<double> random_global_best(this->coordinate_dim);
std::random_device rand_dev;
std::mt19937 engine{rand_dev()};
std::uniform_int_distribution<int> dist(0, global_min_vec.size() - 1);
random_global_best = global_min_vec[dist(engine)];
// TODO use std::sample to choose random vector
//std::sample(global_min_vec.begin(), global_min_vec.end(), std::back_inserter(random_global_best), 1, std::mt19937{std::random_device{}()});
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]);
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])
+ (c1+c2)/2 * this->r3 * (random_global_best[i] - this->coordinate[i]);
do{
if (this->coordinate[i] + vel_mem > this->domain_bounds[2 * i + 1]) {
......@@ -118,6 +134,7 @@ double Particle::change_coordinate(double w, double c1, double c2, double *glob_
}
vel_mem = this->ef->eval(this->coordinate);
this->current_val = vel_mem;
if(vel_mem < this->optimal_value){
this->optimal_value = vel_mem;
......@@ -149,6 +166,8 @@ ParticleSwarm::ParticleSwarm(ErrorFunction* ef, double *domain_bounds,
this->c2 = c2;
this->c3 = (c1 + c2)/2.0;
this->w = w;
this->n_particles = n_particles;
......@@ -191,7 +210,8 @@ void ParticleSwarm::optimize( double gamma, double epsilon, double delta) {
unsigned int outer_it = 0;
Particle *particle;
double *p_min_glob = new double[this->func_dim];
std::vector<double> p_min_glob(this->func_dim);
std::vector<std::vector<double>> global_best_vec;
double optimal_value = 0.0;
std::set<Particle*> cluster; //!< Particles in a cluster
......@@ -213,9 +233,16 @@ void ParticleSwarm::optimize( double gamma, double epsilon, double delta) {
// Clustering algorithm - termination condition //
//////////////////////////////////////////////////
particle = this->determine_optimal_coordinate_and_value(p_min_glob, optimal_value);
if(std::find(global_best_vec.begin(), global_best_vec.end(), p_min_glob) == global_best_vec.end()) {
global_best_vec.emplace_back(p_min_glob); // TODO rewrite as std::set
}
cluster.insert(particle);
for(unsigned int i=0; i < 5; i++) {
//for(unsigned int i=0; i < 5; i++) {
/* Zero AVG coordinates */
std::fill(coords, coords+this->func_dim, 0);
/* Looking for a centroid */
for (auto it : cluster) {
......@@ -231,7 +258,7 @@ void ParticleSwarm::optimize( double gamma, double epsilon, double delta) {
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);
tmp_velocity = particle->change_coordinate( this->w, this->c1, this->c2, p_min_glob, global_best_vec);
if(tmp_velocity > max_velocity) {
prev_max_velocity = max_velocity;
......@@ -249,20 +276,28 @@ void ParticleSwarm::optimize( double gamma, double epsilon, double delta) {
cluster.insert(particle);
}
}
}
//}
prev_max_vel_step = max_vel_step;
max_vel_step = max_velocity - prev_max_velocity;
//TODO only in verbose mode
euclidean_dist /= this->n_particles;
//printf("Iteration %d, avg euclidean distance: %f, cluster percent: %f, f-value: %f\n", outer_it, euclidean_dist,
// double(cluster.size())/this->n_particles, optimal_value);
// for(unsigned int i=0; i < this->n_particles; i++) {
// printf("Particle %d (%f): \n", i, this->particle_swarm[i]->get_current_value());
// for(unsigned int j=0; j < this->func_dim; j++) {
// printf("\t%f\n", this->particle_swarm[i]->get_coordinate()[j]);
// }
// }
/* Check if the particles are near to each other AND the maximal velocity is less than 'gamma' */
if(double(cluster.size())/this->n_particles > delta && std::abs(prev_max_vel_step/max_vel_step) > gamma) {
break;
}
//TODO only in verbose mode
euclidean_dist /= this->n_particles*5.;
printf("Iteration %d, avg euclidean distance: %f\n", outer_it, euclidean_dist);
outer_it++;
// this->w *= 0.99;
}
......@@ -283,11 +318,11 @@ void ParticleSwarm::optimize( double gamma, double epsilon, double delta) {
}
}
delete [] p_min_glob;
//delete [] p_min_glob; // TODO
delete [] coords;
}
Particle* ParticleSwarm::determine_optimal_coordinate_and_value(double *coord, double &val) {
Particle* ParticleSwarm::determine_optimal_coordinate_and_value(std::vector<double> &coord, double &val) {
Particle* p;
......
......@@ -8,8 +8,14 @@
#ifndef INC_4NEURO_PARTICLESWARM_H
#define INC_4NEURO_PARTICLESWARM_H
#include "stdlib.h"
#include "time.h"
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <set>
#include <stdexcept>
#include <random>
#include <iterator>
#include <algorithm>
#include "../Network/NeuralNetwork.h"
#include "../DataSet/DataSet.h"
......@@ -28,6 +34,9 @@ private:
double r1;
double r2;
double r3;
double current_val;
ErrorFunction* ef;
......@@ -50,6 +59,12 @@ public:
*/
double* get_coordinate();
/**
*
* @return
*/
double get_current_value();
/**
*
* @return
......@@ -60,7 +75,7 @@ public:
*
* @param ref_coordinate
*/
void get_optimal_coordinate(double *ref_coordinate);
void get_optimal_coordinate(std::vector<double> &ref_coordinate);
/**
*
......@@ -70,7 +85,7 @@ public:
* @param glob_min_coord
* @param penalty_coef
*/
double change_coordinate(double w, double c1, double c2, double* glob_min_coord, double penalty_coef=0.25);
double change_coordinate(double w, double c1, double c2, std::vector<double> glob_min_coord, std::vector<std::vector<double>> global_min_vec, double penalty_coef=0.25);
};
......@@ -98,6 +113,8 @@ private:
double c2;
double c3;
double w;
double global_optimal_value;
......@@ -111,7 +128,7 @@ protected:
* @param val
* @return
*/
Particle* determine_optimal_coordinate_and_value(double *coord, double &val);
Particle* determine_optimal_coordinate_and_value(std::vector<double> &coord, double &val);
/**
*
......
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 13.6.18 -
*/
#include "Connection.h"
Connection* Connection::get_copy(Neuron *n_in, Neuron *n_out){
Connection *output = new Connection(n_in, n_out, this->con, false);
return output;
}
Connection::Connection(Neuron *n_in, Neuron *n_out, ConnectionWeight* con, bool del_weight) {
this->neuron_in = n_in;
this->neuron_out = n_out;
this->con = con;
this->delete_connection = del_weight;
}
Connection::~Connection() {
if(this->con && this->delete_connection ){
delete this->con;
this->con = nullptr;
}
}
void Connection::adjust_weights(double* values) {
this->con->adjust_weights(values);
}
Neuron* Connection::get_neuron_in() {
return this->neuron_in;
}
Neuron* Connection::get_neuron_out() {
return this->neuron_out;
}
//double Connection::get_weight() {
// return this->weight;
//}
void Connection::pass_signal() {
#ifdef VERBOSE_NN_EVAL
printf(" passing signal between neurons %d -> %d, value: %f * %f\n", this->neuron_in, this->neuron_out, this->neuron_in->get_state(), this->con->eval());
#endif
this->neuron_out->adjust_potential(this->neuron_in->get_state() * this->con->eval());
}
void Connection::set_weights(double *values) {
this->con->set_weights(values);
}
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 13.6.18 -
*/
#ifndef INC_4NEURO_CONNECTION_H
#define INC_4NEURO_CONNECTION_H
#include "../Neuron/Neuron.h"
#include "ConnectionWeight.h"
#include "../settings.h"
class Neuron;
class ConnectionWeight;
/**
* Class representing directed connection between two neurons
*/
class Connection {
private:
/**
* Pointer to an object evaluating the weight function
*/
ConnectionWeight *con = nullptr;
/**
* Pointer to the Neuron on the receiving end of this connection
*/
Neuron *neuron_in = nullptr;
/**
* Pointer to the Neuron on the signaling end of this connection
*/
Neuron *neuron_out = nullptr;
/**
*
*/
bool delete_connection = true;
//TODO pridat gradient pro ucely backpropagation
public:
/**
* Returns a new object reprresenting an edge using the same weight function as this one
* @param n_in
* @param n_out
* @return
*/
virtual Connection* get_copy(Neuron *n_in, Neuron *n_out) final;
/**
*
* @param n_in
* @param n_out
* @param con
* @param delete_weight
*/
Connection(Neuron *n_in, Neuron *n_out, ConnectionWeight* con, bool delete_weight = true);
/**
* Destructor, deletes the 'con' object
*/
~Connection();
/**
* Takes the array of double values and alters the corresponding weights associated
* with the 'con' object
* @param[in] values Values to be added to the associated weights
*/
void adjust_weights(double *values);
/**
* Takes the array of double values and sets the corresponding weights associated
* with the 'con' object
* @param[in] values Values to be set to the associated weights
*/
void set_weights(double *values);
/**
* Takes the output signal of Neuron 'neuron_out', multiplies it by the result of the
* weight function associated with this connection and adds the result to the potential
* of the Neuron 'neuron_in'
*/
void pass_signal();
/**
* Returns the pointer to the Neuron on the receiving end of this connection
* @return
*/
Neuron* get_neuron_in();
/**
* Returns the pointer to the Neuron on the signaling end of this connection
* @return
*/
Neuron* get_neuron_out();
};
#endif //INC_4NEURO_CONNECTION_H
......@@ -7,16 +7,10 @@
#include "ConnectionWeightIdentity.h"
ConnectionWeightIdentity::ConnectionWeightIdentity(std::vector<double>* w_array) {
this->n_params = 1;
this->weight_array = w_array;
this->param_indices = new int[1];
ConnectionWeightIdentity::ConnectionWeightIdentity(double * val) {
this->value = val;
}
double ConnectionWeightIdentity::eval() {
double a = this->weight_array->at(this->param_indices[0]);
return a;
return (*this->value);
}
\ No newline at end of file
......@@ -8,21 +8,22 @@
#ifndef INC_4NEURO_CONNECTIONWEIGHTIDENTITY_H
#define INC_4NEURO_CONNECTIONWEIGHTIDENTITY_H
#include "ConnectionWeight.h"
#include "ConnectionFunctionGeneral.h"
class ConnectionWeight;
class ConnectionFunctionGeneral;
/**
*
*/
class ConnectionWeightIdentity:public ConnectionWeight {
class ConnectionWeightIdentity:public ConnectionFunctionGeneral {
private:
double * value = nullptr;
public:
/**
*
*/
ConnectionWeightIdentity(std::vector<double>* w_array);
ConnectionWeightIdentity(double * value_ptr);
/**
*
......
......@@ -2,7 +2,7 @@
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 13.6.18 -
* @date 8.8.18 -
*/
#include "NeuronNeuralNet.h"
#include "NeuronConstant.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 8.8.18 -
*/
#ifndef INC_4NEURO_NEURONCONSTANT_H
#define INC_4NEURO_NEURONCONSTANT_H
class NeuronConstant {
};
#endif //INC_4NEURO_NEURONCONSTANT_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 13.6.18 -
*/
#ifndef INC_4NEURO_NEURONNEURALNET_H
#define INC_4NEURO_NEURONNEURALNET_H
#include "Neuron.h"
class NeuronNeuralNet:public Neuron {
};
#endif //INC_4NEURO_NEURONNEURALNET_H
//
// Created by fluffymoo on 11.6.18.
//
#include "NeuronTanh.h"
Neuron* NeuronTanh::get_copy( ){
NeuronTanh* output = new NeuronTanh( this->activation_function_parameters[0]);
return output;
}
NeuronTanh::NeuronTanh(double a) {
this->n_activation_function_parameters = 1;
this->activation_function_parameters = new double[1];
this->activation_function_parameters[0] = a;
this->edges_in = new std::vector<Connection*>(0);
this->edges_out = new std::vector<Connection*>(0);
}
void NeuronTanh::activate( ) {
double a = this->activation_function_parameters[0];
double x = this->potential;
double ex = std::pow(E, x - a);
double exi = 1.0 / ex;
this->state = (ex - exi) / (ex + exi);
}
double NeuronTanh::activation_function_eval_partial_derivative(int param_idx) {
double a = this->activation_function_parameters[0];
double x = this->potential;
if(param_idx == 0){
/**
* TODO
* Same as activation_function_get_derivative()
*/
double ex = -4.0 * std::pow(E, 2.0 * (x + a));
double exi = std::pow(E, 2.0 * a) + std::pow(E, 2.0 * x);
return ex / (exi * exi);
}
return 0.0;
}
double NeuronTanh::activation_function_eval_derivative( ) {
double a = this->activation_function_parameters[0];
double x = this->potential;
double ex = -4.0 * std::pow(E, 2.0 * (x + a));
double exi = std::pow(E, 2.0 * a) + std::pow(E, 2.0 * x);
return ex / (exi * exi);
}
Neuron* NeuronTanh::get_derivative() {
return nullptr;
}
\ No newline at end of file