summaryrefslogtreecommitdiff
path: root/2015-spacebot/src/brain/neural_network.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2015-spacebot/src/brain/neural_network.cpp')
-rw-r--r--2015-spacebot/src/brain/neural_network.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/2015-spacebot/src/brain/neural_network.cpp b/2015-spacebot/src/brain/neural_network.cpp
new file mode 100644
index 0000000..c8177e8
--- /dev/null
+++ b/2015-spacebot/src/brain/neural_network.cpp
@@ -0,0 +1,163 @@
+#include "brain/neural_network.h"
+#include "brain/neuron.h"
+#include <limits>
+
+NeuralNetwork::NeuralNetwork(std::istream &&networkConfigFile, unsigned int numberOfSensors, unsigned int numberOfOutputs)
+{
+ _neurons.reserve(400);
+ _sensors.reserve(numberOfSensors);
+ _outputs.reserve(numberOfOutputs);
+
+ _biasNode = std::make_shared<BiasNode>();
+
+ for (unsigned int i=0; i<numberOfSensors; ++i)
+ {
+ auto sensor = std::make_shared<Sensor>(i);
+ _sensors.push_back(sensor);
+ }
+ for (unsigned int i=0; i<numberOfOutputs; ++i)
+ {
+ auto output = findOrAddNeuron(i);
+ _outputs.push_back(output);
+ }
+
+ parseFile(std::move(networkConfigFile));
+}
+
+NeuralNetwork::NeuralNetwork(std::istream &&networkConfigFile, std::vector<bool> sensorInitialValues, unsigned int numberOfOutputs)
+{
+ _neurons.reserve(400);
+ _sensors.reserve(sensorInitialValues.size());
+ _outputs.reserve(numberOfOutputs);
+
+ _biasNode = std::make_shared<BiasNode>();
+
+ for (unsigned int i=0; i<sensorInitialValues.size(); ++i)
+ {
+ auto sensor = std::make_shared<Sensor>(i);
+ sensor->setActivation(sensorInitialValues[i] ? 1 : 0);
+ _sensors.push_back(sensor);
+ }
+ for (unsigned int i=0; i<numberOfOutputs; ++i)
+ {
+ auto output = findOrAddNeuron(i);
+ _outputs.push_back(output);
+ }
+
+ parseFile(std::move(networkConfigFile));
+}
+
+void NeuralNetwork::parseFile(std::istream &&file)
+{
+ double weight;
+ char srcType;
+ unsigned int srcId;
+ unsigned int destId;
+
+ while (file.get(srcType) &&
+ file >> srcId &&
+ file.ignore(std::numeric_limits<std::streamsize>::max(), 'n') &&
+ file >> destId &&
+ file >> weight &&
+ file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'))
+ {
+ std::shared_ptr<NeuralNode> source;
+ std::shared_ptr<Neuron> destination;
+ switch (srcType)
+ {
+ case 's':
+ source = findOrAddSensor(srcId);
+ break;
+ case 'b':
+ source = _biasNode;
+ break;
+ default:
+ source = findOrAddNeuron(srcId);
+ }
+ destination = findOrAddNeuron(destId);
+
+ addLink(source, destination, weight);
+ }
+
+}
+
+void NeuralNetwork::addLink(std::shared_ptr<NeuralNode> source, std::shared_ptr<Neuron> destination, double weight)
+{
+ NeuralLink link(source.get(), weight);
+ destination->addInput(std::move(link));
+}
+
+std::shared_ptr<Sensor> NeuralNetwork::findOrAddSensor(unsigned int id)
+{
+ while (_sensors.size() <= id)
+ {
+ auto sensor = std::make_shared<Sensor>(_sensors.size());
+ _sensors.push_back(sensor);
+ }
+
+ return _sensors.at(id);
+}
+
+std::shared_ptr<Neuron> NeuralNetwork::findOrAddNeuron(unsigned int id)
+{
+ while (_neurons.size() <= id)
+ {
+ auto neuron = std::make_shared<Neuron>(_neurons.size());
+ _neurons.push_back(neuron);
+ }
+
+ return _neurons.at(id);
+}
+
+void NeuralNetwork::setInput(unsigned int inputIndex, double activation)
+{
+ _sensors.at(inputIndex)->setActivation(activation);
+}
+
+unsigned int NeuralNetwork::findMaxOutputIndex() const
+{
+ bool anyNodeChanged = true;
+ auto maxIterations = _neurons.size()*10;
+ for (unsigned int iteration=0; anyNodeChanged && iteration<maxIterations; ++iteration)
+ {
+ anyNodeChanged = false;
+ for (auto const& neuron : _neurons)
+ {
+ bool activationChanged = neuron->calculateActivation();
+ anyNodeChanged = anyNodeChanged || activationChanged;
+ }
+ }
+
+ int currentMaxIndex = 0;
+ double currentMaxActivation = _outputs.at(0)->activation();
+
+ for (unsigned int i=1; i<_outputs.size(); ++i)
+ {
+ double activation = _outputs.at(i)->activation();
+ if (activation >= currentMaxActivation)
+ {
+ currentMaxActivation = activation;
+ currentMaxIndex = i;
+ }
+ }
+ return currentMaxIndex;
+}
+
+bool NeuralNetwork::linkExists(std::string srcIdentifier, std::string destIdentifier, double weight) const
+{
+ std::shared_ptr<Neuron> dest;
+
+ for (auto const& node : _neurons)
+ {
+ if (node->identifier() == destIdentifier)
+ {
+ dest = node;
+ }
+ }
+
+ if (!dest)
+ {
+ return false;
+ }
+ return dest->hasInputWithWeight(srcIdentifier, weight);
+}