diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1ea507921a4155151d0b757eaddd975562368767..0d83c68044266fd10dc2131c4af68dc86fa74511 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,7 +22,7 @@ if (NOT CMAKE_BUILD_TYPE)
          "Choose the type of build, options are: None Debug Release."
          FORCE)
 elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
-    #TODO rewrite to use add_compile_definitions
+    add_compile_definitions("L4N_DEBUG")
 endif (NOT CMAKE_BUILD_TYPE)
 
 #------------------------#
diff --git a/build_scripts/linux/clean_dependencies.sh b/build_scripts/linux/clean_dependencies.sh
index 3b4ead63bb41002d099ab633e7c62349c5ee8cb7..1bbae3c794a4ee4ddee92fab1fcbcce8b7385abe 100755
--- a/build_scripts/linux/clean_dependencies.sh
+++ b/build_scripts/linux/clean_dependencies.sh
@@ -1,4 +1,5 @@
 #!/bin/sh
 
-rm ../../external_dependencies/boost/*
-rm ../../external_dependencies/exprtk/*
+rm -rf ../../external_dependencies/boost/*
+rm -rf ../../external_dependencies/exprtk/*
+rm -rf ../../external_dependencies/turtle/*
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5d018c5c95c68ee42a757c69ec576f21e0c966f0..0b8c2abc63f633246f87d1ed999fc5bd5025a11e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -49,6 +49,7 @@ if ("${BUILD_LIB}" STREQUAL "yes")
 		Exception/Exceptions.cpp
 		CSVReader/CSVReader.cpp
 		CrossValidator/CrossValidator.cpp
+		NormalizationStrategy/NormalizationStrategy.cpp
 	)
 
     target_link_libraries(
diff --git a/src/CrossValidator/CrossValidator.cpp b/src/CrossValidator/CrossValidator.cpp
index 373ec7aa8ba87e9858af4e524f1f1ead58ef6cf8..6be29fca98a78cbc9549216ed673b1b59ce3a0e5 100644
--- a/src/CrossValidator/CrossValidator.cpp
+++ b/src/CrossValidator/CrossValidator.cpp
@@ -12,14 +12,13 @@ namespace lib4neuro {
     }
 
     LIB4NEURO_API void CrossValidator::run_k_fold_test(unsigned int k, unsigned int tests_number) {
-
         NeuralNetwork *net = this->ef->get_network_instance();
 
         for(unsigned int i = 0; i < tests_number; i++) {
-            std::cout << "Cross-validation run " << i+1 << std::endl;
+            COUT_DEBUG(<< "Cross-validation run " << i+1 << std::endl);
 
             this->ef->divide_data_train_test(1.0/k);
-            std::cout << "Cross-validation run " << i+1 << ", number of train data points: " << this->ef->get_dataset()->get_n_elements() << std::endl;
+            COUT_DEBUG(<< "number of train data points: " << this->ef->get_dataset()->get_n_elements() << std::endl);
 
             net->print_weights();
             net->randomize_parameters();
diff --git a/src/DataSet/DataSet.cpp b/src/DataSet/DataSet.cpp
index 83403f8c524aece678cc9aec6f71f4e940313426..35ddee5c5ad4d95092d32cabddc69e01487ba470 100644
--- a/src/DataSet/DataSet.cpp
+++ b/src/DataSet/DataSet.cpp
@@ -2,12 +2,17 @@
 // Created by martin on 7/13/18.
 //
 
+#include <algorithm>
 
 #include "DataSetSerialization.h"
 
 namespace lib4neuro {
 
-    DataSet::DataSet() {}
+    DataSet::DataSet() {
+        this->n_elements = 0;
+        this->input_dim = 0;
+        this->output_dim = 0;
+    }
 
     DataSet::DataSet(std::string file_path) {
         std::ifstream ifs(file_path);
@@ -47,7 +52,6 @@ namespace lib4neuro {
         this->add_isotropic_data(bounds, no_elems_in_one_dim, output_func);
     }
 
-
     void DataSet::add_data_pair(std::vector<double> &inputs, std::vector<double> &outputs) {
         if(this->n_elements == 0 && this->input_dim == 0 && this->output_dim == 0) {
             this->input_dim = inputs.size();
@@ -184,4 +188,44 @@ namespace lib4neuro {
         return v_combined;
     }
 
+    void DataSet::normalize() {
+        /* Find maximum and minimum values */
+        this->max_inp_val =  this->min_inp_val = this->data[0].first.at(0);
+        double tmp, tmp2;
+        for(auto pair : this->data) {
+            /* Finding maximum */
+            //TODO make more efficiently
+            tmp = *std::max_element(pair.first.begin(), pair.first.end());
+            tmp2 = *std::max_element(pair.second.begin(), pair.second.end());
+
+            tmp = std::max(tmp, tmp2);
+
+            if (tmp > this->max_inp_val) {
+                this->max_inp_val = tmp;
+            }
+
+            /* Finding minimum */
+            tmp = *std::min_element(pair.first.begin(), pair.first.end());
+            tmp2 = *std::min_element(pair.second.begin(), pair.second.end());
+
+            tmp = std::min(tmp, tmp2);
+
+            if (tmp < this->min_inp_val) {
+                this->min_inp_val = tmp;
+            }
+        }
+
+        /* Normalize every number in the data set */
+        for(auto& pair : this->data) {
+            for(auto& v : pair.first) {
+                v = normalization_strategy->normalize(v, this->max_inp_val, this->min_inp_val);
+            }
+
+            for(auto& v : pair.second) {
+                v = normalization_strategy->normalize(v, this->max_inp_val, this->min_inp_val);
+            }
+        }
+
+    }
+
 }
