diff options
author | Paul Oliver <contact@pauloliver.dev> | 2024-02-29 19:04:34 +0100 |
---|---|---|
committer | Paul Oliver <contact@pauloliver.dev> | 2024-02-29 19:16:14 +0100 |
commit | e6ab4a8ed100d5d5b7611c74cf3ccd556f1f1d71 (patch) | |
tree | 129cf13c2f9b3eae54402300db4570815789a02a /src/Utils |
Diffstat (limited to 'src/Utils')
-rw-r--r-- | src/Utils/LoadFile.cpp | 280 | ||||
-rw-r--r-- | src/Utils/NodeTypes.cpp | 41 | ||||
-rw-r--r-- | src/Utils/Point.cpp | 33 | ||||
-rw-r--r-- | src/Utils/SaveFile.cpp | 249 | ||||
-rw-r--r-- | src/Utils/ValuePoint.cpp | 7 |
5 files changed, 610 insertions, 0 deletions
diff --git a/src/Utils/LoadFile.cpp b/src/Utils/LoadFile.cpp new file mode 100644 index 0000000..3849f76 --- /dev/null +++ b/src/Utils/LoadFile.cpp @@ -0,0 +1,280 @@ +#include <HyperNeat/Population.hpp> +#include <HyperNeat/NoveltyMetric.hpp> +#include <HyperNeat/NeuralNetPrms.hpp> +#include <HyperNeat/Utils/LoadFile.hpp> + +using namespace std; +using namespace hyperneat; + +LoadFile::LoadFile(Istream& stream) + : _stream(stream) +{ + _stream.setf(ios::boolalpha); +} + +void +LoadFile::loadPopulation(Population& population) +{ + size_t speciesCnt = 0; + size_t innovationsCount = 0; + ssize_t lastReplacement = 0; + ssize_t lastMother = 0; + ssize_t lastFather = 0; + bool hasNoveltyMetric = false; + bool hasNeuralNets = false; + auto& prms = population._prms; + + nextPrm() >> population._populationLock; + nextPrm() >> population._lockedOrganisms; + nextPrm() >> population._frozenOrganisms; + nextPrm() >> innovationsCount; + nextPrm() >> population._basicInnovs; + nextPrm() >> lastReplacement; + nextPrm() >> lastMother; + nextPrm() >> lastFather; + nextPrm() >> population._replacements; + nextPrm() >> population._distanceThreshold; + nextPrm() >> population._oldOrganisms; + nextPrm() >> population._minOldOrganisms; + nextPrm() >> hasNoveltyMetric; + nextPrm() >> population._updates; + nextPrm() >> speciesCnt; + nextPrm() >> hasNeuralNets; + + loadPopulationPrms(prms); + + if (hasNeuralNets) { + population._nnPrms = Pointer<NeuralNetPrms>(new NeuralNetPrms); + loadNeuralNetPrms(*population._nnPrms); + } + + population._innovations.resize(innovationsCount); + + for (auto& i : population._innovations) { + String nodeStr; + + nextPrm() >> i._number; + nextPrm() >> i._source; + nextPrm() >> i._target; + nextPrm() >> i._depth; + nextPrm() >> nodeStr; + + i._nodeType = stringToNode(nodeStr); + } + + population._allOrganisms.resize(prms._popSize, Organism(&population)); + population._species.resize(speciesCnt); + + for (auto& i : population._allOrganisms) { + loadOrganism(i); + } + + population._lastReplacement = (lastReplacement == -1 ? nullptr: &population._allOrganisms[lastReplacement]); + population._lastMother = (lastMother == -1 ? nullptr: &population._allOrganisms[lastMother]); + population._lastFather = (lastFather == -1 ? nullptr: &population._allOrganisms[lastFather]); + + for (auto& i : population._species) { + size_t specieSize = 0; + nextPrm() >> specieSize; + + while (specieSize--) { + size_t organismIdx = 0; + nextArrayValue() >> organismIdx; + + i.emplace_back(&population._allOrganisms[organismIdx]); + } + } + + if (hasNoveltyMetric) { + NoveltyMetricPrms nmPrms; + loadNoveltyMetricPrms(nmPrms); + + population.setNoveltyMetric(nmPrms); + loadNoveltyMetric(*population._noveltyMetric); + } + + if (hasNeuralNets) { + population.generateAllNeuralNets(); + } + + if (prms._seed != 0) { + population._randGen.seed(prms._seed); + } else { + population._randGen.seed(population.getRandSeed()); + } + + population._weightDeviator = BellDist(0.0, prms._weightDeviation); + population._weightSelector = RealDist(-prms._weightRange, prms._weightRange); + + population._organismsBeingGenerated = 0; +} + +void +LoadFile::loadPopulationPrms(PopulationPrms& prms) +{ + nextPrm() >> prms._popSize; + nextPrm() >> prms._cppnInputs; + nextPrm() >> prms._cppnOutputs; + nextPrm() >> prms._seed; + nextPrm() >> prms._weightRange; + nextPrm() >> prms._c1Disjoint; + nextPrm() >> prms._c3WeightDifference; + nextPrm() >> prms._initialDistanceThreshold; + nextPrm() >> prms._distanceThresholdShift; + nextPrm() >> prms._sexualReproductionRate; + nextPrm() >> prms._weightMutationRate; + nextPrm() >> prms._weightDeviation; + nextPrm() >> prms._interspeciesMatingRate; + nextPrm() >> prms._geneDisablingRatio; + nextPrm() >> prms._linkMutationRate; + nextPrm() >> prms._nodeMutationRate; + nextPrm() >> prms._targetSpeciesCount; + nextPrm() >> prms._eligibilityRatio; + nextPrm() >> prms._minimumLifetime; + nextPrm() >> prms._replBeforeReorganization; +} + +void +LoadFile::loadNeuralNetPrms(NeuralNetPrms& prms) +{ + size_t inputs = 0; + size_t outputs = 0; + + nextPrm() >> prms._testGridLevel; + nextPrm() >> prms._maxQuadTreeLevel; + nextPrm() >> prms._minQuadTreeLevel; + nextPrm() >> prms._bandPruningThreshold; + nextPrm() >> prms._varianceThreshold; + nextPrm() >> prms._divisionThreshold; + nextPrm() >> prms._iterations; + nextPrm() >> inputs; + nextPrm() >> outputs; + + prms._inputMap.resize(inputs); + prms._outputMap.resize(outputs); + + for (auto& i : prms._inputMap) { + nextArrayValue() >> i._x; + nextArrayValue() >> i._y; + } + + for (auto& i : prms._outputMap) { + nextArrayValue() >> i._x; + nextArrayValue() >> i._y; + } +} + +void +LoadFile::loadNoveltyMetric(NoveltyMetric& noveltyMetric) +{ + for (auto& i : noveltyMetric._behaviors) { + nextPrm() >> i._criteriaReached; + nextPrm() >> i._noveltyScore; + nextPrm() >> i._toBeArchived; + + for (auto& j : i._characterization) { + nextArrayValue() >> j; + } + } + + size_t archiveSize = 0; + nextPrm() >> archiveSize; + noveltyMetric._archive.resize(archiveSize); + + for (auto& i : noveltyMetric._archive) { + i.resize(noveltyMetric._prms._characterizationSize, 0.0); + + for (auto& j : i) { + nextArrayValue() >> j; + } + } +} + +void +LoadFile::loadNoveltyMetricPrms(NoveltyMetricPrms& noveltyMetricPrms) +{ + nextPrm() >> noveltyMetricPrms._noveltyThreshold; + nextPrm() >> noveltyMetricPrms._referenceOrganisms; + nextPrm() >> noveltyMetricPrms._characterizationSize; + nextPrm() >> noveltyMetricPrms._criteriaReachedByDefault; +} + +void +LoadFile::loadOrganism(Organism& organism) +{ + nextPrm() >> organism._index; + nextPrm() >> organism._fitness; + nextPrm() >> organism._isLocked; + nextPrm() >> organism._isFrozen; + nextPrm() >> organism._specie; + nextPrm() >> organism._lifetime; + + loadGenome(organism._genome); +} + +void +LoadFile::loadGenome(Genome& genome) +{ + size_t nodes = 0; + + nextPrm() >> genome._inputs; + nextPrm() >> nodes; + + while (nodes--) { + String nodeType; + size_t links = 0; + size_t innov = 0; + + nextPrm() >> innov; + auto& nodeGene = genome._nodeGenes[innov]; + + nextPrm() >> nodeGene._depth; + nextPrm() >> nodeType; + nodeGene._nodeType = stringToNode(nodeType); + + nextPrm() >> links; + + while (links--) { + size_t source = 0; + + nextPrm() >> source; + auto& linkGene = nodeGene._linkGenes[source]; + + nextPrm() >> linkGene._weight; + nextPrm() >> linkGene._isEnabled; + } + } +} + +Istream& +LoadFile::nextPrm(bool arrayVal) +{ + for (;;) { + char ch = static_cast<char>(_stream.peek()); + + if (ch == '#') { + _stream.ignore(numeric_limits<streamsize>::max(), '\n'); + } else { + if (!arrayVal) { + _stream.ignore(); + + if (ch == '=') { + return _stream; + } + } else { + if (string("-0123456789").find(ch) != string::npos) { + return _stream; + } + + _stream.ignore(); + } + } + } +} + + +Istream& +LoadFile::nextArrayValue() +{ + return nextPrm(true); +} diff --git a/src/Utils/NodeTypes.cpp b/src/Utils/NodeTypes.cpp new file mode 100644 index 0000000..b11b079 --- /dev/null +++ b/src/Utils/NodeTypes.cpp @@ -0,0 +1,41 @@ +#include <HyperNeat/Utils/NodeTypes.hpp> + +namespace hyperneat +{ + String + nodeToString(NodeType type) + { + switch (type) { + case NodeType::SIGMOID: + return "\"sigmoid\""; + + case NodeType::GAUSSIAN: + return "\"gaussian\""; + + case NodeType::SINE: + return "\"sine\""; + + case NodeType::ABSOLUTE: + return "\"absolute\""; + + default: + return "\"nullType\""; + } + } + + NodeType + stringToNode(const String& str) + { + if (str == "\"sigmoid\"") { + return NodeType::SIGMOID; + } else if (str == "\"gaussian\"") { + return NodeType::GAUSSIAN; + } else if (str == "\"sine\"") { + return NodeType::SINE; + } else if (str == "\"absolute\"") { + return NodeType::ABSOLUTE; + } else { + return NodeType::NULL_TYPE; + } + } +} diff --git a/src/Utils/Point.cpp b/src/Utils/Point.cpp new file mode 100644 index 0000000..7dd9610 --- /dev/null +++ b/src/Utils/Point.cpp @@ -0,0 +1,33 @@ +#include <cmath> +#include <HyperNeat/Utils/Point.hpp> + +using namespace std; +using namespace hyperneat; + +Point::Point(double x, double y) + : _x(x), _y(y) +{} + +double +Point::distance(const Point& other) const +{ + double x = _x - other._x; + double y = _y - other._y; + + return sqrt(x * x + y * y); +} + +bool +Point::operator==(const Point& other) const{ + return (_x == other._x) && (_y == other._y); +} + +bool +Point::operator<(const Point& other) const +{ + if (_x == other._x) { + return _y < other._y; + } else { + return _x < other._x; + } +} diff --git a/src/Utils/SaveFile.cpp b/src/Utils/SaveFile.cpp new file mode 100644 index 0000000..8c471f6 --- /dev/null +++ b/src/Utils/SaveFile.cpp @@ -0,0 +1,249 @@ +#include <HyperNeat/Population.hpp> +#include <HyperNeat/NoveltyMetric.hpp> +#include <HyperNeat/NeuralNetPrms.hpp> +#include <HyperNeat/Utils/SaveFile.hpp> + +using namespace std; +using namespace hyperneat; + +SaveFile::SaveFile(Ostream& stream) + : _stream(stream) +{ + _stream.setf(ios::boolalpha); + _stream.precision(numeric_limits<double>::digits10); +} + +void +SaveFile::savePopulation(Population& population, bool shuttedDown, size_t tabs, const String& prefix) +{ + print(tabs) << "# hyperneat::Population data:" << newl(); + print(tabs) << "# -------------------------------------------------------------------------------------" << newl(); + print(tabs) << "# DO NOT erase or change the order of any entry! Data is read back ENTRY by ENTRY." << newl(2); + + ssize_t lastReplacement = (population.getLastReplacement() ? population.getLastReplacement()->getIndex() : -1); + ssize_t lastMother = (population.getLastMother() ? population.getLastMother()->getIndex() : -1); + ssize_t lastFather = (population.getLastFather() ? population.getLastFather()->getIndex() : -1); + + print(tabs) << "[" << prefix << "population]" << newl(); + print(tabs + 1) << "populationLock = " << (shuttedDown ? false : population.isLocked()) << newl(); + print(tabs + 1) << "lockedOrganisms = " << (shuttedDown ? 0 : population.getLockedOrganisms()) << newl(); + print(tabs + 1) << "frozenOrganisms = " << (shuttedDown ? 0 : population.getFrozenOrganisms()) << newl(); + print(tabs + 1) << "innovationsCount = " << population.getInnovationsCount() << newl(); + print(tabs + 1) << "basicInnovations = " << population.getBasicInnovationsCount() << newl(); + print(tabs + 1) << "lastReplacement = " << lastReplacement << newl(); + print(tabs + 1) << "lastMother = " << lastMother << newl(); + print(tabs + 1) << "lastFather = " << lastFather << newl(); + print(tabs + 1) << "replacements = " << population.getReplacements() << newl(); + print(tabs + 1) << "distanceThreshold = " << population.getDistanceThreshold() << newl(); + print(tabs + 1) << "oldOrganisms = " << (shuttedDown ? 0 : population.getOldOrganisms()) << newl(); + print(tabs + 1) << "minOldOrganisms = " << population.getMinimumOldOrganisms() << newl(); + print(tabs + 1) << "noveltyMetric = " << population.isNoveltyMetricSet() << newl(); + print(tabs + 1) << "updates = " << population.getUpdates() << newl(); + print(tabs + 1) << "species = " << population.getSpecies().size() << newl(); + print(tabs + 1) << "withNeuralNets = " << population.hasNeuralNets() << newl(2); + + savePopulationPrms(population.getPopulationPrms(), tabs + 1, prefix + "population."); + + if (population.hasNeuralNets()) { + print() << newl(); + saveNeuralNetPrms(population.getNeuralNetPrms(), tabs + 1, prefix + "population."); + } + + for (auto& i : population.getInnovations()) { + print() << newl(); + print(tabs + 1) << "[[" + prefix + "population.innovation]]" << newl(); + print(tabs + 2) << "number = " << i._number << newl(); + print(tabs + 2) << "source = " << i._source << newl(); + print(tabs + 2) << "target = " << i._target << newl(); + print(tabs + 2) << "depth = " << i._depth << newl(); + print(tabs + 2) << "function = " << nodeToString(i._nodeType) << newl(); + } + + for (auto& i : population.getAllOrganisms()) { + print() << newl(); + saveOrganism(i, shuttedDown, tabs + 1, prefix + "population."); + } + + for (auto& i : population.getSpecies()) { + print() << newl(); + print(tabs + 1) << "[[" + prefix + "population.specie]]" << newl(); + print(tabs + 2) << "size = " << i.size() << newl(); + print(tabs + 2) << "members = [" << newl(); + + for (auto& j : i) { + print(tabs + 3) << j->getIndex() << "," << newl(); + } + + print(tabs + 2) << "]" << newl(); + } + + if (population.isNoveltyMetricSet()) { + print() << newl(); + saveNoveltyMetric(population.getNoveltyMetric(), shuttedDown, tabs + 1, prefix + "population."); + } +} + +void +SaveFile::savePopulationPrms(const PopulationPrms& prms, size_t tabs, const String& prefix) +{ + print(tabs) << "[" << prefix << "parameters]" << newl(); + print(tabs + 1) << "popSize = " << prms._popSize << newl(); + print(tabs + 1) << "cppnInputs = " << prms._cppnInputs << newl(); + print(tabs + 1) << "cppnOutputs = " << prms._cppnOutputs << newl(); + print(tabs + 1) << "seed = " << prms._seed << newl(); + print(tabs + 1) << "weightRange = " << prms._weightRange << newl(); + print(tabs + 1) << "disjointCoeff = " << prms._c1Disjoint << newl(); + print(tabs + 1) << "weightDifferenceCoeff = " << prms._c3WeightDifference << newl(); + print(tabs + 1) << "initialDistanceThreshold = " << prms._initialDistanceThreshold << newl(); + print(tabs + 1) << "distanceThresholdShift = " << prms._distanceThresholdShift << newl(); + print(tabs + 1) << "sexualReproductionRate = " << prms._sexualReproductionRate << newl(); + print(tabs + 1) << "weightMutationRate = " << prms._weightMutationRate << newl(); + print(tabs + 1) << "weightDeviation = " << prms._weightDeviation << newl(); + print(tabs + 1) << "interspeciesMatingRate = " << prms._interspeciesMatingRate << newl(); + print(tabs + 1) << "geneDisablingRatio = " << prms._geneDisablingRatio << newl(); + print(tabs + 1) << "linkMutationRate = " << prms._linkMutationRate << newl(); + print(tabs + 1) << "nodeMutationRate = " << prms._nodeMutationRate << newl(); + print(tabs + 1) << "targetSpeciesCount = " << prms._targetSpeciesCount << newl(); + print(tabs + 1) << "eligibilityRatio = " << prms._eligibilityRatio << newl(); + print(tabs + 1) << "minimumLifetime = " << prms._minimumLifetime << newl(); + print(tabs + 1) << "replBeforeReorganization = " << prms._replBeforeReorganization << newl(); +} + +void +SaveFile::saveNeuralNetPrms(const NeuralNetPrms& prms, size_t tabs, const String& prefix) +{ + print(tabs) << "[" << prefix << "neuralNetParameters]" << newl(); + print(tabs + 1) << "testGridLevel = " << prms._testGridLevel << newl(); + print(tabs + 1) << "maxQuadTreeLevel = " << prms._maxQuadTreeLevel << newl(); + print(tabs + 1) << "minQuadTreeLevel = " << prms._minQuadTreeLevel << newl(); + print(tabs + 1) << "bandPruningThreshold = " << prms._bandPruningThreshold << newl(); + print(tabs + 1) << "varianceThreshold = " << prms._varianceThreshold << newl(); + print(tabs + 1) << "divisionThreshold = " << prms._divisionThreshold << newl(); + print(tabs + 1) << "iterations = " << prms._iterations << newl(); + print(tabs + 1) << "inputs = " << prms._inputMap.size() << newl(); + print(tabs + 1) << "outputs = " << prms._outputMap.size() << newl(2); + print(tabs + 1) << "inputMap = [" << newl(); + + for (auto& i : prms._inputMap) { + print(tabs + 2) << "[" << i._x << ", " << i._y << "]," << newl(); + } + + print(tabs + 1) << "]" << newl(2); + print(tabs + 1) << "outputMap = [" << newl(); + + for (auto& i : prms._outputMap) { + print(tabs + 2) << "[" << i._x << ", " << i._y << "]," << newl(); + } + + print(tabs + 1) << "]" << newl(); +} + +void +SaveFile::saveOrganism(const Organism& organism, bool shuttedDown, size_t tabs, const String& prefix) +{ + print(tabs) << "[[" << prefix << "organism]]" << newl(); + + if (organism.isChampion()) { + print(tabs + 1) << "# Current champion." << newl(2); + } + + print(tabs + 1) << "index = " << organism.getIndex() << newl(); + print(tabs + 1) << "fitness = " << (shuttedDown ? 0 : organism._fitness) << newl(); + print(tabs + 1) << "isLocked = " << (shuttedDown ? false : organism.isLocked()) << newl(); + print(tabs + 1) << "isFrozen = " << (shuttedDown ? false : organism.isFrozen()) << newl(); + print(tabs + 1) << "specie = " << organism.getSpecie() << newl(); + print(tabs + 1) << "lifetime = " << (shuttedDown ? 0 : organism.getLifetime()) << newl(2); + + saveGenome(organism.getGenome(), tabs + 1, prefix + "organism."); + + // If shutted down, save Neural Net +} + +void +SaveFile::saveGenome(const Genome& genome, size_t tabs, const String& prefix) +{ + print(tabs) << "[" << prefix << "genome]" << newl(); + print(tabs + 1) << "inputs = " << genome._inputs << newl(); + print(tabs + 1) << "nodes = " << genome._nodeGenes.size() << newl(); + + for (auto& i : genome._nodeGenes) { + print() << newl(); + print(tabs + 1) << "[[" << prefix << "genome.nodeGene]]" << newl(); + print(tabs + 2) << "innovation = " << i.first << newl(); + print(tabs + 2) << "depth = " << i.second._depth << newl(); + print(tabs + 2) << "function = " << nodeToString(i.second._nodeType) << newl(); + print(tabs + 2) << "links = " << i.second._linkGenes.size() << newl(); + + for (auto& j : i.second._linkGenes) { + print() << newl(); + print(tabs + 2) << "[[" << prefix << "genome.nodeGene.linkGene]]" << newl(); + print(tabs + 3) << "source = " << j.first << newl(); + print(tabs + 3) << "weight = " << j.second._weight << newl(); + print(tabs + 3) << "isEnabled = " << j.second._isEnabled << newl(); + } + } +} + +void +SaveFile::saveNoveltyMetric(const NoveltyMetric& noveltyMetric, bool shuttedDown, size_t tabs, const String& prefix) +{ + print(tabs) << "[" << prefix << "noveltyMetric]" << newl(); + saveNoveltyMetricPrms(noveltyMetric.getPrms(), tabs + 1, prefix + "noveltyMetric."); + + bool critDef = noveltyMetric.getPrms()._criteriaReachedByDefault; + + for (auto& i : noveltyMetric.getBehaviors()) { + print() << newl(); + print(tabs + 1) << "[[" << prefix << "noveltyMetric.behavior]]" << newl(); + print(tabs + 2) << "criteriaReached = " << (shuttedDown ? critDef : i._criteriaReached) << newl(); + print(tabs + 2) << "noveltyScore = " << (shuttedDown ? 0 : i.getNoveltyScore()) << newl(); + print(tabs + 2) << "toBeArchived = " << (shuttedDown ? false : i.isToBeArchived()) << newl(); + print(tabs + 2) << "characterization = [" << newl(); + + for (auto& j : i.getCharacterization()) { + print(tabs + 3) << j << "," << newl(); + } + + print(tabs + 2) << "]" << newl(); + } + + print() << newl(); + print(tabs + 1) << "[" << prefix << "noveltyMetric.archive]" << newl(); + print(tabs + 2) << "size = " << noveltyMetric.getArchive().size() << newl(); + print(tabs + 2) << "characterizations = [" << newl(); + + for (auto& i : noveltyMetric.getArchive()) { + print(tabs + 3) << "[" << newl(); + + for (auto& j : i) { + print(tabs + 4) << j << "," << newl(); + } + + print(tabs + 3) << "]," << newl(); + } + + print(tabs + 2) << "]" << newl(); +} + +void +SaveFile::saveNoveltyMetricPrms(const NoveltyMetricPrms& noveltyMetricPrms, size_t tabs, const String& prefix) +{ + print(tabs) << "[" << prefix << "parameters]" << newl(); + print(tabs + 1) << "noveltyThreshold = " << noveltyMetricPrms._noveltyThreshold << newl(); + print(tabs + 1) << "referenceOrganisms = " << noveltyMetricPrms._referenceOrganisms << newl(); + print(tabs + 1) << "characterizationSize = " << noveltyMetricPrms._characterizationSize << newl(); + print(tabs + 1) << "criteriaReachedByDefault = " << noveltyMetricPrms._criteriaReachedByDefault << newl(); +} + +Ostream& +SaveFile::print(size_t tabs) +{ + _stream << String(tabs * 4, ' '); + return _stream; +} + +String +SaveFile::newl(size_t lines) +{ + return String(lines, '\n'); +} diff --git a/src/Utils/ValuePoint.cpp b/src/Utils/ValuePoint.cpp new file mode 100644 index 0000000..d9cdc64 --- /dev/null +++ b/src/Utils/ValuePoint.cpp @@ -0,0 +1,7 @@ +#include <HyperNeat/Utils/ValuePoint.hpp> + +using namespace hyperneat; + +ValuePoint::ValuePoint(double x, double y, double value, double segment) + : Point(x, y), _value(value), _segment(segment) +{} |