NeuralNetworkGenetic/main.cpp

392 lines
9.5 KiB
C++
Raw Normal View History

2019-12-13 16:15:44 +03:00
#include <iostream>
#include <time.h>
2019-12-15 16:23:00 +03:00
#define InitialSynapseValue 1.0
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
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 16:23:00 +03:00
this -> value = this -> weight = this -> bias = InitialSynapseValue;
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;
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;
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 16:23:00 +03:00
for (int i = 0; i < forwardsSize; i++)
(forwards + i) -> SetValue(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 16:23:00 +03:00
if(!incomings) return result;
2019-12-15 15:57:34 +03:00
for (int i = 0; i < incomingsSize; i++)
result += (incomings + i) -> Fire();
2019-12-15 16:23:00 +03:00
if(!forwards) return result;
2019-12-15 15:57:34 +03:00
for (int i = 0; i < forwardsSize; i++)
(forwards + i * layerSize) -> SetValue(result);
2019-12-13 16:15:44 +03:00
2019-12-15 15:57:34 +03:00
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;
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
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();
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 16:23:00 +03:00
synapseSize = synapseCount;
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);
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;
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);
2019-12-15 16:23:00 +03:00
#pragma region Initialization
network.SetInputNeurons(1);
network.SetHiddenNeurons(0, 2);
network.SetHiddenNeurons(1, 3);
network.SetHiddenNeurons(2, 2);
network.SetOutputNeurons(1);
network.ConnectLayers();
#pragma endregion
#pragma region Fixed Bias&Weight
network.SetInput(0, 1);
network.FireNetwork();
std::cout << "Result = " << network.GetOutput(0) << "\n";
network.SetInput(0, 2);
network.FireNetwork();
std::cout << "Result = " << network.GetOutput(0) << "\n";
2019-12-13 16:15:44 +03:00
2019-12-15 16:23:00 +03:00
network.SetInput(0, 3);
network.FireNetwork();
std::cout << "Result = " << network.GetOutput(0) << "\n";
#pragma endregion
2019-12-13 16:15:44 +03:00
return 0;
}