예제 #1
0
        /// <summary>
        /// Creates the eigenvalue decomposition of the given matrix.
        /// </summary>
        /// <param name="matrixA">The square matrix A.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixA"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="matrixA"/> is non-square (rectangular).
        /// </exception>
        public EigenvalueDecompositionD(MatrixD matrixA)
        {
            if (matrixA == null)
            {
                throw new ArgumentNullException("matrixA");
            }
            if (matrixA.IsSquare == false)
            {
                throw new ArgumentException("The matrix A must be square.", "matrixA");
            }

            _n = matrixA.NumberOfColumns;
            _d = new VectorD(_n);
            _e = new VectorD(_n);

            _isSymmetric = matrixA.IsSymmetric;

            if (_isSymmetric)
            {
                _v = matrixA.Clone();

                // Tridiagonalize.
                ReduceToTridiagonal();

                // Diagonalize.
                TridiagonalToQL();
            }
            else
            {
                _v = new MatrixD(_n, _n);

                // Abort if A contains NaN values.
                // If we continue with NaN values, we run into an infinite loop.
                for (int i = 0; i < _n; i++)
                {
                    for (int j = 0; j < _n; j++)
                    {
                        if (Numeric.IsNaN(matrixA[i, j]))
                        {
                            _e.Set(double.NaN);
                            _v.Set(double.NaN);
                            _d.Set(double.NaN);
                            return;
                        }
                    }
                }

                // Storage of nonsymmetric Hessenberg form.
                MatrixD matrixH = matrixA.Clone();
                // Working storage for nonsymmetric algorithm.
                double[] ort = new double[_n];

                // Reduce to Hessenberg form.
                ReduceToHessenberg(matrixH, ort);

                // Reduce Hessenberg to real Schur form.
                HessenbergToRealSchur(matrixH);
            }
        }
예제 #2
0
        /// <summary>
        /// Creates the QR decomposition of the given matrix.
        /// </summary>
        /// <param name="matrixA">
        /// The matrix A. (Can be rectangular. NumberOfRows must be ≥ NumberOfColumns.)
        /// </param>
        /// <remarks>
        /// The QR decomposition is computed by Householder reflections.
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixA"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of rows must be greater than or equal to the number of columns.
        /// </exception>
        public QRDecompositionD(MatrixD matrixA)
        {
            if (matrixA == null)
            {
                throw new ArgumentNullException("matrixA");
            }
            if (matrixA.NumberOfRows < matrixA.NumberOfColumns)
            {
                throw new ArgumentException("The number of rows must be greater than or equal to the number of columns.", "matrixA");
            }

            // Initialize.
            _qr        = matrixA.Clone();
            _m         = matrixA.NumberOfRows;
            _n         = matrixA.NumberOfColumns;
            _rDiagonal = new double[_n];

            // Main loop.
            for (int k = 0; k < _n; k++)
            {
                // Compute 2-norm of k-th column without under/overflow.
                double norm = 0;
                for (int i = k; i < _m; i++)
                {
                    norm = MathHelper.Hypotenuse(norm, _qr[i, k]);
                }

                if (norm != 0) // TODO: Maybe a comparison with an epsilon tolerance is required here!?
                {
                    // Form k-th Householder vector.
                    if (_qr[k, k] < 0)
                    {
                        norm = -norm;
                    }
                    for (int i = k; i < _m; i++)
                    {
                        _qr[i, k] /= norm;
                    }
                    _qr[k, k] += 1;

                    // Apply transformation to remaining columns.
                    for (int j = k + 1; j < _n; j++)
                    {
                        double s = 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];
                        }
                    }
                }
                _rDiagonal[k] = -norm;
            }
        }
        //--------------------------------------------------------------
        /// <summary>
        /// Creates the eigenvalue decomposition of the given matrix.
        /// </summary>
        /// <param name="matrixA">The square matrix A.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixA"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="matrixA"/> is non-square (rectangular).
        /// </exception>
        public EigenvalueDecompositionD(MatrixD matrixA)
        {
            if (matrixA == null)
            throw new ArgumentNullException("matrixA");
              if (matrixA.IsSquare == false)
            throw new ArgumentException("The matrix A must be square.", "matrixA");

              _n = matrixA.NumberOfColumns;
              _d = new VectorD(_n);
              _e = new VectorD(_n);

              _isSymmetric = matrixA.IsSymmetric;

              if (_isSymmetric)
              {
            _v = matrixA.Clone();

            // Tridiagonalize.
            ReduceToTridiagonal();

            // Diagonalize.
            TridiagonalToQL();
              }
              else
              {
            _v = new MatrixD(_n, _n);

            // Abort if A contains NaN values.
            // If we continue with NaN values, we run into an infinite loop.
            for (int i = 0; i < _n; i++)
            {
              for (int j = 0; j < _n; j++)
              {
            if (Numeric.IsNaN(matrixA[i, j]))
            {
              _e.Set(double.NaN);
              _v.Set(double.NaN);
              _d.Set(double.NaN);
              return;
            }
              }
            }

            // Storage of nonsymmetric Hessenberg form.
            MatrixD matrixH = matrixA.Clone();
            // Working storage for nonsymmetric algorithm.
            double[] ort = new double[_n];

            // Reduce to Hessenberg form.
            ReduceToHessenberg(matrixH, ort);

            // Reduce Hessenberg to real Schur form.
            HessenbergToRealSchur(matrixH);
              }
        }
예제 #4
0
        /// <summary>
        /// Returns the least squares solution for the equation <c>A * X = B</c>.
        /// </summary>
        /// <param name="matrixB">The matrix B with as many rows as A and any number of columns.</param>
        /// <returns>X with the least squares solution.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixB"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of rows does not match.
        /// </exception>
        /// <exception cref="MathematicsException">
        /// The matrix A does not have full rank.
        /// </exception>
        public MatrixD SolveLinearEquations(MatrixD matrixB)
        {
            if (matrixB == null)
            {
                throw new ArgumentNullException("matrixB");
            }
            if (matrixB.NumberOfRows != _m)
            {
                throw new ArgumentException("The number of rows does not match.", "matrixB");
            }
            if (HasNumericallyFullRank == false)
            {
                throw new MathematicsException("The matrix does not have full rank.");
            }

            // Copy right hand side
            MatrixD x = matrixB.Clone();

            // Compute Y = transpose(Q)*B
            for (int k = 0; k < _n; k++)
            {
                for (int j = 0; j < matrixB.NumberOfColumns; j++)
                {
                    double s = 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 < matrixB.NumberOfColumns; j++)
                {
                    x[k, j] /= _rDiagonal[k];
                }
                for (int i = 0; i < k; i++)
                {
                    for (int j = 0; j < matrixB.NumberOfColumns; j++)
                    {
                        x[i, j] -= x[k, j] * _qr[i, k];
                    }
                }
            }
            return(x.GetSubmatrix(0, _n - 1, 0, matrixB.NumberOfColumns - 1));
        }
