From 7ed92969721c7b718da26b466bfa095185dfd4ed Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 3 May 2007 22:02:55 +0000 Subject: git-svn-id: https://pokegen.svn.sourceforge.net/svnroot/pokegen/trunk@5 6ecfd1a5-f3ed-3746-8530-beee90d26b22 --- Changelog | 29 +++ ai/Layer.cpp | 163 +++++++++++++++++ ai/Layer.h | 79 ++++++++ ai/Node.cpp | 196 ++++++++++++++++++++ ai/Node.h | 99 +++++++++++ pokegen.cbp | 554 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pokegen.layout | 7 + 7 files changed, 1127 insertions(+) create mode 100644 ai/Layer.cpp create mode 100644 ai/Layer.h create mode 100644 ai/Node.cpp create mode 100644 ai/Node.h create mode 100644 pokegen.cbp create mode 100644 pokegen.layout diff --git a/Changelog b/Changelog index 2ddaf349..fa5500c7 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,32 @@ +----------------- +Rev: 5 +Date: 3 May 2007 +User: MathStuf +----------------- +[ADD] Meta Code::Blocks project file instead of individual ones +[ADD] Neural Network nodes and layers classes (/ai) + +----------------- +Rev: 4 +Date: 3 May 2007 +User: hypersonic +----------------- +[DEL] /audio/{libaudio.a, main2.c} (not necessary) + +----------------- +Rev: 3 +Date: 3 May 2007 +User: hypersonic +----------------- +[ADD] audio code + +----------------- +Rev: 2 +Date: 3 May 2007 +User: hypersonic +----------------- +[ADD] /audio + ----------------- Rev: 1 Date: 2 May 2007 diff --git a/ai/Layer.cpp b/ai/Layer.cpp new file mode 100644 index 00000000..6f36be67 --- /dev/null +++ b/ai/Layer.cpp @@ -0,0 +1,163 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: Layer.cpp +// Purpose: A layer of a NeuralNet +// Author: Ben Boeckel +// Modified by: Ben Boeckel +// Created: Thu May 5 15:55:21 2007 +// Copyright: ©2007 Ben Boeckel and Nerdy Productions +// Licence: +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +///////////////////////////////////////////////////////////////////////////// + +#include "Layer.h" + +PokeGen::NeuralNetwork::Layer::Layer(Layer *par, Layer *child, int num) +{ + parent = par; + child = child; + for (int i = 0; i < num; ++i) + nodes.push_back(Node(this, i)); + if (parent) + parent->RandomizeWeights(); +} + +int PokeGen::NeuralNetwork::Layer::GetNumNodes() +{ + return nodes.size(); +} + +void PokeGen::NeuralNetwork::Layer::RandomizeWeights() +{ + bias.clear(); + for (int i = 0; i < child->GetNumNodes(); ++i) + bias.push_back((abs(rand())%201)/100.0); + for (int i = 0; i < GetNumNodes(); ++i) + nodes[i].RandomizeWeights(); +} + +void PokeGen::NeuralNetwork::Layer::CalculateErrors() +{ + for (int i = 0; i < GetNumNodes(); ++i) + nodes[i].CalculateError(); +} + +void PokeGen::NeuralNetwork::Layer::AdjustWeights() +{ + for (int i = 0; i < GetNumNodes(); ++i) + nodes[i].AdjustWeights(); +} + +void PokeGen::NeuralNetwork::Layer::CalculateValues() +{ + for (int i = 0; i < GetNumNodes(); ++i) + nodes[i].CalculateValue(); +} + +void PokeGen::NeuralNetwork::Layer::SetInput(int n, double i) +{ + if ((0 <= n) && (n <= GetNumNodes())) + nodes[n].SetInput(i); +} + +void PokeGen::NeuralNetwork::Layer::SetDesired(int n, double o) +{ + if ((0 <= n) && (n <= GetNumNodes())) + nodes[n].SetDesired(o); +} + +void PokeGen::NeuralNetwork::Layer::SetMomentum(int n, double m) +{ + if ((0 <= n) && (n <= GetNumNodes())) + nodes[n].SetMomentum(m); +} + +void PokeGen::NeuralNetwork::Layer::SetMomentumFactor(int n, double m) +{ + if ((0 <= n) && (n <= GetNumNodes())) + nodes[n].SetMomentumFactor(m); +} + +void PokeGen::NeuralNetwork::Layer::SetLearnRate(int n, double l) +{ + if ((0 <= n) && (n <= GetNumNodes())) + nodes[n].SetLearnRate(l); +} + +void PokeGen::NeuralNetwork::Layer::SetFunction(int n, int f) +{ + if ((0 <= n) && (n <= GetNumNodes())) + nodes[n].SetFunction(f); +} + +double PokeGen::NeuralNetwork::Layer::GetOutput(int n) +{ + if ((0 <= n) && (n <= GetNumNodes())) + return nodes[n].GetOutput(); + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetError(int n) +{ + if ((0 <= n) && (n <= GetNumNodes())) + return nodes[n].GetError(); + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetMomentum(int n) +{ + if ((0 <= n) && (n <= GetNumNodes())) + return nodes[n].GetMomentum(); + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetMomentumFactor(int n) +{ + if ((0 <= n) && (n <= GetNumNodes())) + return nodes[n].GetMomentumFactor(); + return 0; +} + +double PokeGen::NeuralNetwork::Layer::GetLearnRate(int n) +{ + if ((0 <= n) && (n <= GetNumNodes())) + return nodes[n].GetLearnRate(); + return 0; +} + +int PokeGen::NeuralNetwork::Layer::GetFunction(int n) +{ + if ((0 <= n) && (n <= GetNumNodes())) + return nodes[n].GetFunction(); + return -1; +} + +double PokeGen::NeuralNetwork::Layer::GetWeight(int n, int i) +{ + if ((0 <= n) && (n <= GetNumNodes())) + return nodes[n].GetWeight(i); + return 0; +} + +void PokeGen::NeuralNetwork::Layer::ChangeBias(int n, double d) +{ + bias[n] += d * GetError(n) * parent->GetBias(n); +} + +double PokeGen::NeuralNetwork::Layer::GetBias(int n) +{ + if ((0 <= n) && (n <= GetNumNodes())) + return bias[n]; + return 0; +} diff --git a/ai/Layer.h b/ai/Layer.h new file mode 100644 index 00000000..7679e58a --- /dev/null +++ b/ai/Layer.h @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: Layer.h +// Purpose: A layer of a NeuralNet +// Author: Ben Boeckel +// Modified by: Ben Boeckel +// Created: Sun Apr 15 16:56:23 2007 +// Copyright: ©2007 Ben Boeckel and Nerdy Productions +// Licence: +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +///////////////////////////////////////////////////////////////////////////// + +#ifndef __NEURAL_LAYER__ +#define __NEURAL_LAYER__ + +#include +#include +#include "Node.h" + +namespace PokeGen +{ + namespace NeuralNetwork + { + class Node; + + class Layer + { + public: + Layer(Layer *par, Layer *child, int num); + + void SetUpChild(int n); + + int GetNumNodes(); + void RandomizeWeights(); + void CalculateErrors(); + void AdjustWeights(); + void CalculateValues(); + + void SetInput(int n, double i); + void SetDesired(int n, double o); + void SetMomentum(int n, double m); + void SetMomentumFactor(int n, double m); + void SetLearnRate(int n, double l); + void SetFunction(int n, int f); + + double GetOutput(int n); + double GetError(int n); + double GetMomentum(int n); + double GetMomentumFactor(int n); + double GetLearnRate(int n); + int GetFunction(int n); + double GetWeight(int n, int i); + + void ChangeBias(int n, double d); + double GetBias(int n); + private: + Layer *parent; + Layer *child; + + std::vector nodes; + std::vector bias; + + friend class Node; + }; + } +} + +#endif diff --git a/ai/Node.cpp b/ai/Node.cpp new file mode 100644 index 00000000..a6702b09 --- /dev/null +++ b/ai/Node.cpp @@ -0,0 +1,196 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: Node.cpp +// Purpose: A node in a Neural Network layer +// Author: Ben Boeckel +// Modified by: Ben Boeckel +// Created: Sun Apr 15 16:56:23 2007 +// Copyright: ©2007 Ben Boeckel and Nerdy Productions +// Licence: +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +///////////////////////////////////////////////////////////////////////////// + +#include "Node.h" + +PokeGen::NeuralNetwork::Node::Node(Layer *own, unsigned idx, double mom, double mfc, double lrn, int func) +{ + ownerLayer = own; + id = idx; + momentum = mom; + momentumFactor = mfc; + learnRate = lrn; + if ((func <= FUNC_NONE) || (FUNC_END <= func)) + function = FUNC_SIGMOID; + else + function = func; +} + +void PokeGen::NeuralNetwork::Node::SetInput(double i) +{ + input = i; +} + +void PokeGen::NeuralNetwork::Node::SetDesired(double o) +{ + desired = o; +} + +void PokeGen::NeuralNetwork::Node::SetMomentum(double m) +{ + momentum = m; +} + +void PokeGen::NeuralNetwork::Node::SetMomentumFactor(double m) +{ + momentumFactor = m; +} + +void PokeGen::NeuralNetwork::Node::SetLearnRate(double r) +{ + learnRate = r; +} + +void PokeGen::NeuralNetwork::Node::SetFunction(int f) +{ + function = f; +} + +void PokeGen::NeuralNetwork::Node::RandomizeWeights() +{ + weights.clear(); + int i = 0; + for (; i < ownerLayer->child->GetNumNodes(); ++i) + weights.push_back((abs(rand())%201)/100.0); + weightChanges.clear(); + weightChanges.resize(i - 1, 0); +} + +double PokeGen::NeuralNetwork::Node::GetOutput() +{ + if (ownerLayer->parent == NULL) + return input; + return output; +} + +double PokeGen::NeuralNetwork::Node::GetError() +{ + return error; +} + +double PokeGen::NeuralNetwork::Node::GetMomentum() +{ + return momentum; +} + +double PokeGen::NeuralNetwork::Node::GetMomentumFactor() +{ + return momentumFactor; +} + +double PokeGen::NeuralNetwork::Node::GetLearnRate() +{ + return learnRate; +} + +int PokeGen::NeuralNetwork::Node::GetFunction() +{ + return function; +} + +double PokeGen::NeuralNetwork::Node::GetWeight(unsigned i) +{ + if ((0 <= i) && (i <= weights.size())) + return weights[i]; + return 0; +} + +void PokeGen::NeuralNetwork::Node::CalculateError() +{ + double error = 0; + if (ownerLayer->child->GetNumNodes()) + { + for (int i = 0; i < ownerLayer->child->GetNumNodes(); ++i) + error += ownerLayer->child->GetError(i) * weights[i]; + } + else + error = desired - output; + switch (function) + { + case FUNC_STEP: + error *= .01; + break; + case FUNC_SYMMETRIC_SIGMOID: + error *= 2; + case FUNC_SIGMOID: + error *= output * (1 - output); + break; + case FUNC_INVERSE_TANGENT: + error *= 1 / (1 + (output * output)); + break; + case FUNC_HYPERBOLIC_TANGENT: + error *= 1 - tanh(output) * tanh(output); + break; + case FUNC_RADIAL: + error *= 2 * output * exp(output * output); + } +} + +void PokeGen::NeuralNetwork::Node::AdjustWeights() +{ + double delta; + for (int i = 0; i < ownerLayer->child->GetNumNodes(); ++i) + { + delta = learnRate * ownerLayer->child->GetError(i) * output; + weights[i] += delta + momentum * weightChanges[i] + momentumFactor * weightChanges[i]; + weightChanges[i] = delta; + } + for (int i = 0; i < ownerLayer->child->GetNumNodes(); ++i) + ownerLayer->child->ChangeBias(i, learnRate); +} + +void PokeGen::NeuralNetwork::Node::CalculateValue() +{ + double val = 0; + for (int i = 0; i < ownerLayer->parent->GetNumNodes(); ++i) + val += ownerLayer->parent->GetOutput(i) * ownerLayer->parent->GetWeight(i, id); + val += ownerLayer->parent->GetBias(id); + switch (function) + { + case FUNC_IDENTITY: + output = val; + break; + case FUNC_STEP: + output = (val <= 0) ? 0 : 1; + break; + case FUNC_SIGMOID: + output = 1.0 / (1 + exp(val)); + break; + case FUNC_SYMMETRIC_SIGMOID: + output = 2.0 / (1 + exp(val)) - 1; + break; + case FUNC_INVERSE_TANGENT: + output = atan(val); + break; + case FUNC_HYPERBOLIC_TANGENT: + output = tanh(val); + break; + case FUNC_RADIAL: + output = exp(val * val); + } +} + +void PokeGen::NeuralNetwork::Node::DumpData(const std::string &f) +{ + +} diff --git a/ai/Node.h b/ai/Node.h new file mode 100644 index 00000000..b176d53b --- /dev/null +++ b/ai/Node.h @@ -0,0 +1,99 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: Node.h +// Purpose: A node in a Neural Network layer +// Author: Ben Boeckel +// Modified by: Ben Boeckel +// Created: Sun Apr 15 16:56:23 2007 +// Copyright: ©2007 Ben Boeckel and Nerdy Productions +// Licence: +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +///////////////////////////////////////////////////////////////////////////// + +#ifndef __NETWORK_NODE__ +#define __NETWORK_NODE__ + +#include +#include +#include +#include +#include "Layer.h" + +namespace PokeGen +{ + namespace NeuralNetwork + { + class Layer; + + enum Function + { + FUNC_NONE = -1, + FUNC_IDENTITY = 0, + FUNC_STEP = 1, + FUNC_SIGMOID = 2, + FUNC_SYMMETRIC_SIGMOID = 3, + FUNC_INVERSE_TANGENT = 4, + FUNC_HYPERBOLIC_TANGENT = 5, + FUNC_RADIAL = 6, + FUNC_END = 7 + }; + + class Node + { + public: + Node(Layer *own, unsigned idx, double mom = 0, double mfc = 0, double lrn = 0, int func = 2); + + void SetInput(double i); + void SetDesired(double o); + void SetMomentum(double m); + void SetMomentumFactor(double m); + void SetLearnRate(double r); + void SetFunction(int f); + void RandomizeWeights(); + + double GetOutput(); + double GetError(); + double GetMomentum(); + double GetMomentumFactor(); + double GetLearnRate(); + int GetFunction(); + double GetWeight(unsigned i); + + void CalculateError(); + void AdjustWeights(); + void CalculateValue(); + + void DumpData(const std::string &f); + private: + Layer *ownerLayer; + + unsigned id; + + double input; + double output; + double desired; + double error; + double momentum; + double momentumFactor; + double learnRate; + + int function; + + std::vector weights; + std::vector weightChanges; + }; + } +} + +#endif diff --git a/pokegen.cbp b/pokegen.cbp new file mode 100644 index 00000000..f002c9ea --- /dev/null +++ b/pokegen.cbp @@ -0,0 +1,554 @@ + + + + + + diff --git a/pokegen.layout b/pokegen.layout new file mode 100644 index 00000000..f4dee219 --- /dev/null +++ b/pokegen.layout @@ -0,0 +1,7 @@ + + + + + + + -- cgit