Skip to content
Snippets Groups Projects
ACSFNeuralNetwork.cpp 7.5 KiB
Newer Older
//
// Created by martin on 19.08.19.
//

#include "../settings.h"
#include "ACSFNeuralNetwork.h"

lib4neuro::ACSFNeuralNetwork::ACSFNeuralNetwork(std::unordered_map<ELEMENT_SYMBOL, Element*>& elements,
                                                std::vector<ELEMENT_SYMBOL>& elements_list,
                                                bool with_charge,
                                                std::unordered_map<ELEMENT_SYMBOL, std::vector<unsigned int>> n_hidden_neurons,
                                                std::unordered_map<ELEMENT_SYMBOL, std::vector<NEURON_TYPE>> type_hidden_neurons) {
    /* Construct the neural network */
    std::vector<size_t> inputs;
    std::vector<size_t> subnet_outputs;
    size_t              neuron_idx;
    std::unordered_map<ELEMENT_SYMBOL, std::vector<size_t>> subnet_idxs;
    std::unordered_map<ELEMENT_SYMBOL, std::vector<size_t>> subnet_neuron_idxs;
    std::unordered_map<ELEMENT_SYMBOL, std::vector<size_t>> subnet_connection_idxs;


    for(size_t i = 0; i < elements_list.size(); i++) {
        std::vector<size_t> previous_layer;
        std::vector<size_t> new_layer;

        /* Create input neurons for sub-net */
        std::shared_ptr<NeuronLinear> inp_n;
        for(size_t j = 0; j < elements[elements_list.at(i)]->getSymmetryFunctions().size(); j++) {
            inp_n = std::make_shared<NeuronLinear>();
            neuron_idx = this->add_neuron(inp_n, BIAS_TYPE::NO_BIAS);
            previous_layer.emplace_back(neuron_idx);
            inputs.emplace_back(neuron_idx);
        }

        /* Add an additional input neuron for charge, if provided */
        if(with_charge) {
            inp_n = std::make_shared<NeuronLinear>();
            neuron_idx = this->add_neuron(inp_n, BIAS_TYPE::NO_BIAS);
            previous_layer.emplace_back(neuron_idx);
            inputs.emplace_back(neuron_idx);
        }

        /* Create subnet for the current element */
        bool new_subnet = false;
        if(subnet_neuron_idxs.find(elements_list.at(i)) == subnet_neuron_idxs.end()) {
            new_subnet = true;
            subnet_neuron_idxs[elements_list.at(i)] = std::vector<size_t>();
            subnet_connection_idxs[elements_list.at(i)] = std::vector<size_t>();
        }

        /* Create hidden layers in sub-net */
        std::vector<unsigned int> n_neurons = n_hidden_neurons[elements_list.at(i)];
        std::vector<NEURON_TYPE> types = type_hidden_neurons[elements_list.at(i)];
        size_t local_neuron_idx = 0;
        size_t local_connection_idx = 0;

        for(size_t j = 0; j < n_neurons.size(); j++) { /* Iterate over hidden layers */
            /* Create hidden neurons */
            for(size_t k = 0; k < n_neurons.at(j); k++) {
                std::shared_ptr<Neuron> hid_n;
                switch(types.at(j)) {
                    case NEURON_TYPE::LOGISTIC: {
                        hid_n = std::make_shared<NeuronLogistic>();
                        break;
                    }
                    case NEURON_TYPE::BINARY: {
                        hid_n = std::make_shared<NeuronBinary>();
                        break;
                    }
                    case NEURON_TYPE::CONSTANT: {
                        hid_n = std::make_shared<NeuronConstant>();
                        break;
                    }
                    case NEURON_TYPE::LINEAR: {
                        hid_n = std::make_shared<NeuronLinear>();
                        break;
                    }
                }

                if(new_subnet) {
                    neuron_idx = this->add_neuron(hid_n,
                                                  BIAS_TYPE::NEXT_BIAS);
                    subnet_neuron_idxs[elements_list.at(i)].emplace_back(neuron_idx);
                } else {
                    std::cout << subnet_neuron_idxs[elements_list.at(i)].at(0)+local_neuron_idx << std::endl;
                    neuron_idx = this->add_neuron(hid_n,
                                                  BIAS_TYPE::EXISTING_BIAS, local_neuron_idx);
                }
                local_neuron_idx++;
                new_layer.emplace_back(neuron_idx);

                /* Connect hidden neuron to the previous layer */
                for(auto prev_n : previous_layer) {
                    if(new_subnet) {
                        subnet_connection_idxs[elements_list.at(i)].emplace_back(this->add_connection_simple(prev_n,
                                                    neuron_idx,
                                                    SIMPLE_CONNECTION_TYPE::NEXT_WEIGHT));

                    } else {
                        this->add_connection_simple(prev_n,
                                                    neuron_idx,
                                                    SIMPLE_CONNECTION_TYPE::EXISTING_WEIGHT, subnet_connection_idxs[elements_list.at(i)].at(0)+local_connection_idx);
                    }
                    local_connection_idx++;
            previous_layer = new_layer;
            new_layer.clear();
        /* Create hidden layers in sub-net */
//        std::vector<unsigned int> n_neurons = n_hidden_neurons[elements_list.at(i)];
//        std::vector<NEURON_TYPE> types = type_hidden_neurons[elements_list.at(i)];
//        for(size_t j = 0; j < n_neurons.size(); j++) { /* Iterate over hidden layers */
//            /* Create hidden neurons */
//            for(size_t k = 0; k < n_neurons.at(j); k++) {
//                std::shared_ptr<Neuron> hid_n;
//                switch(types.at(j)) {
//                    case NEURON_TYPE::LOGISTIC: {
//                        hid_n = std::make_shared<NeuronLogistic>();
//                        break;
//                    }
//                    case NEURON_TYPE::BINARY: {
//                        hid_n = std::make_shared<NeuronBinary>();
//                        break;
//                    }
//                    case NEURON_TYPE::CONSTANT: {
//                        hid_n = std::make_shared<NeuronConstant>();
//                        break;
//                    }
//                    case NEURON_TYPE::LINEAR: {
//                        hid_n = std::make_shared<NeuronLinear>();
//                        break;
//                    }
//                }
//
//                neuron_idx = this->add_neuron(hid_n, BIAS_TYPE::NEXT_BIAS);
//                new_layer.emplace_back(neuron_idx);
//
//                /* Connect hidden neuron to the previous layer */
//                for(auto prev_n : previous_layer) {
//                    this->add_connection_simple(prev_n, neuron_idx, SIMPLE_CONNECTION_TYPE::NEXT_WEIGHT);
//                }
//                previous_layer = new_layer;
//                new_layer.clear();
//            }
//        }

        /* Create output neurons for sub-net */
        std::shared_ptr<NeuronLinear> sub_out_n = std::make_shared<NeuronLinear>();
        neuron_idx = this->add_neuron(sub_out_n, BIAS_TYPE::NO_BIAS);
        subnet_outputs.emplace_back(neuron_idx);
        for(auto prev_n : previous_layer) {
            this->add_connection_simple(prev_n, neuron_idx);
        }
    }

    /* Specify network inputs */
    this->specify_input_neurons(inputs);

    /* Create final output layer */
    std::shared_ptr<NeuronLinear> final_out_n = std::make_shared<NeuronLinear>();
    neuron_idx = this->add_neuron(final_out_n, BIAS_TYPE::NO_BIAS);
    for(auto subnet_output : subnet_outputs) {
        this->add_connection_constant(subnet_output, neuron_idx, 1);
    }
    std::vector<size_t> outputs = {neuron_idx};
    this->specify_output_neurons(outputs);
}