예제 #5
0
		/// <summary>
		/// 部分ピボット選択付きガウス消去法により連立一次方程式の解を求める
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		/// <returns></returns>
		private static VectorD SolveByGEPP(MatrixD a, VectorD b)
		{
			int r = 0;
			int c = 0;
			var a2 = a.Clone();
			var b2 = b.Clone();

			while (r < a2.Rows - 1)
			{
				var maxA = a2.GetColumn(c).Where((x, i) => i >= r).Max();
				var idxMaxA = a2.GetRowIndex((x, i) => (i >= r) && (x[c] == maxA));
				if (idxMaxA != r)
				{
					a2.SwapRow(r, idxMaxA);
					b2.Swap(r, idxMaxA);
				}

				for (int i = r + 1; i < a2.Rows; i++)
				{
					var x = a2[i, c] * -1.0;
					a2[i, c] = 0;
					for (int j = c + 1; j < a2.Columns; j++)
					{
						a2[i, j] += a2[r, j] * (x / a2[r, c]);
					}

					b2[i] += b2[r] * (x / a2[r, c]);
				}

				r++;
				c++;
			}

			var n = b2.Length;
			var result = new VectorD(new double[n]);
			for (int k = n - 1; k >= 0; k--)
			{
				var sum = 0.0;
				for (int j = k + 1; j < n; j++)
				{
					sum += a2[k, j] * result[j];
				}
				result[k] = (b2[k] - sum) / a2[k, k];
			}

			return result;
		}
예제 #6
0
        /// <summary>
        /// Solves the equation <c>A * X = B</c>.
        /// </summary>
        /// <param name="matrixB">The matrix B with as many rows as A and any number of columns.</param>
        /// <returns>X, so that <c>A * X = B</c>.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixB"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of rows does not match.
        /// </exception>
        /// <exception cref="MathematicsException">
        /// The matrix A is not symmetric and positive definite.
        /// </exception>
        public MatrixD SolveLinearEquations(MatrixD matrixB)
        {
            if (matrixB == null)
            {
                throw new ArgumentNullException("matrixB");
            }
            if (matrixB.NumberOfRows != L.NumberOfRows)
            {
                throw new ArgumentException("The number of rows does not match.", "matrixB");
            }
            if (IsSymmetricPositiveDefinite == false)
            {
                throw new MathematicsException("The original matrix A is not symmetric and positive definite.");
            }

            // Initialize x as a copy of B.
            MatrixD x = matrixB.Clone();

            // Solve L*Y = B.
            for (int k = 0; k < L.NumberOfRows; k++)
            {
                for (int j = 0; j < matrixB.NumberOfColumns; j++)
                {
                    for (int i = 0; i < k; i++)
                    {
                        x[k, j] -= x[i, j] * L[k, i];
                    }
                    x[k, j] /= L[k, k];
                }
            }

            // Solve transpose(L) * X = Y.
            for (int k = L.NumberOfRows - 1; k >= 0; k--)
            {
                for (int j = 0; j < matrixB.NumberOfColumns; j++)
                {
                    for (int i = k + 1; i < L.NumberOfRows; i++)
                    {
                        x[k, j] -= x[i, j] * L[i, k];
                    }
                    x[k, j] /= L[k, k];
                }
            }

            return(x);
        }
예제 #7
0
        //--------------------------------------------------------------
        /// <summary>
        /// Creates the QR decomposition of the given matrix.
        /// </summary>
        /// <param name="matrixA">
        /// The matrix A. (Can be rectangular. NumberOfRows must be ≥ NumberOfColumns.)
        /// </param>
        /// <remarks>
        /// The QR decomposition is computed by Householder reflections.
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixA"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of rows must be greater than or equal to the number of columns.
        /// </exception>
        public QRDecompositionD(MatrixD matrixA)
        {
            if (matrixA == null)
            throw new ArgumentNullException("matrixA");
              if (matrixA.NumberOfRows < matrixA.NumberOfColumns)
            throw new ArgumentException("The number of rows must be greater than or equal to the number of columns.", "matrixA");

              // Initialize.
              _qr = matrixA.Clone();
              _m = matrixA.NumberOfRows;
              _n = matrixA.NumberOfColumns;
              _rDiagonal = new double[_n];

              // Main loop.
              for (int k = 0; k < _n; k++)
              {
            // Compute 2-norm of k-th column without under/overflow.
            double norm = 0;
            for (int i = k; i < _m; i++)
              norm = MathHelper.Hypotenuse(norm, _qr[i, k]);

            if (norm != 0)   // TODO: Maybe a comparison with an epsilon tolerance is required here!?
            {
              // Form k-th Householder vector.
              if (_qr[k, k] < 0)
            norm = -norm;
              for (int i = k; i < _m; i++)
            _qr[i, k] /= norm;
              _qr[k, k] += 1;

              // Apply transformation to remaining columns.
              for (int j = k + 1; j < _n; j++)
              {
            double s = 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];
              }
            }
            _rDiagonal[k] = -norm;
              }
        }
예제 #8
0
		/// <summary>
		/// ガウス消去法により連立一次方程式の解を求める
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		/// <returns></returns>
		private static VectorD SolveByGE(MatrixD a, VectorD b)
		{
			int r = 0;
			int c = 0;
			var a2 = a.Clone();
			var b2 = b.Clone();

			while (r < a2.Rows - 1)
			{
				for (int i = r + 1; i < a2.Rows; i++)
				{
					var x = a2[i, c] * -1.0;
					a2[i, c] = 0;
					for (int j = c + 1; j < a2.Columns; j++)
					{
						a2[i, j] += a2[r, j] * (x / a2[r, c]);
					}

					b2[i] += b2[r] * (x / a2[r, c]);
				}

				r++;
				c++;
			}

			var n = b2.Length;
			var result = new VectorD(new double[n]);
			for (int k = n - 1; k >= 0; k--)
			{
				var sum = 0.0;
				for (int j = k + 1; j < n; j++)
				{
					sum += a2[k, j] * result[j];
				}
				result[k] = (b2[k] - sum) / a2[k, k];
			}

			return result;
		}
