예제 #1
0
        public void SolveMatrix()
        {
            DoubleMatrix b = new DoubleMatrix(3);

            b[0, 0] = 2;
            b[0, 1] = 2;
            b[0, 2] = 2;
            b[1, 0] = 13;
            b[1, 1] = 13;
            b[1, 2] = 13;
            b[2, 0] = 25;
            b[2, 1] = 25;
            b[2, 2] = 25;
            DoubleMatrix x = lu.Solve(b);

            Assert.AreEqual(x[0, 0], 2.965, TOLERENCE);
            Assert.AreEqual(x[0, 1], 2.965, TOLERENCE);
            Assert.AreEqual(x[0, 2], 2.965, TOLERENCE);
            Assert.AreEqual(x[1, 0], -0.479, TOLERENCE);
            Assert.AreEqual(x[1, 1], -0.479, TOLERENCE);
            Assert.AreEqual(x[1, 2], -0.479, TOLERENCE);
            Assert.AreEqual(x[2, 0], 1.227, TOLERENCE);
            Assert.AreEqual(x[2, 1], 1.227, TOLERENCE);
            Assert.AreEqual(x[2, 2], 1.227, TOLERENCE);

            b       = new DoubleMatrix(3, 2);
            b[0, 0] = 2;
            b[0, 1] = 2;
            b[1, 0] = 13;
            b[1, 1] = 13;
            b[2, 0] = 25;
            b[2, 1] = 25;
            x       = lu.Solve(b);
            Assert.AreEqual(x[0, 0], 2.965, TOLERENCE);
            Assert.AreEqual(x[0, 1], 2.965, TOLERENCE);
            Assert.AreEqual(x[1, 0], -0.479, TOLERENCE);
            Assert.AreEqual(x[1, 1], -0.479, TOLERENCE);
            Assert.AreEqual(x[2, 0], 1.227, TOLERENCE);
            Assert.AreEqual(x[2, 1], 1.227, TOLERENCE);

            b       = new DoubleMatrix(3, 4);
            b[0, 0] = 2;
            b[0, 1] = 2;
            b[0, 2] = 2;
            b[0, 3] = 2;
            b[1, 0] = 13;
            b[1, 1] = 13;
            b[1, 2] = 13;
            b[1, 3] = 13;
            b[2, 0] = 25;
            b[2, 1] = 25;
            b[2, 2] = 25;
            b[2, 3] = 25;
            x       = lu.Solve(b);
            Assert.AreEqual(x[0, 0], 2.965, TOLERENCE);
            Assert.AreEqual(x[0, 1], 2.965, TOLERENCE);
            Assert.AreEqual(x[0, 2], 2.965, TOLERENCE);
            Assert.AreEqual(x[0, 3], 2.965, TOLERENCE);
            Assert.AreEqual(x[1, 0], -0.479, TOLERENCE);
            Assert.AreEqual(x[1, 1], -0.479, TOLERENCE);
            Assert.AreEqual(x[1, 2], -0.479, TOLERENCE);
            Assert.AreEqual(x[1, 3], -0.479, TOLERENCE);
            Assert.AreEqual(x[2, 0], 1.227, TOLERENCE);
            Assert.AreEqual(x[2, 1], 1.227, TOLERENCE);
            Assert.AreEqual(x[2, 2], 1.227, TOLERENCE);
            Assert.AreEqual(x[2, 3], 1.227, TOLERENCE);
        }
		public static void Test01e_2()
		{
			var X = new DoubleMatrix(new double[,] { { 73, 746, 743, 106 }, { 584, 531, 420, 579 }, { 255, 562, 234, 693 }, { 360, 474, 381, 484 }, { 301, 78, 68, 313 } });
			var y = new DoubleMatrix(new double[,] { { 803 }, { 292 }, { 230 }, { 469 }, { 655 } });

			var XtX = X.GetTranspose() * X;
			var Xty = X.GetTranspose() * y;

			var solver = new DoubleLUDecomp(XtX);
			var expected = solver.Solve(Xty);

			IMatrix x, w;
			FastNonnegativeLeastSquares.Execution(XtX, Xty, (i) => false, null, out x, out w);

			Assert.AreEqual(expected[0, 0], x[0, 0], 1e-4);
			Assert.AreEqual(expected[1, 0], x[1, 0], 1e-4);
			Assert.AreEqual(expected[2, 0], x[2, 0], 1e-4);
			Assert.AreEqual(expected[3, 0], x[3, 0], 1e-4);

			Assert.AreEqual(0, w[0, 0], 1e-8);
			Assert.AreEqual(0, w[1, 0], 1e-8);
			Assert.AreEqual(0, w[2, 0], 1e-8);
			Assert.AreEqual(0, w[3, 0], 1e-8);
		}