\ No newline at end of file
diff --git a/src/DataSet/DataSet.h b/src/DataSet/DataSet.h
index d31762c992d57ae91b2521c9da1e3b351222dd22..b12e4f5634e4096943a35a07924290868d1c0963 100644
--- a/src/DataSet/DataSet.h
+++ b/src/DataSet/DataSet.h
@@ -14,6 +14,7 @@
 
 #include "../settings.h"
 #include "../Exception/Exceptions.h"
+#include "../NormalizationStrategy/NormalizationStrategy.h"
 
 namespace lib4neuro {
     /**
@@ -39,6 +40,16 @@ namespace lib4neuro {
          */
         size_t output_dim = 0;
 
+        /**
+         * Maximum input value
+         */
+        double max_inp_val;
+
+        /**
+         * Minimum input value
+         */
+        double min_inp_val;
+
         /**
          * Stored data in the format of pairs of corresponding
          * input and output vectors
@@ -48,6 +59,13 @@ namespace lib4neuro {
         template<class T>
         std::vector<std::vector<T>> cartesian_product(const std::vector<std::vector<T>> *v);
 
+        /**
+         *
+         */
+         //TODO let user choose in the constructor!
+        NormalizationStrategy* normalization_strategy = new DoubleUnitStrategy;
+
+
     public:
 
         /**
@@ -171,6 +189,14 @@ namespace lib4neuro {
          * Stores the DataSet object to the binary file
          */
         LIB4NEURO_API void store_text(std::string &file_path);
+
+        /**
+         * Normalizes the data set into [-1,1] interval
+         *
+         * Former maximum and minimum values are stored into the
+         * private variables max_inp_val and min_inp_val
+         */
+        LIB4NEURO_API void normalize();
     };
 }
 #endif //INC_4NEURO_DATASET_H