예제 #9
0
        public void Absolute()
        {
            double[] values = new double[] { -1.0, -2.0, -3.0,
                                     -4.0, -5.0, -6.0,
                                     -7.0, -8.0, -9.0 };
              MatrixD m = new MatrixD(3, 3, values, MatrixOrder.RowMajor);

              MatrixD absolute = m.Clone();
              absolute.Absolute();
              for (int i = 0; i < absolute.NumberOfRows; i++)
            for (int j = 0; j < absolute.NumberOfColumns; j++)
              Assert.AreEqual(i * absolute.NumberOfColumns + j + 1, absolute[i, j]);

              absolute = MatrixD.Absolute(m);
              for (int i = 0; i < absolute.NumberOfRows; i++)
            for (int j = 0; j < absolute.NumberOfColumns; j++)
              Assert.AreEqual(i * absolute.NumberOfColumns + j + 1, absolute[i, j]);

              values = new double[] { 1.0, 2.0, 3.0,
                             4.0, 5.0, 6.0,
                             7.0, 8.0, 9.0 };
              m = new MatrixD(3, 3, values, MatrixOrder.RowMajor);

              absolute = m.Clone();
              absolute.Absolute();
              for (int i = 0; i < absolute.NumberOfRows; i++)
            for (int j = 0; j < absolute.NumberOfColumns; j++)
              Assert.AreEqual(i * absolute.NumberOfColumns + j + 1, absolute[i, j]);

              absolute = MatrixD.Absolute(m);
              for (int i = 0; i < absolute.NumberOfRows; i++)
            for (int j = 0; j < absolute.NumberOfColumns; j++)
              Assert.AreEqual(i * absolute.NumberOfColumns + j + 1, absolute[i, j]);

              Assert.IsNull(MatrixD.Absolute(null));
        }
        public SingularValueDecompositionD(MatrixD matrixA)
        {
            if (matrixA == null)
            {
                throw new ArgumentNullException("matrixA");
            }

            // Derived from LINPACK code.
            // Initialize.
            _m = matrixA.NumberOfRows;
            _n = matrixA.NumberOfColumns;
            MatrixD matrixAClone = matrixA.Clone();

            if (_m < _n)
            {
                throw new ArgumentException("The number of rows must be greater than or equal to the number of columns.", "matrixA");
            }

            int nu = Math.Min(_m, _n);

            _s = new VectorD(Math.Min(_m + 1, _n));
            _u = new MatrixD(_m, nu); //Jama getU() returns new Matrix(U,_m,Math.min(_m+1,_n)) ?!
            _v = new MatrixD(_n, _n);
            double[] e    = new double[_n];
            double[] work = new double[_m];

            // Abort if A contains NaN values.
            // If we continue with NaN values, we run into an infinite loop.
            for (int i = 0; i < _m; i++)
            {
                for (int j = 0; j < _n; j++)
                {
                    if (Numeric.IsNaN(matrixA[i, j]))
                    {
                        _u.Set(double.NaN);
                        _v.Set(double.NaN);
                        _s.Set(double.NaN);
                        return;
                    }
                }
            }

            // By default, we calculate U and V. To calculate only U or V we can set one of the following
            // two constants to false. (This optimization is not yet tested.)
            const bool wantu = true;
            const bool wantv = true;

            // Reduce A to bidiagonal form, storing the diagonal elements
            // in s and the super-diagonal elements in e.

            int nct = Math.Min(_m - 1, _n);
            int nrt = Math.Max(0, Math.Min(_n - 2, _m));

            for (int k = 0; k < Math.Max(nct, nrt); k++)
            {
                if (k < nct)
                {
                    // Compute the transformation for the k-th column and
                    // place the k-th diagonal in s[k].
                    // Compute 2-norm of k-th column without under/overflow.
                    _s[k] = 0;
                    for (int i = k; i < _m; i++)
                    {
                        _s[k] = MathHelper.Hypotenuse(_s[k], matrixAClone[i, k]);
                    }

                    if (_s[k] != 0)
                    {
                        if (matrixAClone[k, k] < 0)
                        {
                            _s[k] = -_s[k];
                        }

                        for (int i = k; i < _m; i++)
                        {
                            matrixAClone[i, k] /= _s[k];
                        }

                        matrixAClone[k, k] += 1;
                    }

                    _s[k] = -_s[k];
                }
                for (int j = k + 1; j < _n; j++)
                {
                    if ((k < nct) && (_s[k] != 0))
                    {
                        // Apply the transformation.
                        double t = 0;
                        for (int i = k; i < _m; i++)
                        {
                            t += matrixAClone[i, k] * matrixAClone[i, j];
                        }

                        t = -t / matrixAClone[k, k];
                        for (int i = k; i < _m; i++)
                        {
                            matrixAClone[i, j] += t * matrixAClone[i, k];
                        }
                    }

                    // Place the k-th row of A into e for the
                    // subsequent calculation of the row transformation.

                    e[j] = matrixAClone[k, j];
                }

                if (wantu & (k < nct))
                {
                    // Place the transformation in U for subsequent back
                    // multiplication.
                    for (int i = k; i < _m; i++)
                    {
                        _u[i, k] = matrixAClone[i, k];
                    }
                }

                if (k < nrt)
                {
                    // Compute the k-th row transformation and place the
                    // k-th super-diagonal in e[k].
                    // Compute 2-norm without under/overflow.
                    e[k] = 0;
                    for (int i = k + 1; i < _n; i++)
                    {
                        e[k] = MathHelper.Hypotenuse(e[k], e[i]);
                    }

                    if (e[k] != 0)
                    {
                        if (e[k + 1] < 0)
                        {
                            e[k] = -e[k];
                        }

                        for (int i = k + 1; i < _n; i++)
                        {
                            e[i] /= e[k];
                        }

                        e[k + 1] += 1;
                    }

                    e[k] = -e[k];
                    if ((k + 1 < _m) && (e[k] != 0))
                    {
                        // Apply the transformation.

                        for (int i = k + 1; i < _m; i++)
                        {
                            work[i] = 0;
                        }

                        for (int j = k + 1; j < _n; j++)
                        {
                            for (int i = k + 1; i < _m; i++)
                            {
                                work[i] += e[j] * matrixAClone[i, j];
                            }
                        }

                        for (int j = k + 1; j < _n; j++)
                        {
                            double t = -e[j] / e[k + 1];
                            for (int i = k + 1; i < _m; i++)
                            {
                                matrixAClone[i, j] += t * work[i];
                            }
                        }
                    }

                    if (wantv)
                    {
                        // Place the transformation in V for subsequent
                        // back multiplication.
                        for (int i = k + 1; i < _n; i++)
                        {
                            _v[i, k] = e[i];
                        }
                    }
                }
            }

            // Set up the final bidiagonal matrix or order p.

            int p = Math.Min(_n, _m + 1);

            if (nct < _n)
            {
                _s[nct] = matrixAClone[nct, nct];
            }

            if (_m < p)
            {
                _s[p - 1] = 0;
            }

            if (nrt + 1 < p)
            {
                e[nrt] = matrixAClone[nrt, p - 1];
            }

            e[p - 1] = 0;

            // If required, generate U.

            if (wantu)
            {
                for (int j = nct; j < nu; j++)
                {
                    for (int i = 0; i < _m; i++)
                    {
                        _u[i, j] = 0;
                    }

                    _u[j, j] = 1;
                }

                for (int k = nct - 1; k >= 0; k--)
                {
                    if (_s[k] != 0)
                    {
                        for (int j = k + 1; j < nu; j++)
                        {
                            double t = 0;
                            for (int i = k; i < _m; i++)
                            {
                                t += _u[i, k] * _u[i, j];
                            }

                            t = -t / _u[k, k];
                            for (int i = k; i < _m; i++)
                            {
                                _u[i, j] += t * _u[i, k];
                            }
                        }
                        for (int i = k; i < _m; i++)
                        {
                            _u[i, k] = -_u[i, k];
                        }

                        _u[k, k] = 1 + _u[k, k];
                        for (int i = 0; i < k - 1; i++)
                        {
                            _u[i, k] = 0;
                        }
                    }
                    else
                    {
                        for (int i = 0; i < _m; i++)
                        {
                            _u[i, k] = 0;
                        }

                        _u[k, k] = 1;
                    }
                }
            }

            // If required, generate V.
            if (wantv)
            {
                for (int k = _n - 1; k >= 0; k--)
                {
                    if ((k < nrt) & (e[k] != 0.0))
                    {
                        for (int j = k + 1; j < nu; j++)
                        {
                            double t = 0;
                            for (int i = k + 1; i < _n; i++)
                            {
                                t += _v[i, k] * _v[i, j];
                            }

                            t = -t / _v[k + 1, k];
                            for (int i = k + 1; i < _n; i++)
                            {
                                _v[i, j] += t * _v[i, k];
                            }
                        }
                    }

                    for (int i = 0; i < _n; i++)
                    {
                        _v[i, k] = 0;
                    }

                    _v[k, k] = 1;
                }
            }

            // Main iteration loop for the singular values.

            int    pp   = p - 1;
            int    iter = 0;
            double eps  = Math.Pow(2, -52);
            double tiny = Math.Pow(2, -966); // Original: 2^-966 for double

            while (p > 0)
            {
                int k, kase;

                // Here is where a test for too many iterations would go.

                // This section of the program inspects for
                // negligible elements in the s and e arrays. On
                // completion the variables kase and k are set as follows.

                // kase = 1     if s(p) and e[k-1] are negligible and k<p
                // kase = 2     if s(k) is negligible and k<p
                // kase = 3     if e[k-1] is negligible, k<p, and
                //              s(k), ..., s(p) are not negligible (qr step).
                // kase = 4     if e(p-1) is negligible (convergence).

                for (k = p - 2; k >= -1; k--)
                {
                    if (k == -1)
                    {
                        break;
                    }

                    if (Math.Abs(e[k]) <= tiny + eps * (Math.Abs(_s[k]) + Math.Abs(_s[k + 1])))
                    {
                        e[k] = 0;
                        break;
                    }
                }

                if (k == p - 2)
                {
                    kase = 4;
                }
                else
                {
                    int ks;
                    for (ks = p - 1; ks >= k; ks--)
                    {
                        if (ks == k)
                        {
                            break;
                        }

                        double t = (ks != p ? Math.Abs(e[ks]) : 0) + (ks != k + 1 ? Math.Abs(e[ks - 1]) : 0);
                        if (Math.Abs(_s[ks]) <= tiny + eps * t)
                        {
                            _s[ks] = 0;
                            break;
                        }
                    }
                    if (ks == k)
                    {
                        kase = 3;
                    }
                    else if (ks == p - 1)
                    {
                        kase = 1;
                    }
                    else
                    {
                        kase = 2;
                        k    = ks;
                    }
                }

                k++;

                // Perform the task indicated by kase.

                switch (kase)
                {
                // Deflate negligible s(p).
                case 1:
                {
                    double f = e[p - 2];
                    e[p - 2] = 0;
                    for (int j = p - 2; j >= k; j--)
                    {
                        double t  = MathHelper.Hypotenuse(_s[j], f);
                        double cs = _s[j] / t;
                        double sn = f / t;
                        _s[j] = t;
                        if (j != k)
                        {
                            f        = -sn * e[j - 1];
                            e[j - 1] = cs * e[j - 1];
                        }

                        if (wantv)
                        {
                            for (int i = 0; i < _n; i++)
                            {
                                t            = cs * _v[i, j] + sn * _v[i, p - 1];
                                _v[i, p - 1] = -sn * _v[i, j] + cs * _v[i, p - 1];
                                _v[i, j]     = t;
                            }
                        }
                    }
                }
                break;

                // Split at negligible s(k).
                case 2:
                {
                    double f = e[k - 1];
                    e[k - 1] = 0;
                    for (int j = k; j < p; j++)
                    {
                        double t  = MathHelper.Hypotenuse(_s[j], f);
                        double cs = _s[j] / t;
                        double sn = f / t;
                        _s[j] = t;
                        f     = -sn * e[j];
                        e[j]  = cs * e[j];
                        if (wantu)
                        {
                            for (int i = 0; i < _m; i++)
                            {
                                t            = cs * _u[i, j] + sn * _u[i, k - 1];
                                _u[i, k - 1] = -sn * _u[i, j] + cs * _u[i, k - 1];
                                _u[i, j]     = t;
                            }
                        }
                    }
                }
                break;

                // Perform one qr step.
                case 3:
                {
                    // Calculate the shift.

                    double scale = Math.Max(Math.Max(Math.Max(Math.Max(
                                                                  Math.Abs(_s[p - 1]), Math.Abs(_s[p - 2])), Math.Abs(e[p - 2])),
                                                     Math.Abs(_s[k])), Math.Abs(e[k]));
                    double sp    = _s[p - 1] / scale;
                    double spm1  = _s[p - 2] / scale;
                    double epm1  = e[p - 2] / scale;
                    double sk    = _s[k] / scale;
                    double ek    = e[k] / scale;
                    double b     = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2;
                    double c     = (sp * epm1) * (sp * epm1);
                    double shift = 0;
                    if ((b != 0.0) | (c != 0.0))
                    {
                        shift = Math.Sqrt(b * b + c);
                        if (b < 0.0)
                        {
                            shift = -shift;
                        }

                        shift = c / (b + shift);
                    }
                    double f = (sk + sp) * (sk - sp) + shift;
                    double g = sk * ek;

                    // Chase zeros.

                    for (int j = k; j < p - 1; j++)
                    {
                        double t  = MathHelper.Hypotenuse(f, g);
                        double cs = f / t;
                        double sn = g / t;
                        if (j != k)
                        {
                            e[j - 1] = t;
                        }

                        f         = cs * _s[j] + sn * e[j];
                        e[j]      = cs * e[j] - sn * _s[j];
                        g         = sn * _s[j + 1];
                        _s[j + 1] = cs * _s[j + 1];
                        if (wantv)
                        {
                            for (int i = 0; i < _n; i++)
                            {
                                t            = cs * _v[i, j] + sn * _v[i, j + 1];
                                _v[i, j + 1] = -sn * _v[i, j] + cs * _v[i, j + 1];
                                _v[i, j]     = t;
                            }
                        }

                        t         = MathHelper.Hypotenuse(f, g);
                        cs        = f / t;
                        sn        = g / t;
                        _s[j]     = t;
                        f         = cs * e[j] + sn * _s[j + 1];
                        _s[j + 1] = -sn * e[j] + cs * _s[j + 1];
                        g         = sn * e[j + 1];
                        e[j + 1]  = cs * e[j + 1];
                        if (wantu && (j < _m - 1))
                        {
                            for (int i = 0; i < _m; i++)
                            {
                                t            = cs * _u[i, j] + sn * _u[i, j + 1];
                                _u[i, j + 1] = -sn * _u[i, j] + cs * _u[i, j + 1];
                                _u[i, j]     = t;
                            }
                        }
                    }

                    e[p - 2] = f;
                    iter     = iter + 1;
                }
                break;

                // Convergence.

                case 4:
                {
                    // Make the singular values positive.

                    if (_s[k] <= 0.0)
                    {
                        _s[k] = (_s[k] < 0.0 ? -_s[k] : 0);
                        if (wantv)
                        {
                            for (int i = 0; i <= pp; i++)
                            {
                                _v[i, k] = -_v[i, k];
                            }
                        }
                    }

                    // Order the singular values.

                    while (k < pp)
                    {
                        if (_s[k] >= _s[k + 1])
                        {
                            break;
                        }

                        double t = _s[k];
                        _s[k]     = _s[k + 1];
                        _s[k + 1] = t;
                        if (wantv && (k < _n - 1))
                        {
                            for (int i = 0; i < _n; i++)
                            {
                                t            = _v[i, k + 1];
                                _v[i, k + 1] = _v[i, k];
                                _v[i, k]     = t;
                            }
                        }
                        if (wantu && (k < _m - 1))
                        {
                            for (int i = 0; i < _m; i++)
                            {
                                t            = _u[i, k + 1];
                                _u[i, k + 1] = _u[i, k];
                                _u[i, k]     = t;
                            }
                        }

                        k++;
                    }

                    iter = 0;
                    p--;
                }
                break;
                }
            }
        }
