2019-12-13 16:15:44 +03:00
|
|
|
#include <iostream>
|
|
|
|
#include <time.h>
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
class Synapse;
|
|
|
|
class Neuron;
|
|
|
|
class Layer;
|
|
|
|
class Input;
|
|
|
|
class Output;
|
|
|
|
class NeuralNetwork;
|
2019-12-13 16:15:44 +03:00
|
|
|
|
|
|
|
float RandomFloat(int min, int max)
|
|
|
|
{
|
2019-12-13 18:51:11 +03:00
|
|
|
float result;
|
|
|
|
int value;
|
2019-12-13 16:15:44 +03:00
|
|
|
static unsigned long int counter = 0;
|
|
|
|
srand(time(0) + counter++ * 50);
|
2019-12-13 18:51:11 +03:00
|
|
|
value = (rand() % ((max - min) * 100));
|
|
|
|
result = (float)value / 100.0 + (float)min;
|
2019-12-15 15:57:34 +03:00
|
|
|
return result;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
#pragma region Synapse
|
|
|
|
class Synapse
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
|
|
|
private:
|
2019-12-15 15:57:34 +03:00
|
|
|
float weight;
|
|
|
|
float value;
|
|
|
|
float bias;
|
2019-12-13 16:15:44 +03:00
|
|
|
public:
|
2019-12-15 15:57:34 +03:00
|
|
|
Synapse();
|
2019-12-13 16:15:44 +03:00
|
|
|
void SetValue(float);
|
2019-12-15 15:57:34 +03:00
|
|
|
void SetWeight(float);
|
2019-12-13 16:15:44 +03:00
|
|
|
void SetBias(float);
|
|
|
|
float Fire();
|
|
|
|
};
|
2019-12-13 20:04:33 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
Synapse::Synapse()
|
2019-12-13 18:51:11 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
this -> value = this -> weight = this -> bias = 1.0;
|
2019-12-13 18:51:11 +03:00
|
|
|
}
|
2019-12-15 15:57:34 +03:00
|
|
|
|
|
|
|
void Synapse::SetValue(float value)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
|
|
|
this -> value = value;
|
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
void Synapse::SetWeight(float weight)
|
|
|
|
{
|
2019-12-13 18:51:11 +03:00
|
|
|
this -> weight = weight;
|
2019-12-15 15:57:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Synapse::SetBias(float bias)
|
|
|
|
{
|
2019-12-13 18:51:11 +03:00
|
|
|
this -> bias = bias;
|
2019-12-15 15:57:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
float Synapse::Fire()
|
|
|
|
{
|
|
|
|
float result = 0.0;
|
|
|
|
|
|
|
|
result = this -> value * this -> weight + this -> bias;
|
|
|
|
|
2019-12-13 18:51:11 +03:00
|
|
|
return result;
|
|
|
|
}
|
2019-12-13 16:15:44 +03:00
|
|
|
#pragma endregion
|
2019-12-15 15:57:34 +03:00
|
|
|
#pragma region Neuron
|
|
|
|
class Neuron
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
|
|
|
private:
|
2019-12-15 15:57:34 +03:00
|
|
|
Synapse *incomings;
|
|
|
|
Synapse *forwards;
|
|
|
|
int incomingsSize;
|
|
|
|
int forwardsSize;
|
|
|
|
int layerSize;
|
|
|
|
float value;
|
2019-12-13 16:15:44 +03:00
|
|
|
public:
|
2019-12-15 15:57:34 +03:00
|
|
|
Neuron();
|
|
|
|
void ConnectIncomings(Synapse *, int);
|
|
|
|
void ConnectForwards(Synapse *, int, int);
|
|
|
|
void SetValue(float);
|
|
|
|
float GetValue();
|
2019-12-13 16:15:44 +03:00
|
|
|
};
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
Neuron::Neuron()
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
incomings = forwards = NULL;
|
|
|
|
incomingsSize = forwardsSize = layerSize = 0;
|
|
|
|
value = 0.0;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
void Neuron::SetValue(float value)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
this -> value = value;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
void Neuron::ConnectIncomings(Synapse *incomings, int incomingsSize)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
this -> incomings = incomings;
|
|
|
|
this -> incomingsSize = incomingsSize;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
2019-12-15 15:57:34 +03:00
|
|
|
|
|
|
|
void Neuron::ConnectForwards(Synapse *forwards, int forwardsSize, int layerSize)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
this -> forwards = forwards;
|
|
|
|
this -> forwardsSize = forwardsSize;
|
|
|
|
this -> layerSize = layerSize;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
float Neuron::GetValue()
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
float result = 0.0;
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
if(!incomings) return (value = result);
|
|
|
|
|
|
|
|
for (int i = 0; i < incomingsSize; i++)
|
|
|
|
result += (incomings + i) -> Fire();
|
|
|
|
|
|
|
|
|
|
|
|
if(!forwards) return (value = result);
|
|
|
|
|
|
|
|
for (int i = 0; i < forwardsSize; i++)
|
|
|
|
// currentSynapse = (forwards -> synapses + (forwardNeuron * this -> neuronSize));
|
|
|
|
// (forwards + i) -> SetValue(result);
|
|
|
|
//BAK BURAYA
|
|
|
|
(forwards + i * layerSize) -> SetValue(result);
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
value = result;
|
|
|
|
return result;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
#pragma endregion
|
2019-12-15 15:57:34 +03:00
|
|
|
#pragma region Layer
|
|
|
|
class Layer
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
|
|
|
protected:
|
2019-12-15 15:57:34 +03:00
|
|
|
Neuron *neurons;
|
|
|
|
Synapse *synapses;
|
|
|
|
int neuronSize;
|
|
|
|
int synapseSize;
|
|
|
|
Neuron *_CreateNeurons(int);
|
2019-12-13 16:15:44 +03:00
|
|
|
public:
|
2019-12-15 15:57:34 +03:00
|
|
|
Layer();
|
|
|
|
Layer(int);
|
|
|
|
~Layer();
|
2019-12-13 16:15:44 +03:00
|
|
|
void FireLayer();
|
2019-12-15 15:57:34 +03:00
|
|
|
bool CreateNeurons(int);
|
|
|
|
bool ConnectPrevious(Layer *);
|
|
|
|
bool ConnectForwards(Layer *);
|
2019-12-13 16:15:44 +03:00
|
|
|
int GetSize();
|
|
|
|
};
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
Layer::Layer()
|
2019-12-13 18:51:11 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
neuronSize = synapseSize = 0;
|
|
|
|
neurons = NULL;
|
|
|
|
synapses = NULL;
|
2019-12-13 18:51:11 +03:00
|
|
|
}
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
Layer::Layer(int size)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
neuronSize = synapseSize = 0;
|
|
|
|
synapses = NULL;
|
|
|
|
neurons = _CreateNeurons(size);
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
2019-12-15 15:57:34 +03:00
|
|
|
|
|
|
|
Layer::~Layer()
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
if(neurons) delete neurons;
|
|
|
|
if(synapses) delete synapses;
|
|
|
|
}
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
Neuron *Layer::_CreateNeurons(int size)
|
|
|
|
{
|
|
|
|
Neuron *newNeurons = NULL;
|
|
|
|
newNeurons = (Neuron *) new char[sizeof(Neuron) * size];
|
|
|
|
|
|
|
|
if(newNeurons)
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
*(newNeurons + i) = Neuron();
|
2019-12-13 18:51:11 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
return newNeurons;
|
|
|
|
}
|
2019-12-13 18:51:11 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
void Layer::FireLayer()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < neuronSize; i++)
|
|
|
|
(neurons + i) -> GetValue();
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
bool Layer::CreateNeurons(int size)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
if(neurons = _CreateNeurons(size))
|
|
|
|
neuronSize = size;
|
|
|
|
return neurons;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
bool Layer::ConnectPrevious(Layer *previous)
|
|
|
|
{
|
|
|
|
int previousSize = previous -> GetSize();
|
|
|
|
int synapseCount = (this -> neuronSize) * previousSize;
|
|
|
|
int currentIndex = 0;
|
|
|
|
Synapse *currentSynapse = NULL;
|
|
|
|
Neuron *currentNeuron = NULL;
|
|
|
|
// Synapse *connectSynapses = NULL;
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
if(synapses) delete synapses;
|
|
|
|
synapses = (Synapse *) new char[sizeof(Synapse) * synapseCount];
|
|
|
|
if(!synapses) return false;
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
// connectSynapses = (Synapse *) new char[sizeof(Synapse) * previousSize];
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
for (int thisNeuron = 0; thisNeuron < this -> neuronSize; thisNeuron++)
|
2019-12-13 18:51:11 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
for (int prevNeuron = 0; prevNeuron < previousSize; prevNeuron++)
|
2019-12-13 18:51:11 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
currentIndex = thisNeuron * previousSize + prevNeuron;
|
|
|
|
currentSynapse = (synapses + currentIndex);
|
|
|
|
currentNeuron = (previous -> neurons) + prevNeuron;
|
|
|
|
|
|
|
|
*currentSynapse = Synapse();
|
|
|
|
// currentSynapse = (Synapse *) new char[sizeof(Synapse)];
|
|
|
|
// currentSynapse -> SetWeight(1);
|
|
|
|
// currentSynapse -> SetValue(2);
|
|
|
|
// currentSynapse -> SetBias(3);
|
|
|
|
// currentSynapse -> SetRoot(currentNeuron);
|
2019-12-13 18:51:11 +03:00
|
|
|
}
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
currentNeuron = (neurons + thisNeuron);
|
|
|
|
currentNeuron -> ConnectIncomings((synapses + thisNeuron * previousSize), previousSize);
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
return previous -> ConnectForwards(this);
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
bool Layer::ConnectForwards(Layer *forwards)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
int forwardsSize = forwards -> neuronSize;
|
|
|
|
Neuron *currentNeuron = NULL;
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
for (int thisNeuron = 0; thisNeuron < this -> neuronSize; thisNeuron++)
|
2019-12-13 18:51:11 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
currentNeuron = (neurons + thisNeuron);
|
|
|
|
for (int forwardNeuron = 0; forwardNeuron < forwardsSize; forwardNeuron++)
|
|
|
|
currentNeuron -> ConnectForwards(forwards -> synapses + thisNeuron, forwardsSize, this -> neuronSize);
|
|
|
|
// currentSynapse = (forwards -> synapses + (thisNeuron + forwardNeuron * this -> neuronSize));
|
2019-12-13 18:51:11 +03:00
|
|
|
}
|
2019-12-13 16:15:44 +03:00
|
|
|
return true;
|
|
|
|
}
|
2019-12-13 18:51:11 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
int Layer::GetSize()
|
|
|
|
{
|
|
|
|
return neuronSize;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
2019-12-15 15:57:34 +03:00
|
|
|
#pragma region Input-Output
|
|
|
|
class Input : public Layer
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
|
|
|
public:
|
2019-12-15 15:57:34 +03:00
|
|
|
Input();
|
2019-12-13 16:15:44 +03:00
|
|
|
void SetValue(int, float);
|
|
|
|
};
|
2019-12-15 15:57:34 +03:00
|
|
|
|
|
|
|
Input::Input() : Layer() {}
|
|
|
|
void Input::SetValue(int index, float value)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
if(index >= this -> neuronSize || index < 0)
|
|
|
|
return;
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
(neurons + index) -> SetValue(value);
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
2019-12-15 15:57:34 +03:00
|
|
|
|
|
|
|
class Output : public Layer
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
|
|
|
public:
|
2019-12-15 15:57:34 +03:00
|
|
|
Output();
|
2019-12-13 16:15:44 +03:00
|
|
|
float GetValue(int);
|
|
|
|
};
|
2019-12-15 15:57:34 +03:00
|
|
|
|
|
|
|
Output::Output() : Layer() {}
|
|
|
|
float Output::GetValue(int index)
|
|
|
|
{
|
|
|
|
float result = 0.0;
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
if(index >= this -> neuronSize || index < 0)
|
|
|
|
return result;
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
result = (neurons + index) -> GetValue();
|
2019-12-13 18:51:11 +03:00
|
|
|
return result;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
#pragma endregion
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region NeuralNetwork
|
|
|
|
class NeuralNetwork
|
|
|
|
{
|
|
|
|
private:
|
2019-12-15 15:57:34 +03:00
|
|
|
Input *input;
|
|
|
|
Layer *hidden;
|
|
|
|
Output *output;
|
2019-12-13 16:15:44 +03:00
|
|
|
int hiddenSize;
|
2019-12-15 15:57:34 +03:00
|
|
|
|
2019-12-13 16:15:44 +03:00
|
|
|
public:
|
|
|
|
NeuralNetwork();
|
|
|
|
NeuralNetwork(int);
|
|
|
|
~NeuralNetwork();
|
|
|
|
void FireNetwork();
|
|
|
|
bool SetInputNeurons(int);
|
2019-12-15 15:57:34 +03:00
|
|
|
bool SetHiddenNeurons(int, int);
|
2019-12-13 16:15:44 +03:00
|
|
|
bool SetOutputNeurons(int);
|
|
|
|
bool ConnectLayers();
|
2019-12-15 15:57:34 +03:00
|
|
|
float GetOutput(int);
|
|
|
|
void SetInput(int, float);
|
2019-12-13 16:15:44 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
NeuralNetwork::NeuralNetwork()
|
|
|
|
{
|
|
|
|
hiddenSize = 0;
|
|
|
|
input = NULL;
|
2019-12-15 15:57:34 +03:00
|
|
|
hidden = NULL;
|
2019-12-13 16:15:44 +03:00
|
|
|
output = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
NeuralNetwork::NeuralNetwork(int hiddenSize)
|
|
|
|
{
|
|
|
|
this -> hiddenSize = hiddenSize;
|
2019-12-15 15:57:34 +03:00
|
|
|
input = new Input();
|
|
|
|
hidden = new Layer(hiddenSize);
|
|
|
|
output = new Output();
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NeuralNetwork::~NeuralNetwork()
|
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
if(input) delete input;
|
|
|
|
if(hidden) delete hidden;
|
|
|
|
if(output) delete output;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
void NeuralNetwork::FireNetwork()
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
for (int i = 0; i < hiddenSize; i++)
|
|
|
|
(hidden + i) -> FireLayer();
|
|
|
|
|
|
|
|
output -> FireLayer();
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NeuralNetwork::SetInputNeurons(int size)
|
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
return input -> CreateNeurons(size);
|
|
|
|
}
|
2019-12-13 16:15:44 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
bool NeuralNetwork::SetHiddenNeurons(int index, int size)
|
|
|
|
{
|
|
|
|
return (hidden + index) -> CreateNeurons(size);
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NeuralNetwork::SetOutputNeurons(int size)
|
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
return output -> CreateNeurons(size);
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NeuralNetwork::ConnectLayers()
|
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
if(!hidden -> ConnectPrevious(input))
|
2019-12-13 16:15:44 +03:00
|
|
|
return false;
|
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
for (int i = 1; i < hiddenSize; i++)
|
|
|
|
if(!(hidden + i) -> ConnectPrevious((hidden + i - 1)))
|
2019-12-13 16:15:44 +03:00
|
|
|
return false;
|
2019-12-14 18:24:48 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
if(output -> ConnectPrevious((hidden + hiddenSize - 1)))
|
2019-12-13 16:15:44 +03:00
|
|
|
return false;
|
2019-12-13 18:51:11 +03:00
|
|
|
|
2019-12-15 15:57:34 +03:00
|
|
|
return true;
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
2019-12-15 15:57:34 +03:00
|
|
|
|
|
|
|
float NeuralNetwork::GetOutput(int index)
|
2019-12-13 16:15:44 +03:00
|
|
|
{
|
2019-12-15 15:57:34 +03:00
|
|
|
return output -> GetValue(index);
|
2019-12-13 16:15:44 +03:00
|
|
|
}
|
2019-12-15 15:57:34 +03:00
|
|
|
|
2019-12-13 16:15:44 +03:00
|
|
|
void NeuralNetwork::SetInput(int index, float value)
|
|
|
|
{
|
|
|
|
input -> SetValue(index, value);
|
|
|
|
}
|
2019-12-15 15:57:34 +03:00
|
|
|
#pragma endregion
|
2019-12-13 16:15:44 +03:00
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char const *argv[])
|
|
|
|
{
|
|
|
|
NeuralNetwork network(3);
|
|
|
|
|
|
|
|
network.SetInputNeurons(1);
|
2019-12-15 15:57:34 +03:00
|
|
|
network.SetHiddenNeurons(0, 2);
|
|
|
|
network.SetHiddenNeurons(1, 3);
|
|
|
|
network.SetHiddenNeurons(2, 2);
|
2019-12-13 16:15:44 +03:00
|
|
|
network.SetOutputNeurons(1);
|
|
|
|
|
|
|
|
network.ConnectLayers();
|
2019-12-15 15:57:34 +03:00
|
|
|
network.SetInput(0, 2);
|
2019-12-14 12:50:57 +03:00
|
|
|
network.FireNetwork();
|
2019-12-15 15:57:34 +03:00
|
|
|
std::cout << "Result = " << network.GetOutput(0) << "\n";
|
2019-12-13 16:15:44 +03:00
|
|
|
return 0;
|
|
|
|
}
|