Skip to content
Snippets Groups Projects
ACSFNeuralNetwork.cpp 7.36 KiB
Newer Older
  • Learn to ignore specific revisions
  • //
    // 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_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 {
                        neuron_idx = this->add_neuron(hid_n,
                                                      BIAS_TYPE::EXISTING_BIAS, subnet_neuron_idxs[elements_list.at(i)].at(0)+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);
    }