예제 #11
0
        //--------------------------------------------------------------
        /// <summary>
        /// Returns the least squares solution for the equation <c>A * X = B</c>.
        /// </summary>
        /// <param name="matrixB">The matrix B with as many rows as A and any number of columns.</param>
        /// <returns>X with the least squares solution.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixB"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of rows does not match.
        /// </exception>
        /// <exception cref="MathematicsException">
        /// The matrix A does not have full rank.
        /// </exception>
        public MatrixD SolveLinearEquations(MatrixD matrixB)
        {
            if (matrixB == null)
            throw new ArgumentNullException("matrixB");
              if (matrixB.NumberOfRows != _m)
            throw new ArgumentException("The number of rows does not match.", "matrixB");
              if (HasNumericallyFullRank == false)
            throw new MathematicsException("The matrix does not have full rank.");

              // Copy right hand side
              MatrixD x = matrixB.Clone();

              // Compute Y = transpose(Q)*B
              for (int k = 0; k < _n; k++)
              {
            for (int j = 0; j < matrixB.NumberOfColumns; j++)
            {
              double s = 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 < matrixB.NumberOfColumns; j++)
              x[k, j] /= _rDiagonal[k];
            for (int i = 0; i < k; i++)
              for (int j = 0; j < matrixB.NumberOfColumns; j++)
            x[i, j] -= x[k, j] * _qr[i, k];
              }
              return x.GetSubmatrix(0, _n - 1, 0, matrixB.NumberOfColumns - 1);
        }
        public SingularValueDecompositionD(MatrixD matrixA)
        {
            if (matrixA == null)
            throw new ArgumentNullException("matrixA");

              // Derived from LINPACK code.
              // Initialize.
              _m = matrixA.NumberOfRows;
              _n = matrixA.NumberOfColumns;
              MatrixD matrixAClone = matrixA.Clone();

              if (_m < _n)
            throw new ArgumentException("The number of rows must be greater than or equal to the number of columns.", "matrixA");

              int nu = Math.Min(_m, _n);
              _s = new VectorD(Math.Min(_m + 1, _n));
              _u = new MatrixD(_m, nu);     //Jama getU() returns new Matrix(U,_m,Math.min(_m+1,_n)) ?!
              _v = new MatrixD(_n, _n);
              double[] e = new double[_n];
              double[] work = new double[_m];

              // Abort if A contains NaN values.
              // If we continue with NaN values, we run into an infinite loop.
              for (int i = 0; i < _m; i++)
              {
            for (int j = 0; j < _n; j++)
            {
              if (Numeric.IsNaN(matrixA[i, j]))
              {
            _u.Set(double.NaN);
            _v.Set(double.NaN);
            _s.Set(double.NaN);
            return;
              }
            }
              }

              // By default, we calculate U and V. To calculate only U or V we can set one of the following
              // two constants to false. (This optimization is not yet tested.)
              const bool wantu = true;
              const bool wantv = true;

              // Reduce A to bidiagonal form, storing the diagonal elements
              // in s and the super-diagonal elements in e.

              int nct = Math.Min(_m - 1, _n);
              int nrt = Math.Max(0, Math.Min(_n - 2, _m));
              for (int k = 0; k < Math.Max(nct, nrt); k++)
              {
            if (k < nct)
            {
              // Compute the transformation for the k-th column and
              // place the k-th diagonal in s[k].
              // Compute 2-norm of k-th column without under/overflow.
              _s[k] = 0;
              for (int i = k; i < _m; i++)
            _s[k] = MathHelper.Hypotenuse(_s[k], matrixAClone[i, k]);

              if (_s[k] != 0)
              {
            if (matrixAClone[k, k] < 0)
              _s[k] = -_s[k];

            for (int i = k; i < _m; i++)
              matrixAClone[i, k] /= _s[k];

            matrixAClone[k, k] += 1;
              }

              _s[k] = -_s[k];
            }
            for (int j = k + 1; j < _n; j++)
            {
              if ((k < nct) && (_s[k] != 0))
              {
            // Apply the transformation.
            double t = 0;
            for (int i = k; i < _m; i++)
              t += matrixAClone[i, k] * matrixAClone[i, j];

            t = -t / matrixAClone[k, k];
            for (int i = k; i < _m; i++)
              matrixAClone[i, j] += t * matrixAClone[i, k];
              }

              // Place the k-th row of A into e for the
              // subsequent calculation of the row transformation.

              e[j] = matrixAClone[k, j];
            }

            if (wantu & (k < nct))
            {
              // Place the transformation in U for subsequent back
              // multiplication.
              for (int i = k; i < _m; i++)
            _u[i, k] = matrixAClone[i, k];
            }

            if (k < nrt)
            {
              // Compute the k-th row transformation and place the
              // k-th super-diagonal in e[k].
              // Compute 2-norm without under/overflow.
              e[k] = 0;
              for (int i = k + 1; i < _n; i++)
            e[k] = MathHelper.Hypotenuse(e[k], e[i]);

              if (e[k] != 0)
              {
            if (e[k + 1] < 0)
              e[k] = -e[k];

            for (int i = k + 1; i < _n; i++)
              e[i] /= e[k];

            e[k + 1] += 1;
              }

              e[k] = -e[k];
              if ((k + 1 < _m) && (e[k] != 0))
              {
            // Apply the transformation.

            for (int i = k + 1; i < _m; i++)
              work[i] = 0;

            for (int j = k + 1; j < _n; j++)
              for (int i = k + 1; i < _m; i++)
                work[i] += e[j] * matrixAClone[i, j];

            for (int j = k + 1; j < _n; j++)
            {
              double t = -e[j] / e[k + 1];
              for (int i = k + 1; i < _m; i++)
                matrixAClone[i, j] += t * work[i];
            }
              }

              if (wantv)
              {
            // Place the transformation in V for subsequent
            // back multiplication.
            for (int i = k + 1; i < _n; i++)
              _v[i, k] = e[i];
              }
            }
              }

              // Set up the final bidiagonal matrix or order p.

              int p = Math.Min(_n, _m + 1);
              if (nct < _n)
            _s[nct] = matrixAClone[nct, nct];

              if (_m < p)
            _s[p - 1] = 0;

              if (nrt + 1 < p)
            e[nrt] = matrixAClone[nrt, p - 1];

              e[p - 1] = 0;

              // If required, generate U.

              if (wantu)
              {
            for (int j = nct; j < nu; j++)
            {
              for (int i = 0; i < _m; i++)
            _u[i, j] = 0;

              _u[j, j] = 1;
            }

            for (int k = nct - 1; k >= 0; k--)
            {
              if (_s[k] != 0)
              {
            for (int j = k + 1; j < nu; j++)
            {
              double t = 0;
              for (int i = k; i < _m; i++)
                t += _u[i, k] * _u[i, j];

              t = -t / _u[k, k];
              for (int i = k; i < _m; i++)
                _u[i, j] += t * _u[i, k];

            }
            for (int i = k; i < _m; i++)
              _u[i, k] = -_u[i, k];

            _u[k, k] = 1 + _u[k, k];
            for (int i = 0; i < k - 1; i++)
              _u[i, k] = 0;
              }
              else
              {
            for (int i = 0; i < _m; i++)
              _u[i, k] = 0;

            _u[k, k] = 1;
              }
            }
              }

              // If required, generate V.
              if (wantv)
              {
            for (int k = _n - 1; k >= 0; k--)
            {
              if ((k < nrt) & (e[k] != 0.0))
              {
            for (int j = k + 1; j < nu; j++)
            {
              double t = 0;
              for (int i = k + 1; i < _n; i++)
                t += _v[i, k] * _v[i, j];

              t = -t / _v[k + 1, k];
              for (int i = k + 1; i < _n; i++)
                _v[i, j] += t * _v[i, k];
            }
              }

              for (int i = 0; i < _n; i++)
            _v[i, k] = 0;

              _v[k, k] = 1;
            }
              }

              // Main iteration loop for the singular values.

              int pp = p - 1;
              int iter = 0;
              double eps = Math.Pow(2, -52);
              double tiny = Math.Pow(2, -966);   // Original: 2^-966 for double
              while (p > 0)
              {
            int k, kase;

            // Here is where a test for too many iterations would go.

            // This section of the program inspects for
            // negligible elements in the s and e arrays. On
            // completion the variables kase and k are set as follows.

            // kase = 1     if s(p) and e[k-1] are negligible and k<p
            // kase = 2     if s(k) is negligible and k<p
            // kase = 3     if e[k-1] is negligible, k<p, and
            //              s(k), ..., s(p) are not negligible (qr step).
            // kase = 4     if e(p-1) is negligible (convergence).

            for (k = p - 2; k >= -1; k--)
            {
              if (k == -1)
            break;

              if (Math.Abs(e[k]) <= tiny + eps * (Math.Abs(_s[k]) + Math.Abs(_s[k + 1])))
              {
            e[k] = 0;
            break;
              }
            }

            if (k == p - 2)
            {
              kase = 4;
            }
            else
            {
              int ks;
              for (ks = p - 1; ks >= k; ks--)
              {
            if (ks == k)
              break;

            double t = (ks != p ? Math.Abs(e[ks]) : 0) + (ks != k + 1 ? Math.Abs(e[ks - 1]) : 0);
            if (Math.Abs(_s[ks]) <= tiny + eps * t)
            {
              _s[ks] = 0;
              break;
            }
              }
              if (ks == k)
              {
            kase = 3;
              }
              else if (ks == p - 1)
              {
            kase = 1;
              }
              else
              {
            kase = 2;
            k = ks;
              }
            }

            k++;

            // Perform the task indicated by kase.

            switch (kase)
            {
              // Deflate negligible s(p).
              case 1:
            {
              double f = e[p - 2];
              e[p - 2] = 0;
              for (int j = p - 2; j >= k; j--)
              {
                double t = MathHelper.Hypotenuse(_s[j], f);
                double cs = _s[j] / t;
                double sn = f / t;
                _s[j] = t;
                if (j != k)
                {
                  f = -sn * e[j - 1];
                  e[j - 1] = cs * e[j - 1];
                }

                if (wantv)
                {
                  for (int i = 0; i < _n; i++)
                  {
                    t = cs * _v[i, j] + sn * _v[i, p - 1];
                    _v[i, p - 1] = -sn * _v[i, j] + cs * _v[i, p - 1];
                    _v[i, j] = t;
                  }
                }
              }
            }
            break;

              // Split at negligible s(k).
              case 2:
            {
              double f = e[k - 1];
              e[k - 1] = 0;
              for (int j = k; j < p; j++)
              {
                double t = MathHelper.Hypotenuse(_s[j], f);
                double cs = _s[j] / t;
                double sn = f / t;
                _s[j] = t;
                f = -sn * e[j];
                e[j] = cs * e[j];
                if (wantu)
                {
                  for (int i = 0; i < _m; i++)
                  {
                    t = cs * _u[i, j] + sn * _u[i, k - 1];
                    _u[i, k - 1] = -sn * _u[i, j] + cs * _u[i, k - 1];
                    _u[i, j] = t;
                  }
                }
              }
            }
            break;

              // Perform one qr step.
              case 3:
            {
              // Calculate the shift.

              double scale = Math.Max(Math.Max(Math.Max(Math.Max(
                      Math.Abs(_s[p - 1]), Math.Abs(_s[p - 2])), Math.Abs(e[p - 2])),
                      Math.Abs(_s[k])), Math.Abs(e[k]));
              double sp = _s[p - 1] / scale;
              double spm1 = _s[p - 2] / scale;
              double epm1 = e[p - 2] / scale;
              double sk = _s[k] / scale;
              double ek = e[k] / scale;
              double b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2;
              double c = (sp * epm1) * (sp * epm1);
              double shift = 0;
              if ((b != 0.0) | (c != 0.0))
              {
                shift = Math.Sqrt(b * b + c);
                if (b < 0.0)
                  shift = -shift;

                shift = c / (b + shift);
              }
              double f = (sk + sp) * (sk - sp) + shift;
              double g = sk * ek;

              // Chase zeros.

              for (int j = k; j < p - 1; j++)
              {
                double t = MathHelper.Hypotenuse(f, g);
                double cs = f / t;
                double sn = g / t;
                if (j != k)
                  e[j - 1] = t;

                f = cs * _s[j] + sn * e[j];
                e[j] = cs * e[j] - sn * _s[j];
                g = sn * _s[j + 1];
                _s[j + 1] = cs * _s[j + 1];
                if (wantv)
                {
                  for (int i = 0; i < _n; i++)
                  {
                    t = cs * _v[i, j] + sn * _v[i, j + 1];
                    _v[i, j + 1] = -sn * _v[i, j] + cs * _v[i, j + 1];
                    _v[i, j] = t;
                  }
                }

                t = MathHelper.Hypotenuse(f, g);
                cs = f / t;
                sn = g / t;
                _s[j] = t;
                f = cs * e[j] + sn * _s[j + 1];
                _s[j + 1] = -sn * e[j] + cs * _s[j + 1];
                g = sn * e[j + 1];
                e[j + 1] = cs * e[j + 1];
                if (wantu && (j < _m - 1))
                {
                  for (int i = 0; i < _m; i++)
                  {
                    t = cs * _u[i, j] + sn * _u[i, j + 1];
                    _u[i, j + 1] = -sn * _u[i, j] + cs * _u[i, j + 1];
                    _u[i, j] = t;
                  }
                }
              }

              e[p - 2] = f;
              iter = iter + 1;
            }
            break;

              // Convergence.

              case 4:
            {
              // Make the singular values positive.

              if (_s[k] <= 0.0)
              {
                _s[k] = (_s[k] < 0.0 ? -_s[k] : 0);
                if (wantv)
                {
                  for (int i = 0; i <= pp; i++)
                    _v[i, k] = -_v[i, k];
                }
              }

              // Order the singular values.

              while (k < pp)
              {
                if (_s[k] >= _s[k + 1])
                  break;

                double t = _s[k];
                _s[k] = _s[k + 1];
                _s[k + 1] = t;
                if (wantv && (k < _n - 1))
                {
                  for (int i = 0; i < _n; i++)
                  {
                    t = _v[i, k + 1];
                    _v[i, k + 1] = _v[i, k];
                    _v[i, k] = t;
                  }
                }
                if (wantu && (k < _m - 1))
                {
                  for (int i = 0; i < _m; i++)
                  {
                    t = _u[i, k + 1];
                    _u[i, k + 1] = _u[i, k];
                    _u[i, k] = t;
                  }
                }

                k++;
              }

              iter = 0;
              p--;
            }
            break;
            }
              }
        }
