#pragma once #include "Exception.h" #include "Cell.h" #include #include #include namespace NeuralNetworks { namespace ConstructiveAlgorithms { namespace CelularEncoding { class CelularEncoding { public: CelularEncoding(const CelularEncoding &) = delete; CelularEncoding &operator=(const CelularEncoding &) = delete; CelularEncoding() { } void setActivationFunction(const std::shared_ptr &fun) { _activationFunction=fun; } void setMaxSteps(std::size_t steps) { _maxSteps=steps; } NeuralNetwork::Recurrent::Network run() { std::size_t cellsStep = 0; std::size_t steps=0; do { cellsStep = step(); steps++; } while(cellsStep > 0 && steps < _maxSteps); if(steps >= _maxSteps) { throw Exception("Went over max steps"); } if(cells.size() > _maxCells) { throw Exception("Went over max cells"); } std::size_t outputs = 0; std::size_t inputs = 0; std::vector cells2Neurons; cells2Neurons.resize(cells.size()); std::size_t indexOfNeuronTmp=1; for(std::size_t i = 0; i < cells.size(); i++) { if(cells[i]->isInput()) { cells2Neurons[i] = indexOfNeuronTmp++; inputs++; } } for(std::size_t i = 0; i < cells.size(); i++) { if(cells[i]->isOutput()) { if(!cells[i]->isInput()) { cells2Neurons[i] = indexOfNeuronTmp++; } outputs++; } } for(std::size_t i = 0; i < cells.size(); i++) { if(!cells[i]->isOutput() && !cells[i]->isInput()) { cells2Neurons[i] = indexOfNeuronTmp++; } } std::size_t hiddenNeurons = static_cast(cells.size()) - static_cast(inputs) - static_cast(outputs) < 0 ? 0 : cells.size() - inputs - outputs; NeuralNetwork::Recurrent::Network netw(inputs, outputs, hiddenNeurons); for(std::size_t i = 0; i < cells.size(); i++) { const auto &cell = cells[i]; std::size_t indexOfNeuron = cells2Neurons[i]; auto& neuron = netw[indexOfNeuron]; if(cells2Neurons[i] > inputs) { neuron.setActivationFunction(*_activationFunction); } neuron.weight(0)=cell->getBias(); for(auto &link: cells[i]->getLinks()) { if(link.status == true) { neuron.weight(cells2Neurons[link.neuron]) = link.value; } else { neuron.weight(cells2Neurons[link.neuron]) = 0.0; } } } return netw; } Cell &addCell(const EvolutionaryAlgorithm::GeneticPrograming::CodeTree *c) { cells.push_back(std::make_shared(cells.size(), c)); return (*cells.back()); } void setAcyclicTopology() { cells.clear(); /* for(std::size_t i = 0; i < inputSize; i++) { addCell(code).die(); } */ Cell &cell = addCell(code); cell.setLife(_initialLife); _processingOrder.push_back(cell.getID()); cell.setOutput(); cell.setInput(); /* for(std::size_t i = 0; i < inputSize; i++) { Link l(true, 1.0, i); cell.addLink(l); } */ } void setCyclicTopology() { setAcyclicTopology(); // Acyclic + reccurent link Link l(true, 1.0, cells.back()->getID()); cells.back()->addLink(l); } void setCode(const EvolutionaryAlgorithm::GeneticPrograming::CodeTree *code_) { code = code_; } const EvolutionaryAlgorithm::GeneticPrograming::CodeTree *getCodeStart() const { return code; } std::vector> &getCells() { return cells; } void addCellToProcessingOrder(std::size_t id) { auto position = std::find(_processingOrder.begin(),_processingOrder.end(),currentID); if(position == _processingOrder.end()) { _processingOrder.push_back(id); } else { _processingOrder.insert(position+1,id); } } void setInitiaLife(std::size_t life) { _initialLife=life; } protected: std::size_t step(); private: std::size_t _maxCells= 15; std::size_t _maxSteps = std::numeric_limits::max(); std::size_t _initialLife = 2.0; std::shared_ptr _activationFunction = std::make_shared(); std::vector _processingOrder = {}; std::size_t currentID = 0; const EvolutionaryAlgorithm::GeneticPrograming::CodeTree *code = nullptr; std::vector> cells = {}; }; } } }