コード例 #1
0
        public void AppendRight(IROMatrix a)
        {
            if (m_NumVectors == 0 && m_VectorLen == 0)
            {
                m_bVerticalVectors = true;
                m_NumVectors       = a.Columns;
                m_VectorLen        = a.Rows;
                m_Array            = new double[m_NumVectors][];
                for (int i = 0; i < m_NumVectors; i++)
                {
                    m_Array[i] = new double[m_VectorLen];
                }
                MatrixMath.Copy(a, this);
            }
            else if (this.m_bVerticalVectors == true)
            {
                double [][] newArray = new double[m_NumVectors + a.Columns][];
                for (int i = 0; i < m_NumVectors; i++)
                {
                    newArray[i] = m_Array[i];
                }
                for (int i = m_NumVectors; i < m_NumVectors + a.Columns; i++)
                {
                    newArray[i] = new double[m_VectorLen];
                }
                m_Array       = newArray;
                m_NumVectors += a.Columns;

                MatrixMath.Copy(a, this, 0, this.Columns - a.Columns);
            }
            else
            {
                throw new System.NotImplementedException("This worst case is not implemented yet.");
            }
        }
コード例 #2
0
ファイル: Matrix.cs プロジェクト: olesar/Altaxo
        public void AppendBottom(IROMatrix <double> a)
        {
            if (m_NumVectors == 0 && m_VectorLen == 0)
            {
                m_bVerticalVectors = false;
                m_NumVectors       = a.RowCount;
                m_VectorLen        = a.ColumnCount;
                m_Array            = new double[m_NumVectors][];
                for (int i = 0; i < m_NumVectors; i++)
                {
                    m_Array[i] = new double[m_VectorLen];
                }
                MatrixMath.Copy(a, this);
            }
            else if (m_bVerticalVectors == false)
            {
                double[][] newArray = new double[m_NumVectors + a.RowCount][];
                for (int i = 0; i < m_NumVectors; i++)
                {
                    newArray[i] = m_Array[i];
                }
                for (int i = m_NumVectors; i < m_NumVectors + a.RowCount; i++)
                {
                    newArray[i] = new double[m_VectorLen];
                }
                m_Array       = newArray;
                m_NumVectors += a.RowCount;

                MatrixMath.Copy(a, this, RowCount - a.RowCount, 0);
            }
            else
            {
                throw new System.NotImplementedException("This worst case is not implemented yet.");
            }
        }
コード例 #3
0
ファイル: QRDecomposition.cs プロジェクト: olesar/Altaxo
        public void Decompose(IROMatrix <double> A)
        {
            // Initialize.
            if (m == A.RowCount && n == A.ColumnCount)
            {
                MatrixMath.Copy(A, new JaggedArrayMatrix(QR, m, n));
                //JaggedArrayMath.Copy(A, QR);
            }
            else
            {
                QR    = JaggedArrayMath.GetMatrixCopy(A);
                m     = A.RowCount;
                n     = A.ColumnCount;
                Rdiag = new double[n];
            }

            // Main loop.
            for (int k = 0; k < n; k++)
            {
                // Compute 2-norm of k-th column without under/overflow.
                double nrm = 0;
                for (int i = k; i < m; i++)
                {
                    nrm = RMath.Hypot(nrm, QR[i][k]);
                }

                if (nrm != 0.0)
                {
                    // Form k-th Householder vector.
                    if (QR[k][k] < 0)
                    {
                        nrm = -nrm;
                    }
                    for (int i = k; i < m; i++)
                    {
                        QR[i][k] /= nrm;
                    }
                    QR[k][k] += 1.0;

                    // Apply transformation to remaining columns.
                    for (int j = k + 1; j < n; j++)
                    {
                        double s = 0.0;
                        for (int i = k; i < m; i++)
                        {
                            s += QR[i][k] * QR[i][j];
                        }
                        s = -s / QR[k][k];
                        for (int i = k; i < m; i++)
                        {
                            QR[i][j] += s * QR[i][k];
                        }
                    }
                }
                Rdiag[k] = -nrm;
            }
        }
コード例 #4
0
        /// <summary>Solves system of linear equations Ax = b using Gaussian elimination with partial pivoting.</summary>
        /// <param name="A">Elements of matrix 'A'. This array is modified during solution!</param>
        /// <param name="b">Right part 'b'. This array is also modified during solution!</param>
        /// <param name="x">Vector to store the result, i.e. the solution to the problem a x = b.</param>
        public void Solve(IROMatrix <double> A, IReadOnlyList <double> b, IVector <double> x)
        {
            if (_temp_A.RowCount != A.RowCount || _temp_A.ColumnCount != A.ColumnCount)
            {
                _temp_A = new MatrixWrapperStructForLeftSpineJaggedArray <double>(A.RowCount, A.ColumnCount);
            }
            if (b.Count != _temp_b?.Length)
            {
                _temp_b = new double[b.Count];
            }
            if (b.Count != _temp_x?.Length)
            {
                _temp_x = new double[b.Count];
            }

            MatrixMath.Copy(A, _temp_A);
            VectorMath.Copy(b, _temp_b);
            SolveDestructive(_temp_A, _temp_b, _temp_x);
            VectorMath.Copy(_temp_x, x);
        }