예제 #13
0
        public void Invert()
        {
            Assert.AreEqual(MatrixD.CreateIdentity(3, 3), MatrixD.CreateIdentity(3, 3).Inverse);

              MatrixD m = new MatrixD(new double[,] {{1, 2, 3, 4},
                                            {2, 5, 8, 3},
                                            {7, 6, -1, 1},
                                            {4, 9, 7, 7}});
              MatrixD inverse = m.Clone();
              m.Invert();
              VectorD v = new VectorD(4, 1);
              VectorD w = m * v;
              Assert.IsTrue(VectorD.AreNumericallyEqual(v, inverse * w));
              Assert.IsTrue(MatrixD.AreNumericallyEqual(MatrixD.CreateIdentity(4, 4), m * inverse));

              m = new MatrixD(new double[,] {{1, 2, 3},
                                    {2, 5, 8},
                                    {7, 6, -1},
                                    {4, 9, 7}});
              // To check the pseudo-inverse we use the definition: A*A.Transposed*A = A
              // see http://en.wikipedia.org/wiki/Moore-Penrose_pseudoinverse
              inverse = m.Clone();
              inverse.Invert();
              Assert.IsTrue(MatrixD.AreNumericallyEqual(m, m * inverse * m));
        }
예제 #14
0
 public void Clone()
 {
     MatrixD m = new MatrixD(3, 4, rowMajor, MatrixOrder.RowMajor);
       var o = m.Clone();
       Assert.AreEqual(m, o);
 }
