public DeconvolutionLayer(UpSamplingLayer prev_upsampling_l, ConvolutionLayer base_convolution_layer)
        {
            this.feature_maps_number = prev_upsampling_l.feature_maps_number;
            this.feature_maps        = new List <DeconvolutionFeatureMap>();
            this.inputs     = new List <float[, ]>();
            this.avg_inputs = new List <float[, ]>();
            this.proportion = prev_upsampling_l.feature_maps_number / base_convolution_layer.feature_maps_number;

            this.kwidth  = base_convolution_layer.kwidth;
            this.kheight = base_convolution_layer.kheight;
            //boundaries effect
            this.map_width  = kwidth + base_convolution_layer.map_width - 1;
            this.map_height = kheight + base_convolution_layer.map_height - 1;
            this.inp_w      = prev_upsampling_l.outputwidth;
            this.inp_h      = prev_upsampling_l.outputwidth;
            //create kernels
            //previous layer must contain more feature maps or same number of feature maps
            for (int k = 0; k < base_convolution_layer.feature_maps_number; k++)
            {
                avg_inputs.Add(new float[inp_w, inp_h]);
                feature_maps.Add(new DeconvolutionFeatureMap(avg_inputs[k], base_convolution_layer.feature_maps[k]));
            }
            for (int k = 0; k < prev_upsampling_l.feature_maps_number; k++)
            {
                inputs.Add(prev_upsampling_l.feature_maps[k].output);
            }
        }
 public void set_link_with_conv_next_layer(ConvolutionLayer next_layer, int currentLayerMapId, List <int> connectedMapsIds)
 {
     for (int i = 0; i < connectedMapsIds.Count; i++)
     {
         feature_maps[currentLayerMapId].conv_maps_next_layer.Add(next_layer.feature_maps[connectedMapsIds[i]]);
     }
 }
        public SubsamplingLayer(ConvolutionLayer prev_conv_layer)
        {
            this.feature_maps_number = prev_conv_layer.feature_maps_number;
            bj           = new float[feature_maps_number];
            aj           = new float[feature_maps_number];
            this.inputs  = new List <float[, ]>();
            this.outputs = new List <float[, ]>();
            //full connecntion
            for (int j = 0; j < feature_maps_number; j++)
            {
                this.inputs.Add(prev_conv_layer.feature_maps[j].output);
            }
            this.inputw = prev_conv_layer.map_width;
            this.inputh = prev_conv_layer.map_height;

            this.feature_maps = new List <SubSampleFeatureMap>();
            this.errors       = new List <float[, ]>();
            //compression koef=2
            //"valid" boundary mode
            this.outputwidth  = inputw / 2;
            this.outputheight = inputh / 2;

            for (int j = 0; j < feature_maps_number; j++)
            {   //aj=bj=1 initially
                bj[j]      = 0.01f;
                this.aj[j] = 1;
                feature_maps.Add(new SubSampleFeatureMap(inputw, inputh, outputwidth, outputheight, inputs[j]));
                errors.Add(new float[outputwidth, outputheight]);
            }
        }
 public static void save_output_to_file(string name, ConvolutionLayer layer)
 {
     for (int k = 0; k < layer.feature_maps_number; k++)
     {
         save_matrix_to_file(name + " feature map " + k.ToString() + " ", layer.feature_maps[k].output, layer.map_width, layer.map_height);
     }
 }
 public void getError(ConvolutionLayer next_layer)
 {
     //GETTING ERROR FROM NEXT CONVOLUTINAL LAYER!
     for (int j = 0; j < feature_maps.Count; j++)
     {
         // feature_maps[j].get_map_error_from_convolution();
         errors[j] = feature_maps[j].error;
         bj[j]     = feature_maps[j].b;
     }
 }
        public ConvolutionLayer(ConvolutionLayer prev_convolution, int k_w, int k_h)
        {
            //default value
            this.next_l_type         = "convolution";
            this.feature_maps_number = prev_convolution.feature_maps_number;
            this.bj = new float[this.feature_maps_number];
            //bj=1 initially
            for (int j = 0; j < this.feature_maps_number; j++)
            {
                bj[j] = 0.01f;
            }
            this.feature_maps = new List <ConvolutionFeatureMap>();
            this.errors       = new List <float[, ]>();
            this.kwidth       = k_w;
            this.kheight      = k_h;
            //if filter<map =>"valid" bounadary mode, else - full-mode
            this.map_width  = prev_convolution.map_width;
            this.map_height = prev_convolution.map_height;
            if (this.map_width > kwidth)
            {
                this.map_width = -(kwidth - 1);
            }
            if (this.map_height > kheight)
            {
                this.map_height -= (kheight - 1);
            }

            //create kernels
            for (int k = 0; k < feature_maps_number; k++)
            {
                ConvolutionFeatureMap fm = new ConvolutionFeatureMap(kwidth, kheight, map_width, map_height);
                MatrixOperations.init_matrix_random(fm.weights, kwidth, kheight);
                feature_maps.Add(fm);

                errors.Add(new float[map_width, map_height]);
            }
            //link with previous layer
            //all-to-all connection

            for (int i = 0; i < this.feature_maps_number; i++)
            {   //link prev layers output
                this.feature_maps[i].add_input_full_connection(prev_convolution.feature_maps[i].output);
                //link this error input path
            }
        }
        //input is a picture's matrix
        public Network(int input_w, int input_h, int FL_feature_maps_number,
                       int fl_kw, int fl_kh, int SL_feature_maps_number, int sl_kw, int sl_kh)
        {
            this.FL_feature_maps_number = FL_feature_maps_number;
            this.SL_feature_maps_number = SL_feature_maps_number;

            //create first convolutional layer(first layer)
            FirstLayer = new ConvolutionLayer(FL_feature_maps_number, fl_kw, fl_kh, input_w, input_h);

            //first subsampling layer(second layer)
            SecondLayer = new SubsamplingLayer(FirstLayer);

            //second convolutional layer(third layer).Consists of number of convolutional layers
            ThirdLayer = new ConvolutionLayer(SL_feature_maps_number, sl_kw, sl_kh, SecondLayer.outputwidth, SecondLayer.outputheight);
            //connect inputs with previous layer
            //Parallel conctruction (like RGB) 2 cards of new layer for 1 card of previous layer
            //like 6/3 = 2
            //set topology for second layer
            List <int> topology = new List <int>();
            int        counter  = 0;

            for (int i = 0; i < FL_feature_maps_number; i++)
            {
                for (int j = 0; j < SL_feature_maps_number / FL_feature_maps_number; j++)
                {
                    topology.Add(counter);
                    counter++;
                }
                SecondLayer.set_link_with_conv_next_layer(ThirdLayer, i, topology);
                topology.Clear();
            }

            //set topology for third layer
            for (int i = 0; i < SL_feature_maps_number; i++)
            {
                int nextid = i * FL_feature_maps_number / SL_feature_maps_number;
                ThirdLayer.feature_maps[i].add_input_full_connection(SecondLayer.feature_maps[nextid].output);
            }



/*
 *          //all-to-all connection
 *          List<int> topology = new List<int>();
 *          for (int i = 0; i < FL_feature_maps_number; i++)
 *          {
 *              for (int j = 0; j < SL_feature_maps_number; j++)
 *              {
 *                  topology.Add(j);
 *              }
 *              SecondLayer.set_link_with_conv_next_layer(ThirdLayer, i, topology);
 *              topology.Clear();
 *          }
 *
 *          //set topology for third layer
 *          for (int j = 0; j < ThirdLayer.feature_maps_number; j++)
 *          {
 *              for (int i = 0; i < SecondLayer.feature_maps_number; i++)
 *              {
 *                  ThirdLayer.feature_maps[j].add_input_full_connection(SecondLayer.feature_maps[i].output);
 *              }
 *          }
 */

            FourthLayer = new SubsamplingLayer(ThirdLayer);

            FifthLayer   = new UpSamplingLayer(FourthLayer);
            SixthLayer   = new DeconvolutionLayer(FifthLayer, ThirdLayer);
            SeventhLayer = new UpSamplingLayer(SixthLayer, SecondLayer.feature_maps_number);
            EightsLayer  = new DeconvolutionLayer(SeventhLayer, FirstLayer);
        }