コード例 #5
0
ファイル: QRDecomposition.cs プロジェクト: olesar/Altaxo
        /** Least squares solution of A*X = B
         *          @param B    A Matrix with as many rows as A and any number of columns.
         *          @return     X that minimizes the two norm of Q*R*X-B.
         *          @exception  IllegalArgumentException  Matrix row dimensions must agree.
         *          @exception  RuntimeException  Matrix is rank deficient.
         */

        public void Solve(IROMatrix <double> B, IMatrix <double> result)
        {
            if (B.RowCount != m)
            {
                throw new ArgumentException("Matrix row dimensions must agree.");
            }
            if (!IsFullRank())
            {
                throw new Exception("Matrix is rank deficient.");
            }

            // Copy right hand side
            int nx = B.ColumnCount;

            double[][] X;
            if (_solveMatrixWorkspace != null && _solveMatrixWorkspace.RowCount == B.RowCount && _solveMatrixWorkspace.ColumnCount == B.ColumnCount)
            {
                X = _solveMatrixWorkspace.Array;
                MatrixMath.Copy(B, _solveMatrixWorkspace);
            }
            else
            {
                X = JaggedArrayMath.GetMatrixCopy(B);
                _solveMatrixWorkspace = new JaggedArrayMatrix(X, B.RowCount, B.ColumnCount);
            }

            // Compute Y = transpose(Q)*B
            for (int k = 0; k < n; k++)
            {
                for (int j = 0; j < nx; j++)
                {
                    double s = 0.0;
                    for (int i = k; i < m; i++)
                    {
                        s += QR[i][k] * X[i][j];
                    }
                    s = -s / QR[k][k];
                    for (int i = k; i < m; i++)
                    {
                        X[i][j] += s * QR[i][k];
                    }
                }
            }
            // Solve R*X = Y;
            for (int k = n - 1; k >= 0; k--)
            {
                for (int j = 0; j < nx; j++)
                {
                    X[k][j] /= Rdiag[k];
                }
                for (int i = 0; i < k; i++)
                {
                    for (int j = 0; j < nx; j++)
                    {
                        X[i][j] -= X[k][j] * QR[i][k];
                    }
                }
            }

            MatrixMath.Submatrix(_solveMatrixWorkspace, result, 0, 0);
        }