예제 #15
0
        public void TryInvert()
        {
            // Regular, square
              MatrixD m = new MatrixD(new double[,] {{1, 2, 3, 4},
                                            {2, 5, 8, 3},
                                            {7, 6, -1, 1},
                                            {4, 9, 7, 7}});
              MatrixD inverse = m.Clone();
              Assert.AreEqual(true, m.TryInvert());
              Assert.IsTrue(MatrixD.AreNumericallyEqual(MatrixD.CreateIdentity(4, 4), m * inverse));

              // Full column rank, rectangular
              m = new MatrixD(new double[,] {{1, 2, 3},
                                    {2, 5, 8},
                                    {7, 6, -1},
                                    {4, 9, 7}});
              inverse = m.Clone();
              Assert.AreEqual(true, m.TryInvert());
              Assert.IsTrue(MatrixD.AreNumericallyEqual(m, m * inverse * m));

              // singular
              m = new MatrixD(new double[,] {{1, 2, 3},
                                    {2, 5, 8},
                                    {3, 7, 11}});
              inverse = m.Clone();
              Assert.AreEqual(false, m.TryInvert());
        }
예제 #16
0
        //--------------------------------------------------------------
        /// <summary>
        /// Creates the LU decomposition of the given matrix.
        /// </summary>
        /// <param name="matrixA">
        /// The matrix A. (Can be rectangular. Number of rows ≥ number of columns.)
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixA"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of rows must be greater than or equal to the number of columns.
        /// </exception>
        public LUDecompositionD(MatrixD matrixA)
        {
            if (matrixA == null)
            throw new ArgumentNullException("matrixA");
              if (matrixA.NumberOfColumns > matrixA.NumberOfRows)
            throw new ArgumentException("The number of rows must be greater than or equal to the number of columns.", "matrixA");

              // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
              _lu = matrixA.Clone();
              _m = matrixA.NumberOfRows;
              _n = matrixA.NumberOfColumns;
              _pivotVector = new int[_m];

              // Initialize with the 0 to m-1.
              for (int i = 0; i < _m; i++)
            _pivotVector[i] = i;

              _pivotSign = 1;

              // Outer loop.
              for (int j = 0; j < _n; j++)
              {
            // Make a copy of the j-th column to localize references.
            double[] luColumnJ = new double[_m];
            for (int i = 0; i < _m; i++)
              luColumnJ[i] = _lu[i, j];

            // Apply previous transformations.
            for (int i = 0; i < _m; i++)
            {
              // Most of the time is spent in the following dot product.
              int kmax = Math.Min(i, j);
              double s = 0;
              for (int k = 0; k < kmax; k++)
            s += _lu[i, k] * luColumnJ[k];

              luColumnJ[i] -= s;
              _lu[i, j] = luColumnJ[i];
            }

            // Find pivot and exchange if necessary.
            int p = j;
            for (int i = j + 1; i < _m; i++)
              if (Math.Abs(luColumnJ[i]) > Math.Abs(luColumnJ[p]))
            p = i;

            // Swap lines p and k.
            if (p != j)
            {
              for (int k = 0; k < _n; k++)
              {
            double dummy = _lu[p, k];
            _lu[p, k] = _lu[j, k];
            _lu[j, k] = dummy;
              }

              MathHelper.Swap(ref _pivotVector[p], ref _pivotVector[j]);

              _pivotSign = -_pivotSign;
            }

            // Compute multipliers.
            if (j < _m && _lu[j, j] != 0)
              for (int i = j + 1; i < _m; i++)
            _lu[i, j] /= _lu[j, j];
              }
        }
