#ifndef NEURAL_NETWORK_H
#define	NEURAL_NETWORK_H

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#define MLP_TF_SIGMOID 0
#define MLP_TF_SIGMOID_SYMMETRIC 1
#define MLP_TF_LINEAR 2

typedef struct MLP {
  double ***weights;
  unsigned int *neurons;
  unsigned int layers;
  double **vals;
} mlp;

// Funkce

/*
 * Alokuje strukturu MLP s L vrstvami a N[0..L] poctem neuronu v kazde vrstve.
 * N[0] je vstupni vrstva a N[L-1] je vystupni vrstva. L musi byt vetsi nebo
 * rovno 2. TF[0..L] znaci jaka je v dane vrstve prenosova funkce.
 */
mlp * mlp_alloc(unsigned int layers, unsigned int * n);

/*
 * Uvolni z pameti strukturu MLP.
 */
void mlp_free(mlp * net);

/*
 * Klonuje neuronovou sit.
 */
mlp *mlp_clone(mlp *net);

/*
 * Alokuju pamet po vahy neuronove site NET a vrati na ne ukazatel.
 */
double * * * mlp_weights_alloc(mlp * net);

/*
 * Uvolnim z pameti vahy WEIGHTS, ktere jsou vytvoreny pro neuronovou sit NET.
 */
void mlp_weights_free(double * * * weights, mlp * net);

/*
 * Vrati pocet vstupu neuronove site NET.
 */
unsigned int mlp_get_num_inputs(mlp * net);

/*
 * Vrati pocet vystupu neuronove site NET.
 */
unsigned int mlp_get_num_outputs(mlp * net);

/*
 * Vrati pocet neuronu site NET z vrstvy I.
 */
unsigned int mlp_get_neurons (mlp * net, unsigned int i);

/*
 * Vrati pocet vrstev zahrujici vstupnii vystupni vrstvu site NET.
 */
unsigned int mlp_get_num_layers (mlp * net);

/*
 * Nastavi vahu I-teho neuronu na L-te vrstve do J-teho neuronu na nasledujici
 * vrstve site NET.
 */
void mlp_set_weight(mlp * net, unsigned int l, unsigned int i, unsigned int j, double value);

/*
 * Vrati vahu z I-teho neuronu na L-te vrstve do J-teho neuronu na nasledujici
 * vrstve site NET.
 */
double mlp_get_weight(mlp * net, unsigned int l, unsigned int i, unsigned int j);

/*
 * Vynuluje vsechny vahy WEIGHTS. Informace o poctu vrstev a neuronu je ulozena
 * v neuronove siti NET.
 */
void mlp_zeros_weights(mlp * net, double * * * weights);

/*
 * Inicializuje hodnoty vah neuronove site NET pomoci generatoru nahodnych ciel
 * v intervalu < - D ; + D >.
 */
void mlp_weight_init(mlp * net, double d);

/*
 * Vrati vystupni vektor site NET na vstup PATERN.
 */
void mlp_run(mlp * net, double * x, double * y);

/*
 * Vypise vsechyn synapticke spojjeni neuronove site NET.
 */
void mlp_print_weight(mlp * net);

/*
 * Vrati celkovy pocet synaptickych spojeni.
 */
unsigned long mlp_get_total_connections(mlp * net);

/*
 * Uloží neuronovou sit NET do souboru FILE
 */
int mlp_save(mlp * net, const char * file);

/*
 * Nacte ze souboru FILE neuronovou sit a vrati na ni ukazatel
 */
mlp * mlp_load(const char * file);


// Aktivacni funkce
double mlp_sigmoid(double x);

#endif