コード例 #6
0
        /// <summary>
        /// Execution of the fast nonnegative least squares algorithm. The algorithm finds a vector x with all elements xi&gt;=0 which minimizes |X*x-y|.
        /// </summary>
        /// <param name="XtX">X transposed multiplied by X, thus a square matrix.</param>
        /// <param name="Xty">X transposed multiplied by Y, thus a matrix with one column and same number of rows as X.</param>
        /// <param name="isRestrictedToPositiveValues">Function that takes the parameter index as argument and returns true if the parameter at this index is restricted to positive values; otherwise the return value must be false.</param>
        /// <param name="tolerance">Used to decide if a solution element is less than or equal to zero. If this is null, a default tolerance of tolerance = MAX(SIZE(XtX)) * NORM(XtX,1) * EPS is used.</param>
        /// <param name="x">Output: solution vector (matrix with one column and number of rows according to dimension of X.</param>
        /// <param name="w">Output: Lagrange vector. Elements which take place in the fit are set to 0. Elements fixed to zero contain a negative number.</param>
        /// <remarks>
        /// <para>
        /// Literature: Rasmus Bro and Sijmen De Jong, 'A fast non-negativity-constrained least squares algorithm', Journal of Chemometrics, Vol. 11, 393-401 (1997)
        /// </para>
        /// <para>
        /// Algorithm modified by Dirk Lellinger 2015 to allow a mixture of restricted and unrestricted parameters.
        /// </para>
        /// </remarks>
        public static void Execution(IROMatrix <double> XtX, IROMatrix <double> Xty, Func <int, bool> isRestrictedToPositiveValues, double?tolerance, out IMatrix <double> x, out IMatrix <double> w)
        {
            if (null == XtX)
            {
                throw new ArgumentNullException(nameof(XtX));
            }
            if (null == Xty)
            {
                throw new ArgumentNullException(nameof(Xty));
            }
            if (null == isRestrictedToPositiveValues)
            {
                throw new ArgumentNullException(nameof(isRestrictedToPositiveValues));
            }

            if (XtX.RowCount != XtX.ColumnCount)
            {
                throw new ArgumentException("Matrix should be a square matrix", nameof(XtX));
            }
            if (Xty.ColumnCount != 1)
            {
                throw new ArgumentException(nameof(Xty) + " should be a column vector (number of columns should be equal to 1)", nameof(Xty));
            }
            if (Xty.RowCount != XtX.ColumnCount)
            {
                throw new ArgumentException("Number of rows in " + nameof(Xty) + " should match number of columns in " + nameof(XtX), nameof(Xty));
            }

            var matrixGenerator = new Func <int, int, DoubleMatrix>((rows, cols) => new DoubleMatrix(rows, cols));

            // if nargin < 3
            //   tol = 10 * eps * norm(XtX, 1) * length(XtX);
            // end
            double tol = tolerance.HasValue ? tolerance.Value : 10 * DoubleConstants.DBL_EPSILON * MatrixMath.Norm(XtX, MatrixNorm.M1Norm) * Math.Max(XtX.RowCount, XtX.ColumnCount);

            //	[m, n] = size(XtX);
            int n = XtX.ColumnCount;

            // P = zeros(1, n);
            // Z = 1:n;
            var  P = new bool[n]; // POSITIVE SET: all indices which are currently not fixed are marked with TRUE (Negative set is simply this, but inverted)
            bool initializationOfSolutionRequired = false;

            for (int i = 0; i < n; ++i)
            {
                bool isNotRestricted = !isRestrictedToPositiveValues(i);
                P[i] = isNotRestricted;
                initializationOfSolutionRequired |= isNotRestricted;
            }

            // x = P';
            x = matrixGenerator(n, 1);

            // w = Xty-XtX*x;
            w = matrixGenerator(n, 1);
            MatrixMath.Copy(Xty, w);
            var helper_n_1 = matrixGenerator(n, 1);

            MatrixMath.Multiply(XtX, x, helper_n_1);
            MatrixMath.Subtract(w, helper_n_1, w);

            // set up iteration criterion
            int iter  = 0;
            int itmax = 30 * n;

            // outer loop to put variables into set to hold positive coefficients
            // while any(Z) & any(w(ZZ) > tol)
            while (initializationOfSolutionRequired || (P.Any(ele => false == ele) && w.Any((r, c, ele) => false == P[r] && ele > tol)))
            {
                if (initializationOfSolutionRequired)
                {
                    initializationOfSolutionRequired = false;
                }
                else
                {
                    // [wt, t] = max(w(ZZ));
                    // t = ZZ(t);
                    int    t  = -1; // INDEX
                    double wt = double.NegativeInfinity;
                    for (int i = 0; i < n; ++i)
                    {
                        if (!P[i])
                        {
                            if (w[i, 0] > wt)
                            {
                                wt = w[i, 0];
                                t  = i;
                            }
                        }
                    }

                    // P(1, t) = t;
                    // Z(t) = 0;
                    P[t] = true;
                }

                // z(PP')=(Xty(PP)'/XtX(PP,PP)');
                var subXty      = Xty.SubMatrix(P, 0, matrixGenerator); // Xty(PP)'
                var subXtX      = XtX.SubMatrix(P, P, matrixGenerator);
                var solver      = new DoubleLUDecomp(subXtX);
                var subSolution = solver.Solve(subXty);
                var z           = matrixGenerator(n, 1);
                for (int i = 0, ii = 0; i < n; ++i)
                {
                    z[i, 0] = P[i] ? subSolution[ii++, 0] : 0;
                }

                // C. Inner loop (to remove elements from the positive set which no longer belong to)
                while (z.Any((r, c, ele) => true == P[r] && ele <= tol && isRestrictedToPositiveValues(r)) && iter < itmax)
                {
                    ++iter;
                    // QQ = find((z <= tol) & P');
                    //alpha = min(x(QQ)./ (x(QQ) - z(QQ)));
                    double alpha = double.PositiveInfinity;
                    for (int i = 0; i < n; ++i)
                    {
                        if ((z[i, 0] <= tol && true == P[i] && isRestrictedToPositiveValues(i)))
                        {
                            alpha = Math.Min(alpha, x[i, 0] / (x[i, 0] - z[i, 0]));
                        }
                    }
                    // x = x + alpha * (z - x);
                    for (int i = 0; i < n; ++i)
                    {
                        x[i, 0] += alpha * (z[i, 0] - x[i, 0]);
                    }

                    // ij = find(abs(x) < tol & P' ~= 0);
                    // Z(ij) = ij';
                    // P(ij) = zeros(1, length(ij));

                    for (int i = 0; i < n; ++i)
                    {
                        if (Math.Abs(x[i, 0]) < tol && P[i] == true && isRestrictedToPositiveValues(i))
                        {
                            P[i] = false;
                        }
                    }

                    //PP = find(P);
                    //ZZ = find(Z);
                    //nzz = size(ZZ);
                    //z(PP) = (Xty(PP)'/XtX(PP,PP)');

                    subXty      = Xty.SubMatrix(P, 0, matrixGenerator);
                    subXtX      = XtX.SubMatrix(P, P, matrixGenerator);
                    solver      = new DoubleLUDecomp(subXtX);
                    subSolution = solver.Solve(subXty);

                    for (int i = 0, ii = 0; i < n; ++i)
                    {
                        z[i, 0] = P[i] ? subSolution[ii++, 0] : 0;
                    }
                } // end inner loop

                MatrixMath.Copy(z, x);
                MatrixMath.Copy(Xty, w);
                MatrixMath.Multiply(XtX, x, helper_n_1);
                MatrixMath.Subtract(w, helper_n_1, w);
            }
        }