예제 #17
0
        /// <summary>
        /// Creates the LU decomposition of the given matrix.
        /// </summary>
        /// <param name="matrixA">
        /// The matrix A. (Can be rectangular. Number of rows ≥ number of columns.)
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixA"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of rows must be greater than or equal to the number of columns.
        /// </exception>
        public LUDecompositionD(MatrixD matrixA)
        {
            if (matrixA == null)
            {
                throw new ArgumentNullException("matrixA");
            }
            if (matrixA.NumberOfColumns > matrixA.NumberOfRows)
            {
                throw new ArgumentException("The number of rows must be greater than or equal to the number of columns.", "matrixA");
            }

            // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
            _lu          = matrixA.Clone();
            _m           = matrixA.NumberOfRows;
            _n           = matrixA.NumberOfColumns;
            _pivotVector = new int[_m];

            // Initialize with the 0 to m-1.
            for (int i = 0; i < _m; i++)
            {
                _pivotVector[i] = i;
            }

            _pivotSign = 1;

            // Outer loop.
            for (int j = 0; j < _n; j++)
            {
                // Make a copy of the j-th column to localize references.
                double[] luColumnJ = new double[_m];
                for (int i = 0; i < _m; i++)
                {
                    luColumnJ[i] = _lu[i, j];
                }

                // Apply previous transformations.
                for (int i = 0; i < _m; i++)
                {
                    // Most of the time is spent in the following dot product.
                    int    kmax = Math.Min(i, j);
                    double s    = 0;
                    for (int k = 0; k < kmax; k++)
                    {
                        s += _lu[i, k] * luColumnJ[k];
                    }

                    luColumnJ[i] -= s;
                    _lu[i, j]     = luColumnJ[i];
                }

                // Find pivot and exchange if necessary.
                int p = j;
                for (int i = j + 1; i < _m; i++)
                {
                    if (Math.Abs(luColumnJ[i]) > Math.Abs(luColumnJ[p]))
                    {
                        p = i;
                    }
                }

                // Swap lines p and k.
                if (p != j)
                {
                    for (int k = 0; k < _n; k++)
                    {
                        double dummy = _lu[p, k];
                        _lu[p, k] = _lu[j, k];
                        _lu[j, k] = dummy;
                    }

                    MathHelper.Swap(ref _pivotVector[p], ref _pivotVector[j]);

                    _pivotSign = -_pivotSign;
                }

                // Compute multipliers.
                if (j < _m && _lu[j, j] != 0)
                {
                    for (int i = j + 1; i < _m; i++)
                    {
                        _lu[i, j] /= _lu[j, j];
                    }
                }
            }
        }