예제 #3
0
		/// <summary>
		/// Calculate the matrix for the polyharmonic spline and solves the linear equation to calculate the coefficients.
		/// </summary>
		private void InternalCompute()
		{
			var N = _numberOfControlPoints;

			// Allocate the matrix and vector
			var mtx_l = new DoubleMatrix(N + 1 + _coordDim, N + 1 + _coordDim);

			// there is no need for this matrix if we don't need to calculate the bending energy
			_mtx_orig_k = new DoubleMatrix(N, N);

			// Fill K (p x p, upper left of L)
			// K is symmetrical so we really have to calculate only about half of the coefficients.
			double a = 0.0;
			for (int i = 0; i < N; ++i)
			{
				for (int j = i + 1; j < N; ++j)
				{
					double distance = DistanceBetweenControlPoints(i, j);
					mtx_l[i, j] = mtx_l[j, i] = _mtx_orig_k[i, j] = _mtx_orig_k[j, i] = _cachedTpsFunc(distance);
					a += distance * 2; // same for upper & lower triangle
				}
			}
			a /= ((double)N) * N;

			// Fill the rest of L with the values to do regularization and linear interpolation
			for (int i = 0; i < N; ++i)
			{
				// diagonal: regularization parameter (lambda * a^2)
				mtx_l[i, i] = _mtx_orig_k[i, i] = _regularizationParameter * (a * a);

				// P (N x (nCoordDim+1), upper right)
				mtx_l[i, N + 0] = 1; // for the intercept
				for (int d = 0; d < _coordDim; d++)
					mtx_l[i, N + 1 + d] = _coordinates[d][i];

				// P transposed ((nCoordDim+1) x N, bottom left)
				mtx_l[N + 0, i] = 1; // for the intercept
				for (int d = 0; d < _coordDim; ++d)
					mtx_l[N + 1 + d, i] = _coordinates[d][i];
			}
			// Zero ((nCoordDim+1) x (nCoordDim+1), lower right)
			for (int i = N; i < N + _coordDim + 1; ++i)
				for (int j = N; j < N + _coordDim + 1; ++j)
					mtx_l[i, j] = 0;

			// Solve the linear system
			var solver = new DoubleLUDecomp(mtx_l);
			if (solver.IsSingular)
				throw new ArgumentException("The provided points lead to a singular matrix");

			// Fill the right hand vector V with the values to spline; the last nCoordDim+1 elements are zero
			_mtx_v = new DoubleVector(N + 1 + _coordDim);
			for (int i = 0; i < N; ++i)
				_mtx_v[i] = _values[i];
			for (int d = 0; d <= _coordDim; ++d) // comparison '<=' is ok here because of additional intercept
				_mtx_v[N + d] = 0;

			_mtx_v = solver.Solve(_mtx_v);
		}
예제 #4
0
        /// <summary>
        /// Calculate the matrix for the polyharmonic spline and solves the linear equation to calculate the coefficients.
        /// </summary>
        private void InternalCompute()
        {
            var N = _numberOfControlPoints;

            // Allocate the matrix and vector
            var mtx_l = new DoubleMatrix(N + 1 + _coordDim, N + 1 + _coordDim);

            // there is no need for this matrix if we don't need to calculate the bending energy
            _mtx_orig_k = new DoubleMatrix(N, N);

            // Fill K (p x p, upper left of L)
            // K is symmetrical so we really have to calculate only about half of the coefficients.
            double a = 0.0;

            for (int i = 0; i < N; ++i)
            {
                for (int j = i + 1; j < N; ++j)
                {
                    double distance = DistanceBetweenControlPoints(i, j);
                    mtx_l[i, j] = mtx_l[j, i] = _mtx_orig_k[i, j] = _mtx_orig_k[j, i] = _cachedTpsFunc(distance);
                    a          += distance * 2; // same for upper & lower triangle
                }
            }
            a /= ((double)N) * N;

            // Fill the rest of L with the values to do regularization and linear interpolation
            for (int i = 0; i < N; ++i)
            {
                // diagonal: regularization parameter (lambda * a^2)
                mtx_l[i, i] = _mtx_orig_k[i, i] = _regularizationParameter * (a * a);

                // P (N x (nCoordDim+1), upper right)
                mtx_l[i, N + 0] = 1; // for the intercept
                for (int d = 0; d < _coordDim; d++)
                {
                    mtx_l[i, N + 1 + d] = _coordinates[d][i];
                }

                // P transposed ((nCoordDim+1) x N, bottom left)
                mtx_l[N + 0, i] = 1; // for the intercept
                for (int d = 0; d < _coordDim; ++d)
                {
                    mtx_l[N + 1 + d, i] = _coordinates[d][i];
                }
            }
            // Zero ((nCoordDim+1) x (nCoordDim+1), lower right)
            for (int i = N; i < N + _coordDim + 1; ++i)
            {
                for (int j = N; j < N + _coordDim + 1; ++j)
                {
                    mtx_l[i, j] = 0;
                }
            }

            // Solve the linear system
            var solver = new DoubleLUDecomp(mtx_l);

            if (solver.IsSingular)
            {
                throw new ArgumentException("The provided points lead to a singular matrix");
            }

            // Fill the right hand vector V with the values to spline; the last nCoordDim+1 elements are zero
            _mtx_v = new DoubleVector(N + 1 + _coordDim);
            for (int i = 0; i < N; ++i)
            {
                _mtx_v[i] = _values[i];
            }
            for (int d = 0; d <= _coordDim; ++d) // comparison '<=' is ok here because of additional intercept
            {
                _mtx_v[N + d] = 0;
            }

            _mtx_v = solver.Solve(_mtx_v);
        }
예제 #5
-1
		/// <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 XtX, IROMatrix Xty, Func<int, bool> isRestrictedToPositiveValues, double? tolerance, out IMatrix x, out IMatrix 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.Rows != XtX.Columns)
				throw new ArgumentException("Matrix should be a square matrix", nameof(XtX));
			if (Xty.Columns != 1)
				throw new ArgumentException(nameof(Xty) + " should be a column vector (number of columns should be equal to 1)", nameof(Xty));
			if (Xty.Rows != XtX.Columns)
				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.Rows, XtX.Columns);

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

			// 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);
			}
		}