public NeuralNetworks(int inputNumber, int outputNumber, int hiddenLayerWidth, int hiddenLayerHeight)
        {
            HiddenLayerWeights = new Tensor(hiddenLayerWidth, hiddenLayerHeight, hiddenLayerHeight);
            InputLayerWeights = new Matrix(hiddenLayerHeight, inputNumber);
            OutputLayerWeights = new Matrix(outputNumber, hiddenLayerHeight);

            HiddenLayerNeuron = new Neuron[hiddenLayerWidth, hiddenLayerHeight];
            OutputLayerNeuron = new Neuron[outputNumber];

            InputNumber = inputNumber;
            OutputNumber = outputNumber;
            HiddenLayerWidth = hiddenLayerWidth;
            HiddenLayerHeight = hiddenLayerHeight;

            Random random = new Random();
            //Initialize weights randomly from -1 to 1
            for (int i = 0; i < HiddenLayerWeights.Width; i++)
            {
                for (int j = 0; j < HiddenLayerWeights.Height; j++)
                {
                    for (int k = 0; k < HiddenLayerWeights.Depth; k++)
                    {
                        if (random.Next() % 2 == 0)
                            HiddenLayerWeights[i, j, k] = random.NextDouble();
                        else
                            HiddenLayerWeights[i, j, k] = -random.NextDouble();
                    }
                }
            }
            for (int i = 0; i < hiddenLayerHeight; i++)
            {
                for (int j = 0; j < inputNumber; j++)
                    InputLayerWeights[i, j] = random.NextDouble();
            }
            for (int i = 0; i < outputNumber; i++)
            {
                for (int j = 0; j < hiddenLayerHeight; j++)
                    OutputLayerWeights[i, j] = random.NextDouble();
            }
            //Initialize neurons
            for (int i = 0; i < HiddenLayerWidth; i++)
            {
                for (int j = 0; j < hiddenLayerHeight; j++)
                    HiddenLayerNeuron[i, j] = new Neuron();
            }
            for (int i = 0; i < outputNumber; i++)
                OutputLayerNeuron[i] = new Neuron();
            //Initizlize input as a 0 vector
            LastInput = new Vector(InputNumber);
            for (int i = 0; i < inputNumber; i++)
                LastInput[i] = 0;
        }
 /// <summary>
 /// Return the fired states the column of hidden neurons at given (width) position as a Vector.
 /// 1 if fired, 0 otherwise
 /// </summary>
 /// <param name="position"></param>
 /// <returns></returns>
 public Vector GetHiddenColumnFiredStates(int position)
 {
     Vector vector = new Vector(HiddenLayerHeight);
     for (int i = 0; i < HiddenLayerHeight; i++)
         vector[i] = HiddenLayerNeuron[position, i].Fired ? 1 : 0;
     return vector;
 }
 public static Vector operator *(Matrix one, Vector other)
 {
     if (one.Width != other.Dim)
         throw new Exception("Dim Error");
     Vector newV = new Vector(one.Height);
     for (int i = 0; i < newV.Dim; i++)
         newV[i] = other * one.Row(i);
     return newV;
 }
 /// <summary>
 /// Propagage through the network, a neuron fires if potential >= threshold
 /// </summary>
 /// <param name="input"></param>
 public void ForwardPropagation(Vector input)
 {
     if (input.Dim != InputNumber)
         throw (new Exception("Number of inputs doesn't match, please refer to InputNumber field"));
     LastInput = input;
     if (input.Dim != InputNumber)
         throw new Exception("Input Dimension doesn't match");
     for (int i = 0; i < HiddenLayerHeight; i++)
         HiddenLayerNeuron[0, i].Fire(InputLayerWeights.Row(i) * HiddenLayerWeights[0, i]);
     for (int i = 1; i < HiddenLayerWidth; i++)
     {
         for (int j = 0; j < HiddenLayerHeight; j++)
             HiddenLayerNeuron[i, j].Fire(HiddenLayerWeights[i, j] * GetHiddenColumnFiredStates(i - 1));
     }
     for (int i = 0; i < OutputNumber; i++)
         OutputLayerNeuron[i].Fire(OutputLayerWeights.Row(i) * GetHiddenColumnFiredStates(HiddenLayerWidth - 1));
 }
 public static Vector operator -(Vector one, Vector other)
 {
     if (one.Dim != other.Dim)
         throw new Exception("Vector lengths aren't the same");
     Vector newV = new Vector(one);
     for (int i = 0; i < other.Dim; i++)
         newV[i] -= other[i];
     return newV;
 }
 public static Vector operator /(Vector one, double param)
 {
     Vector newV = new Vector(one);
     for (int i = 0; i < one.Dim; i++)
         newV[i] /= param;
     return newV;
 }
 public Vector this[int x, int y]
 {
     get
     {
         Vector vector = new Vector(Depth);
         for (int i = 0; i < Depth; i++)
             vector[i] = field[x, y, i];
         return vector;
     }
     set
     {
         //set a vector
     }
 }
        public Vector(Vector other)
        {
            field = new double[other.Dim];

            for (int i = 0; i < other.Dim; i++)
                field[i] = other[i];
        }
 public void SetRow(int position, Vector row)
 {
     if (Width != row.Dim)
         throw new Exception("Dim Error");
     for (int i = 0; i < Width; i++)
         field[i, position] = row[i];
 }
 public void SetColumn(int position, Vector column)
 {
     if (Height != column.Dim)
         throw new Exception("Dim Error");
     for (int i = 0; i < Height; i++)
         field[position, i] = column[i];
 }
 /// <summary>
 /// Returns a row at the given postion as a vector, intial index is 0
 /// </summary>
 /// <param name="position"></param>
 /// <returns></returns>
 public Vector Row(int position)
 {
     Vector newV = new Vector(Width);
     for (int i = 0; i < Width; i++)
         newV[i] = field[i, position];
     return newV;
 }
 /// <summary>
 /// Return a new matrix after GaussianElimination (row reduction) of the original matrix
 /// </summary>
 /// <returns></returns>
 public Matrix GaussianElimination()
 {
     //if (Height != Width)
     //    throw new Exception();
     Matrix newM = new Matrix(this);
     int position = -1;
     double param = 0;
     int count = 0;
     Vector positionV = new Vector(Width);
     for (int i = 0; i < Width; i++)
     {
         if (position != -1)
         {
             newM.SwitchRow(position, count);
             count++;
             position = -1;
         }
         for (int j = count; j < Height; j++)
         {
             if (newM.field[i, j] != 0)
             {
                 if (position != -1)
                     newM.SetRow(j, newM.Row(j) - positionV * newM[i, j] / param);
                 else
                 {
                     position = j;
                     param = newM[i, j];
                     newM.SetRow(j, newM.Row(j));
                     positionV = newM.Row(j);
                 }
             }
         }
     }
     return newM;
 }
 /// <summary>
 /// Return a column at the given position as a vector, initial index is 0
 /// </summary>
 /// <param name="position"></param>
 /// <returns></returns>
 public Vector Column(int position)
 {
     Vector newV = new Vector(Height);
     for (int i = 0; i < Height; i++)
         newV[i] = field[position, i];
     return newV;
 }