예제 #18
0
        //--------------------------------------------------------------
        /// <summary>
        /// Solves the equation <c>A * X = B</c>.
        /// </summary>
        /// <param name="matrixB">The matrix B with as many rows as A and any number of columns.</param>
        /// <returns>X, so that <c>A * X = B</c>.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixB"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of rows does not match.
        /// </exception>
        /// <exception cref="MathematicsException">
        /// The matrix A is not symmetric and positive definite.
        /// </exception>
        public MatrixD SolveLinearEquations(MatrixD matrixB)
        {
            if (matrixB == null)
            throw new ArgumentNullException("matrixB");
              if (matrixB.NumberOfRows != L.NumberOfRows)
            throw new ArgumentException("The number of rows does not match.", "matrixB");
              if (IsSymmetricPositiveDefinite == false)
            throw new MathematicsException("The original matrix A is not symmetric and positive definite.");

              // Initialize x as a copy of B.
              MatrixD x = matrixB.Clone();

              // Solve L*Y = B.
              for (int k = 0; k < L.NumberOfRows; k++)
              {
            for (int j = 0; j < matrixB.NumberOfColumns; j++)
            {
              for (int i = 0; i < k; i++)
            x[k, j] -= x[i, j] * L[k, i];
              x[k, j] /= L[k, k];
            }
              }

              // Solve transpose(L) * X = Y.
              for (int k = L.NumberOfRows - 1; k >= 0; k--)
              {
            for (int j = 0; j < matrixB.NumberOfColumns; j++)
            {
              for (int i = k + 1; i < L.NumberOfRows; i++)
            x[k, j] -= x[i, j] * L[i, k];
              x[k, j] /= L[k, k];
            }
              }

              return x;
        }