// - - - - - - - - - - - - - - - - - - - - - - - - - - -
// File: neuralnetwork.h                                |
// Purpose: provides interface for class NeuralNetwork  |
// Author: Taivo Lints, Estonia                         |
// Date: May, 2003                                      |
// Copyright: see copyright.txt                         |
// - - - - - - - - - - - - - - - - - - - - - - - - - - -

#ifndef NEURALNETWORK_H
#define NEURALNETWORK_H

#include "neuron.h"
#include <vector>
using namespace std;

class NeuralNetwork {  // Represents a typical multilayered feedforward
                       // artificial neural network. Uses backpropagation
                       // for training.
                       
                       // I am currently not supporting modifying the
                       // structure of already generated network. It would
                       // be useful when you want to create/edit the network
                       // node by node with mouse in a graphical environment,
                       // so it may be supported in the future...

                       // By the way, it would probably be a brilliant idea
                       // to create a network that modifies structure ITSELF
                       // at runtime, but then it shouldn't be such a simple
                       // layered feedforward network :)
   public:

     // ******************************
     // * Construction & Destruction *
     // ******************************

     NeuralNetwork(char* config_file);  
                  // NeuralNetwork constructor. Creates a network from your
                  // configuration file. If file not found, then you will get
                  // an empty network. You can check it by calling
                  // get_number_of_layers(). It will be zero when network is
                  // empty.

     NeuralNetwork(const NeuralNetwork& rN);  // NeuralNetwork copy-constructor.

     NeuralNetwork& operator=(const NeuralNetwork& rN); // Operator overloading.

     ~NeuralNetwork(); // NeuralNetwork destructor.


     // *********************************************
     // * Functions for getting general information *
     // *********************************************

     int get_number_of_inputs();   // Returns the number of input nodes.
     int get_number_of_outputs();  // Returns the number of output nodes.
     int get_number_of_layers();   // Returns the number of layers, including
                                   // the input layer (which is made of buffer
                                   // nodes, not real neurons).

     int get_number_of_nodes();    // Returns the total number of nodes,
                                   // including input nodes.


     // ************************************************
     // * Functions for setting some neuron parameters *
     // ************************************************

     // Normally you don't need to use them, just give
     // these parameters in training configuration file,
     // or don't give them at all, then default values are used.

     void set_treshold(double treshold);
                                   // Sets treshold value in all neurons
                                   // (see "neuron.h" for more information).

     void set_slope_parameter(double slope_parameter);
                                   // Sets slope_parameter value in all neurons.
                                   // (see "neuron.h" for more information).
                                   

     // ******************************************
     // * Functions for basic use of the network *
     // ******************************************

     bool set_inputs(vector<double>* v_dbl_inputvalues); // Sets network inputs.
                                   // Returns false if size of given input
                                   // vector is incorrect.

     void update();                // Updates the network (calls update() for
                                   // all neurons).

     void get_outputs(vector<double>* vp_outputs); // Writes network outputs
                                   // into given vector. If vector size
                                   // is incorrect, will fix it.


     // *************************************************
     // * A useful class for storing a training pattern *
     // *************************************************

     // Normally you don't need to use it, just give
     // your patterns in training configuration file.

     class Pattern {  // A useful class for storing one training pattern.
                      // As you see, this is just a class, not an object.
                      // There is a private vector vPatterns containing
                      // Pattern objects (see somewhere below). That vector
                      // is normally filled by train() function, but if you
                      // want to do it manually with add_training_pattern()
                      // from outside code, then you can create a pattern
                      // object this way:

                      // NeuralNetwork::Pattern myPattern;

       public:

         vector<double> vInputs;   // Input values for all input nodes (starting
                                   // from the first in vpNeurons).

         vector<double> vOutputs;  // Desired output values (in the same order
                                   // as output nodes in vpNeurons).
     };


     // ****************************
     // * Some training parameters *
     // ****************************

     // Normally you don't need to set them, just give
     // these parameters in training configuration file,
     // or don't give them at all, then default values are used.
     
     double error_limit;         // For evaluating the success of training.
                                 // If all outputs are in a range from
                                 // (desired_output - error_limit) to
                                 // (desired_output + error_limit), then
                                 // training is completed.

