Esempio n. 1
0
        /// <summary> Create a transposed matrix </summary>
        public MyMatrix Transpose()
        {
            MyMatrix result = new MyMatrix(this.cols, this.rows);

            for (int row = 0; row < this.rows; row++)
            {
                for (int col = 0; col < this.cols; col++)
                {
                    result[col, row] = this.data[row, col];
                }
            }
            return(result);
        }
        /// <summary> Iteratively solve the coefficients using Gauss-Newton method </summary>
        /// <remarks> http://en.wikipedia.org/wiki/Gauss%E2%80%93Newton_algorithm </remarks>
        public double[] Solve()
        {
            if (this.ys == null)
            {
                throw new InvalidOperationException("Not yet initialized");
            }

            double lastSSE = double.MaxValue;

            double[] errors = new double[this.ys.Length];

            // let C0 be the current coefficient guess, C1 be the better answer we are after
            // let E0 be the error using current guess
            // we have:
            // JacT * Jac * (C1 - C0) = JacT * E0
            //
            MyMatrix     jacobian  = Jacobian();
            MyMatrix     jacobianT = jacobian.Transpose();
            MyMatrix     product   = jacobianT * jacobian;
            SquareMatrix inverse   = SquareMatrix.FromMatrix(product).Inverse();

            for (int iteration = 0; iteration < GaussNewton.MaxIteration; iteration++)
            {
                this.sse = 0;

                for (int i = 0; i < this.ys.Length; i++)
                {
                    double y = function(this.coefficients, this.xs[i]);
                    errors[i] = this.ys[i] - y;
                    sse      += errors[i] * errors[i];
                }

                if (lastSSE - sse < GaussNewton.ConvergeThreshold)
                {
                    this.solved = true;
                    return(this.coefficients);
                }

                double[] shift = inverse * (jacobianT * errors);

                for (int i = 0; i < this.coefficientCount; i++)
                {
                    this.coefficients[i] += shift[i];
                }

                lastSSE = sse;
            }
            throw new InvalidOperationException("No answer can be found");
        }
        /// <summary> Calculate a Jacobian matrix. </summary>
        /// <remarks> http://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant </remarks>
        private MyMatrix Jacobian()
        {
            double[][] p = new double[this.coefficientCount][];
            for (int i = 0; i < p.Length; i++)
            {
                p[i]    = new double[this.coefficientCount];
                p[i][i] = 1;
            }

            MyMatrix jacobian = new MyMatrix(this.ys.Length, this.coefficientCount);

            for (int i = 0; i < this.ys.Length; i++)
            {
                for (int j = 0; j < this.coefficientCount; j++)
                {
                    jacobian[i, j] = function(p[j], this.xs[i]);
                }
            }
            return(jacobian);
        }
Esempio n. 4
0
        /// <summary> Multiply by another matrix. The width of left matrix should equal the height of right matrix </summary>
        public MyMatrix Multiply(MyMatrix m)
        {
            if (m == null || m.rows != this.cols)
            {
                throw new ArgumentException("Invalid matrix to multiply");
            }
            MyMatrix result = new MyMatrix(this.rows, m.cols);
            int      inner  = this.cols;

            for (int row = 0; row < result.rows; row++)
            {
                for (int col = 0; col < result.cols; col++)
                {
                    double sum = 0;
                    for (int i = 0; i < inner; i++)
                    {
                        sum += this[row, i] * m[i, col];
                    }
                    result[row, col] = sum;
                }
            }
            return(result);
        }