diff --git a/src/ErrorFunction/ErrorFunctions.cpp b/src/ErrorFunction/ErrorFunctions.cpp
index 164b375b8f3141a7aa08d29c581aa106cb3b14b8..394ba231c8c4d9543857b92ae4b5297d61ba431a 100644
--- a/src/ErrorFunction/ErrorFunctions.cpp
+++ b/src/ErrorFunction/ErrorFunctions.cpp
@@ -30,7 +30,6 @@ namespace lib4neuro {
         boost::random::uniform_int_distribution<> dist(0, ds_size - 1);
 
         size_t test_set_size = ceil(ds_size * percent_test);
-        printf("new train set size: %d\n", test_set_size);
 
         std::vector<unsigned int> test_indices;
         test_indices.reserve(test_set_size);
@@ -115,6 +114,9 @@ namespace lib4neuro {
 
         for (auto el: *data) {  // Iterate through every element in the test set
 
+            /* Input normalization to [0,1] interval */
+            //TODO
+
             this->net->eval_single(el.first, error_derivative,
                                    &params);  // Compute the net output and store it into 'output' variable
 
diff --git a/src/Network/NeuralNetwork.cpp b/src/Network/NeuralNetwork.cpp
index 94c8d4889ce3ad05b1dfb145a09fc58519038746..06606068bb47b6b0dc0f8a3dc5a38ab6579db879 100644
--- a/src/Network/NeuralNetwork.cpp
+++ b/src/Network/NeuralNetwork.cpp
@@ -12,8 +12,6 @@
 #include "NeuralNetwork.h"
 #include "NeuralNetworkSerialization.h"
 
-/* Seed for the random number generator */
-boost::random::mt19937 gen;
 
 namespace lib4neuro {
     NeuralNetwork::NeuralNetwork() {
@@ -595,7 +593,7 @@ namespace lib4neuro {
 
     void NeuralNetwork::randomize_weights() {
 
-//        boost::random::mt19937 gen;
+        boost::random::mt19937 gen(std::time(0));
 
         // Init weight guess ("optimal" for logistic activation functions)
         double r = 4 * sqrt(6. / (this->connection_weights->size()));
@@ -609,7 +607,7 @@ namespace lib4neuro {
 
     void NeuralNetwork::randomize_biases() {
 
-//        boost::random::mt19937 gen;
+        boost::random::mt19937 gen(std::time(0));
 
         // Init weight guess ("optimal" for logistic activation functions)
         boost::random::uniform_real_distribution<> dist(-1, 1);
@@ -911,8 +909,9 @@ namespace lib4neuro {
         unsigned int inp_dim = neuron_numbers->at(0);  //!< Network input dimension
         unsigned int out_dim = neuron_numbers->back(); //!< Network output dimension
 
-        printf("# of inputs: %d\n", inp_dim);
-        printf("# of outputs: %d\n", out_dim);
+        COUT_DEBUG(<< "Fully connected feed-forward network:" << std::endl)
+        COUT_DEBUG(<< "# of inputs: " << inp_dim << std::endl);
+        COUT_DEBUG(<< "# of outputs: " << out_dim << std::endl);
 
         std::vector<size_t> input_layer_neuron_indices;
         std::vector<size_t> previous_layer_neuron_indices;
diff --git a/src/Network/NeuralNetwork.h b/src/Network/NeuralNetwork.h
index 223aa26ce435d78eb97f88d148649ac80b820273..02c5b3408377d73b6d5d895e881fd5c55485e193 100644
--- a/src/Network/NeuralNetwork.h
+++ b/src/Network/NeuralNetwork.h
@@ -205,8 +205,6 @@ namespace lib4neuro {
         LIB4NEURO_API virtual void eval_single(std::vector<double> &input, std::vector<double> &output,
                                                std::vector<double> *custom_weights_and_biases = nullptr);
 
-
-
         /**
          *
          * @param error_derivative
diff --git a/src/Neuron/Neuron.h b/src/Neuron/Neuron.h
index fd81dde8aef8eb6be179f34e133fc338d8c99ac8..fb8142d4223c7c7953b36ad5ad9fd443488c1334 100644
--- a/src/Neuron/Neuron.h
+++ b/src/Neuron/Neuron.h
@@ -15,7 +15,7 @@
 
 namespace lib4neuro {
 
-    enum NeuronType {
+    enum NEURON_TYPE {
         BINARY,
         CONSTANT,
         LINEAR,
diff --git a/src/Neuron/NeuronLogistic.cpp b/src/Neuron/NeuronLogistic.cpp
index 1af9fde526e7821d78305582b712f0fe691cb61e..b9dcca793f7d9c6acdde5cf0b0ffaf6ab6df3793 100644
--- a/src/Neuron/NeuronLogistic.cpp
+++ b/src/Neuron/NeuronLogistic.cpp
@@ -97,9 +97,21 @@ namespace lib4neuro {
     double NeuronLogistic::activation_function_eval_derivative_bias(double x, double b) {
         //-e^(b - x)/(e^(b - x) + 1)^2
         double ex = std::pow(E, b - x);
+//        if(std::isinf(ex)) {
+//            ex = 10e35;
+//        }
+
         double denom = (ex + 1);
 
-        return -ex / (denom * denom);
+        double res = -ex / (denom * denom);
+
+//        if(std::isnan(res)) {
+//            throw std::runtime_error("Derivative results in NeuronLogistic is NaN!");
+//        } else if (std::abs(res) < 10e-8) {
+//            res = 0;
+//        }
+
+        return res;
     }
 
 
diff --git a/src/NormalizationStrategy/NormalizationStrategy.cpp b/src/NormalizationStrategy/NormalizationStrategy.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7e83d15ff683bfeea17bb820d2863a2854557b7d
--- /dev/null
+++ b/src/NormalizationStrategy/NormalizationStrategy.cpp
@@ -0,0 +1,11 @@
+//
+// Created by martin on 21.11.18.
+//
+
+#include "NormalizationStrategy.h"
+
+DoubleUnitStrategy::DoubleUnitStrategy() {}
+
+double DoubleUnitStrategy::normalize(double n, double max, double min) {
+    return 2*(n - min)/(max - min) - 1;
+}
\ No newline at end of file
diff --git a/src/NormalizationStrategy/NormalizationStrategy.h b/src/NormalizationStrategy/NormalizationStrategy.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec7548cad5166517844df07960b16175830af8d4
--- /dev/null
+++ b/src/NormalizationStrategy/NormalizationStrategy.h
@@ -0,0 +1,28 @@
+//
+// Created by martin on 21.11.18.
+//
+
+#ifndef LIB4NEURO_NORMALIZATIONSTRATEGY_H
+#define LIB4NEURO_NORMALIZATIONSTRATEGY_H
+
+class NormalizationStrategy {
+public:
+    virtual double normalize(double n, double max, double min) = 0;
+};
+
+class DoubleUnitStrategy : public NormalizationStrategy {
+public:
+    DoubleUnitStrategy();
+
+    /**
+     * Normalizes the input value to the interval [-1,1]
+     *
+     * @param n
+     * @param max
+     * @param min
+     * @return
+     */
+    double normalize(double n, double max, double min) override;
+};
+
+#endif //LIB4NEURO_NORMALIZATIONSTRATEGY_H
diff --git a/src/examples/main.cpp b/src/examples/main.cpp
index 5c766604a55e579be9cee8a94e103291c63ce6d0..b8d4580f84f48697389504d0a0575956de56a728 100644
--- a/src/examples/main.cpp
+++ b/src/examples/main.cpp
@@ -17,18 +17,21 @@
 
 int main(int argc, char** argv){
 
+    /* Read data from the file */
     l4n::CSVReader reader("/home/martin/Desktop/ANN_DATA_1_SET.txt", "\t", true);
     reader.read();
 
-//    std::vector<std::vector<std::string>>* data = reader.get_data();
-
+    /* Create data set for both the training and testing of the neural network */
     std::vector<unsigned int> inputs = {2,3,4,5,6,7,8,26,27,28};
     std::vector<unsigned int> outputs = {17,18,19,20,21,22,23,24,25};
     l4n::DataSet ds = reader.get_data_set(&inputs, &outputs);
 
+    /* Normalize data in the set for easier training of the network */
+    ds.normalize();
+
     /* Neural network construction */
-    std::vector<unsigned int> neuron_numbers_in_layers = {10,9};
-    l4n::FullyConnectedFFN nn(&neuron_numbers_in_layers, l4n::NeuronType::LOGISTIC);
+    std::vector<unsigned int> neuron_numbers_in_layers = {10,10,10,9};
+    l4n::FullyConnectedFFN nn(&neuron_numbers_in_layers, l4n::NEURON_TYPE::LOGISTIC);
 
     /* Error function */
     l4n::MSE mse(&nn, &ds);
@@ -36,17 +39,38 @@ int main(int argc, char** argv){
     /* Domain */
     std::vector<double> domain_bounds(2 * (nn.get_n_weights() + nn.get_n_biases()));
 
-    for(size_t i = 0; i < domain_bounds.size() / 2; ++i){
-        domain_bounds[2 * i] = -20;
-        domain_bounds[2 * i + 1] = 20;
-    }
     /* Training method */
-//    l4n::ParticleSwarm ps(&domain_bounds);
-    l4n::GradientDescent gs;
+//    for(size_t i = 0; i < domain_bounds.size() / 2; ++i){
+//        domain_bounds[2 * i] = -10;
+//        domain_bounds[2 * i + 1] = 10;
+//    }
+//    l4n::ParticleSwarm ps(&domain_bounds,
+//                          1.711897,
+//                          1.711897,
+//                          0.711897,
+//                          0.5,
+//                          20,
+//                          0.7,
+//                          600,
+//                          1000);
+    l4n::GradientDescent gs(1e-3, 1);
+
+    nn.randomize_weights();
 
     /* Cross - validation */
     l4n::CrossValidator cv(&gs, &mse);
     cv.run_k_fold_test(10, 3);
 
+    /* Save network to the file */
+    nn.save_text("test_net.4n");
+
+    /* Check of the saved network */
+    std::cout << "The original network info:" << std::endl;
+    nn.print_stats();
+
+    l4n::NeuralNetwork nn_loaded("test_net.4n");
+    std::cout << "The loaded network info:" << std::endl;
+    nn_loaded.print_stats();
+
     return 0;
 }
diff --git a/src/examples/seminar.cpp b/src/examples/seminar.cpp
index 45117e492854bf2c83a1f46a6af9a4b31dd56065..a52a1425b388166a3876bc67bd3093678c6923ee 100644
--- a/src/examples/seminar.cpp
+++ b/src/examples/seminar.cpp
@@ -10,7 +10,6 @@
 #include <fstream>
 
 #include "4neuro.h"
-#include "../Solvers/DESolver.h"
 
 int main() {
 
@@ -18,14 +17,14 @@ int main() {
     std::cout << "********************************************************************************************************************************************" <<std::endl;
 
 
-    NeuralNetwork XOR;
-    unsigned  int i1 = XOR.add_neuron( new NeuronLinear( ), BIAS_TYPE::NO_BIAS );
-    unsigned  int i2 = XOR.add_neuron( new NeuronLinear( ), BIAS_TYPE::NO_BIAS );
+    l4n::NeuralNetwork XOR;
+    unsigned  int i1 = XOR.add_neuron( new l4n::NeuronLinear( ), l4n::BIAS_TYPE::NO_BIAS );
+    unsigned  int i2 = XOR.add_neuron( new l4n::NeuronLinear( ), l4n::BIAS_TYPE::NO_BIAS );
 
-    unsigned  int h1 = XOR.add_neuron( new NeuronLogistic( ) );
-    unsigned  int h2 = XOR.add_neuron( new NeuronLogistic( ) );
+    unsigned  int h1 = XOR.add_neuron( new l4n::NeuronLogistic( ) );
+    unsigned  int h2 = XOR.add_neuron( new l4n::NeuronLogistic( ) );
 
-    unsigned  int o1 = XOR.add_neuron( new NeuronLinear( ), BIAS_TYPE::NO_BIAS );
+    unsigned  int o1 = XOR.add_neuron( new l4n::NeuronLinear( ), l4n::BIAS_TYPE::NO_BIAS );
 
     XOR.add_connection_simple( i1, h1 );
     XOR.add_connection_simple( i2, h1 );
@@ -56,7 +55,7 @@ int main() {
     out = {0};
     data_vec.emplace_back(std::make_pair(inp, out));
 
-    DataSet ds(&data_vec);
+    l4n::DataSet ds(&data_vec);
 
     /* specification of the input/output neurons */
     std::vector<size_t> net_input_neurons_indices(2);
@@ -71,7 +70,7 @@ int main() {
 
 
     /* ERROR FUNCTION SPECIFICATION */
-    MSE mse(&XOR, &ds);
+    l4n::MSE mse(&XOR, &ds);
 
 
 
@@ -98,17 +97,15 @@ int main() {
     double epsilon = 0.02;
     double delta = 0.7;
 
-    ParticleSwarm swarm_01(
-            &domain_bounds,
-            c1,
-            c2,
-            w,
-            gamma,
-            epsilon,
-            delta,
-            n_particles,
-            iter_max
-    );
+    l4n::ParticleSwarm swarm_01(&domain_bounds,
+                                c1,
+                                c2,
+                                w,
+                                gamma,
+                                epsilon,
+                                delta,
+                                n_particles,
+                                iter_max);
     swarm_01.optimize( mse );
 
     std::vector<double> *parameters = swarm_01.get_parameters( );
diff --git a/src/message.h b/src/message.h
index b04fccb24f4abdbdb320d66f0fc735e53e0bff0c..a0f0a05de6e41061e3a43884cf006178c873ee28 100644
--- a/src/message.h
+++ b/src/message.h
@@ -7,7 +7,12 @@
 
 #include <cassert>
 
-#define MSG_INFO(str) std::cout << "INFO: " << str << std::endl;
-#define MSG_DEBUG(str) assert(std::cerr << "DEBUG:" << str << std::endl);
+#define COUT_INFO(inp) std::cout << "INFO: " inp;
+
+#ifdef L4N_DEBUG
+#define COUT_DEBUG(inp) assert(std::cerr << "DEBUG: " inp);
+#else
+#define COUT_DEBUG(inp)
+#endif // L4N_DEBUG
 
 #endif //PROJECT_MESSAGE_H