     int max_iterations;         // Maximum allowed number of training
                                 // iterations (epochs). When this number
                                 // of iterations is reached, training
                                 // will be stopped and is failed (i.e.
                                 // outputs were still outside the given
                                 // error limits).


     // **************************************************************
     // * Functions for setting other training parameters & patterns *
     // **************************************************************

     // Normally you don't need to use them, just give these parameters
     // in training configuration file, or don't give them at all,
     // then default values are used. Patterns, unlike parameters,
     // do NOT have default values, so they should be present in training
     // configuration file if you want to train the network (or if you
     // really want to set them manually, then use these functions).
     
     void set_learning_rate(double learning_rate);
                                   // Sets learning rate in all neurons.
                                   // (see "neuron.h" for more information).

     void set_max_weight(double max_weight);
                                   // Sets max_weight value in all neurons
                                   // (see "neuron.h" for more information).

     void add_training_pattern(Pattern myPattern);
                                   // Adds a training pattern to vPatterns
                                   // (see somewhere below).

     bool verify_all_patterns();   // Verifies that the number of input and
                                   // output values in all patterns is
                                   // correct (e.g. if you have two input
                                   // neurons in your network, then every
                                   // pattern must hold two input values,
                                   // i.e. the size of vInputs vector must be
                                   // two). Returns "true" if all OK.

                                   // When you add training patterns manually,
                                   // please USE this function before calling
                                   // train(NULL) and do NOT call train(NULL)
                                   // if something is wrong, otherwise the
                                   // program may crash.

     void erase_all_patterns();    // Deletes all training patterns.

     int get_number_of_patterns(); // Returns the number of training patterns
                                   // in vPatterns vector.


     // **************************
     // * Functions for training *
     // **************************

     int train(char* training_file);
                 // Trains network using backpropagation algorithm. Returns 0,
                 // if training successful; returns 1, if goal not reached;
                 // returns 2, if problems with patterns. Also sets iterations
                 // parameter (see the next section below). Gets information
                 // from a file. Example: train("trainingfile.txt")

                 // If you have fiddled something manually and don't want to
                 // use training file, then call train(NULL), because
                 // otherwise all your patterns will be deleted.


     // ***********************************
     // * Some information about training *
     // ***********************************

     int iterations;  // Train() function writes here the number of training
                      // iterations (epochs) that it had to go through before
                      // reaching the goal (if goal was not reached, then
                      // iterations = max_iterations).

     // ************************************
     // * Functions for saving the network *
     // ************************************

     void save_network(char* savefile);  // Saves your network into a file.
                 // Example: save_network("configuration_generated.txt")
                 // You can use this generated file for initializing a
                 // new network (instead of the usual configuration file,
                 // where weights are not described).


     // ************************************************
     // * Functions for getting some neuron parameters *
     // ************************************************

     // All these functions assume, that all neurons have similar
     // parameters. So they just use values taken from the first
     // neuron in vpNeurons vector (which is actually an input node,
     // but still should have all these parameters set correctly).
     // If network is empty, then all these functions return 0.

     double get_treshold();
     double get_slope_parameter();
     double get_learning_rate();
     double get_max_weight();   // Returns the value of parameter max_weight,
                                // NOT the maximum weight found in network!


   // *******************
   // * Protected stuff *
   // *******************

   // You can't use that stuff from outside code, except from child classes.

   protected:

     vector<Neuron*> vpNeurons;    // Vector of pointers to neurons. This is
                                   // the actual "implementation" of network.
                                   // Vector allows array style indexing
                                   // and thus makes it easier to describe
                                   // connections between neurons (I can say:
                                   // "This neuron is connected to a neuron
                                   // number 7," meaning vpNeurons[7]).

     vector<int> v_int_layers;     // Contains information about how many
                                   // nodes there are in each layer, starting
                                   // from the input layer.

     vector<Pattern> vPatterns;    // Vector of training patterns.

     void load_config_file(char* config_file);
                                   // Loads info from configuration file.
                                   // Is used by constructor. Does not
                                   // guarantee anything and should be used
                                   // carefully.

     void create_unset_connections();  // Creates missing connections so that
                                   // network will be a fully connected multi-
                                   // layer feedforward network. Is used by
                                   // constructor.

     int load_training_file(char* training_file);
                                   // Loads info from training file. Is used
                                   // by train() function. Returns the number
                                   // of loading errors.

};

#endif // NEURALNETWORK_H