Exemple #1
0
        public Vector <double> SeidelMethod(Matrix <double> A, Vector <double> B, double eps)
        {
            Vector <double> X     = new DenseVector(A.RowCount);
            Vector <double> TempX = new DenseVector(A.RowCount);
            int             count = 0;

            do
            {
                TempX = X.Clone();
                for (int i = 0; i < A.RowCount; ++i)
                {
                    double var = 0;
                    for (int j = 0; j < i; j++)
                    {
                        var += (A[i, j] * X[j]);
                    }
                    for (int j = i + 1; j < A.RowCount; ++j)
                    {
                        var += (A[i, j] * TempX[j]);
                    }
                    X[i] = (B[i] - var) / A[i, i];
                }
                if (++count == 1000)
                {
                    break;
                }
            } while ((X - TempX).L2Norm() > eps);
            Console.WriteLine(count);
            return(X);
        }
Exemple #2
0
 public HistogramDataAndProperties(DenseVector data, int countOfBins = 10)
 {
     dvData      = (DenseVector)data.Clone();
     binsCount   = countOfBins;
     color       = Color.Black;
     description = "histogram";
     stats       = new DescriptiveStatistics(dvData);
     calculateProbDens();
     CalculateQuantiles();
 }
Exemple #3
0
 public HistogramDataAndProperties()
 {
     dvData        = DenseVector.Create(1, i => 0.0d);
     binsCount     = 1;
     color         = Color.Black;
     description   = "histogram";
     dvbinsCenters = (DenseVector)dvData.Clone();
     stats         = new DescriptiveStatistics(dvData);
     calculateProbDens();
     CalculateQuantiles();
 }
Exemple #4
0
        public T Clone()
        {
            var r = new T();

            r.A = (DenseMatrix)A.Clone();
            r.B = (DenseVector)B.Clone();
            r.C = (DenseVector)C.Clone();
            if (J != null)
            {
                r.J = new List <int> (J);
            }
            r.N  = N;
            r.M  = M;
            r.DL = (DenseVector)DL.Clone();
            r.DR = (DenseVector)DR.Clone();
            return(r);
        }
        public static DenseVector ExponentialMovingAverage(DenseVector dvValues, int gap = 10, double smoothingParameter = 0.4d)
        {
            DenseVector dvOutValues = (DenseVector)dvValues.Clone();

            dvOutValues.MapIndexedInplace(new Func <int, double, double>((i, x) =>
            {
                DenseVector dvWeights = DenseVector.Create(1 + gap * 2, new Func <int, double>(j =>
                {
                    int k = j - gap;
                    if (i + k < 0)
                    {
                        return(0.0d);
                    }
                    if (i + k >= dvOutValues.Count)
                    {
                        return(0.0d);
                    }
                    return(Math.Exp(-Math.Abs(k) * smoothingParameter));
                }));
                //dvWeights.MapIndexedInplace(new Func<int,double,double>((j, dVal) =>
                //{
                //    if (double.IsNaN(dvValues[])) return 0.0d;
                //}))
                double sum = dvWeights.Sum();
                dvWeights.MapInplace(new Func <double, double>(d => d / sum));

                double retVal = 0.0d;
                for (int n = 0; n < 1 + gap * 2; n++)
                {
                    int m = n - gap + i;
                    if ((m < 0) || (m >= dvOutValues.Count))
                    {
                        continue;
                    }
                    double weight = dvWeights[n];
                    retVal       += weight * dvValues[m];
                }
                return(retVal);
            }));
            return(dvOutValues);
        }
Exemple #6
0
        public GroupingQueryResult(List <UserQueryResult> InputList, List <string> ADGroupNames, string Name, string TypeName) : base(new DenseVector(InputList[0].ReturnAccessVector().Count))
        {
            groupingName     = Name;
            groupingType     = TypeName;
            groupMemberCount = InputList.Count;
            List <string> MembersList = new List <string>();

            Vector InterimAccessVector = new DenseVector(InputList[0].ReturnAccessVector().Count);

            foreach (UserQueryResult UQR in InputList)
            {
                if (UQR != null)
                {
                    InterimAccessVector = (Vector)(InterimAccessVector + UQR.ReturnAccessVector());
                    MembersList.Add(UQR.AccountName);
                }
            }
            members             = HelperFunctions.StringListToCommaSeparatedString(MembersList);
            accessSummaryVector = (Vector)(InterimAccessVector / groupMemberCount);
            aDGroupsRepresented = HelperFunctions.StringListToCommaSeparatedString(ReturnAccessList(ADGroupNames));
            rawCountVector      = (Vector)InterimAccessVector.Clone();
        }
Exemple #7
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
        /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
        /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
        public void Solve(Matrix matrix, Vector input, Vector result)
        {
            // If we were stopped before, we are no longer
            // We're doing this at the start of the method to ensure
            // that we can use these fields immediately.
            _hasBeenStopped = false;

            // Parameters checks
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch<ArgumentException>(input, result);
            }

            // Initialize the solver fields
            // Set the convergence monitor
            if (_iterator == null)
            {
                _iterator = Iterator.CreateDefault();
            }

            if (_preconditioner == null)
            {
                _preconditioner = new UnitPreconditioner();
            }
            
            _preconditioner.Initialize(matrix);
            
            // Compute r_0 = b - Ax_0 for some initial guess x_0
            // In this case we take x_0 = vector
            // This is basically a SAXPY so it could be made a lot faster
            Vector residuals = new DenseVector(matrix.RowCount);
            CalculateTrueResidual(matrix, residuals, result, input);

            // Choose r~ (for example, r~ = r_0)
            var tempResiduals = residuals.Clone();

            // create seven temporary vectors needed to hold temporary
            // coefficients. All vectors are mangled in each iteration.
            // These are defined here to prevent stressing the garbage collector
            Vector vecP = new DenseVector(residuals.Count);
            Vector vecPdash = new DenseVector(residuals.Count);
            Vector nu = new DenseVector(residuals.Count);
            Vector vecS = new DenseVector(residuals.Count);
            Vector vecSdash = new DenseVector(residuals.Count);
            Vector temp = new DenseVector(residuals.Count);
            Vector temp2 = new DenseVector(residuals.Count);

            // create some temporary double variables that are needed
            // to hold values in between iterations
            Complex currentRho = 0;
            Complex alpha = 0;
            Complex omega = 0;

            var iterationNumber = 0;
            while (ShouldContinue(iterationNumber, result, input, residuals))
            {
                // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
                var oldRho = currentRho;
                currentRho = tempResiduals.DotProduct(residuals);

                // if (rho_(i-1) == 0) // METHOD FAILS
                // If rho is only 1 ULP from zero then we fail.
                if (currentRho.Real.AlmostEqual(0, 1) && currentRho.Imaginary.AlmostEqual(0, 1))
                {
                    // Rho-type breakdown
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                if (iterationNumber != 0)
                {
                    // beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
                    var beta = (currentRho / oldRho) * (alpha / omega);

                    // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
                    nu.Multiply(-omega, temp);
                    vecP.Add(temp, temp2);
                    temp2.CopyTo(vecP);

                    vecP.Multiply(beta, vecP);
                    vecP.Add(residuals, temp2);
                    temp2.CopyTo(vecP);
                }
                else
                {
                    // p_i = r_(i-1)
                    residuals.CopyTo(vecP);
                }

                // SOLVE Mp~ = p_i // M = preconditioner
                _preconditioner.Approximate(vecP, vecPdash);
                
                // nu_i = Ap~
                matrix.Multiply(vecPdash, nu);

                // alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
                alpha = currentRho * 1 / tempResiduals.DotProduct(nu);

                // s = r_(i-1) - alpha_i nu_i
                nu.Multiply(-alpha, temp);
                residuals.Add(temp, vecS);

                // Check if we're converged. If so then stop. Otherwise continue;
                // Calculate the temporary result. 
                // Be careful not to change any of the temp vectors, except for
                // temp. Others will be used in the calculation later on.
                // x_i = x_(i-1) + alpha_i * p^_i + s^_i
                vecPdash.Multiply(alpha, temp);
                temp.Add(vecSdash, temp2);
                temp2.CopyTo(temp);
                temp.Add(result, temp2);
                temp2.CopyTo(temp);

                // Check convergence and stop if we are converged.
                if (!ShouldContinue(iterationNumber, temp, input, vecS))
                {
                    temp.CopyTo(result);

                    // Calculate the true residual
                    CalculateTrueResidual(matrix, residuals, result, input);

                    // Now recheck the convergence
                    if (!ShouldContinue(iterationNumber, result, input, residuals))
                    {
                        // We're all good now.
                        return;
                    }

                    // Continue the calculation
                    iterationNumber++;
                    continue;
                }

                // SOLVE Ms~ = s
                _preconditioner.Approximate(vecS, vecSdash);

                // temp = As~
                matrix.Multiply(vecSdash, temp);

                // omega_i = temp^T s / temp^T temp
                omega = temp.DotProduct(vecS) / temp.DotProduct(temp);

                // x_i = x_(i-1) + alpha_i p^ + omega_i s^
                temp.Multiply(-omega, residuals);
                residuals.Add(vecS, temp2);
                temp2.CopyTo(residuals);

                vecSdash.Multiply(omega, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                vecPdash.Multiply(alpha, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                // for continuation it is necessary that omega_i != 0.0
                // If omega is only 1 ULP from zero then we fail.
                if (omega.Real.AlmostEqual(0, 1) && omega.Imaginary.AlmostEqual(0, 1))
                {
                    // Omega-type breakdown
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                if (!ShouldContinue(iterationNumber, result, input, residuals))
                {
                    // Recalculate the residuals and go round again. This is done to ensure that
                    // we have the proper residuals.
                    // The residual calculation based on omega_i * s can be off by a factor 10. So here
                    // we calculate the real residual (which can be expensive) but we only do it if we're
                    // sufficiently close to the finish.
                    CalculateTrueResidual(matrix, residuals, result, input);
                }

                iterationNumber++;
            }
        }
Exemple #8
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
        /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
        /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
        public void Solve(Matrix <float> matrix, Vector <float> input, Vector <float> result)
        {
            // If we were stopped before, we are no longer
            // We're doing this at the start of the method to ensure
            // that we can use these fields immediately.
            _hasBeenStopped = false;

            // Parameters checks
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(input, matrix);
            }

            // Initialize the solver fields
            // Set the convergence monitor
            if (_iterator == null)
            {
                _iterator = Iterator.CreateDefault();
            }

            if (_preconditioner == null)
            {
                _preconditioner = new UnitPreconditioner <float>();
            }

            _preconditioner.Initialize(matrix);

            // Compute r_0 = b - Ax_0 for some initial guess x_0
            // In this case we take x_0 = vector
            // This is basically a SAXPY so it could be made a lot faster
            var residuals = new DenseVector(matrix.RowCount);

            CalculateTrueResidual(matrix, residuals, result, input);

            // Choose r~ (for example, r~ = r_0)
            var tempResiduals = residuals.Clone();

            // create seven temporary vectors needed to hold temporary
            // coefficients. All vectors are mangled in each iteration.
            // These are defined here to prevent stressing the garbage collector
            var vecP     = new DenseVector(residuals.Count);
            var vecPdash = new DenseVector(residuals.Count);
            var nu       = new DenseVector(residuals.Count);
            var vecS     = new DenseVector(residuals.Count);
            var vecSdash = new DenseVector(residuals.Count);
            var temp     = new DenseVector(residuals.Count);
            var temp2    = new DenseVector(residuals.Count);

            // create some temporary float variables that are needed
            // to hold values in between iterations
            float currentRho = 0;
            float alpha      = 0;
            float omega      = 0;

            var iterationNumber = 0;

            while (ShouldContinue(iterationNumber, result, input, residuals))
            {
                // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
                var oldRho = currentRho;
                currentRho = tempResiduals.DotProduct(residuals);

                // if (rho_(i-1) == 0) // METHOD FAILS
                // If rho is only 1 ULP from zero then we fail.
                if (currentRho.AlmostEqual(0, 1))
                {
                    // Rho-type breakdown
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                if (iterationNumber != 0)
                {
                    // beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
                    var beta = (currentRho / oldRho) * (alpha / omega);

                    // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
                    nu.Multiply(-omega, temp);
                    vecP.Add(temp, temp2);
                    temp2.CopyTo(vecP);

                    vecP.Multiply(beta, vecP);
                    vecP.Add(residuals, temp2);
                    temp2.CopyTo(vecP);
                }
                else
                {
                    // p_i = r_(i-1)
                    residuals.CopyTo(vecP);
                }

                // SOLVE Mp~ = p_i // M = preconditioner
                _preconditioner.Approximate(vecP, vecPdash);

                // nu_i = Ap~
                matrix.Multiply(vecPdash, nu);

                // alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
                alpha = currentRho * 1 / tempResiduals.DotProduct(nu);

                // s = r_(i-1) - alpha_i nu_i
                nu.Multiply(-alpha, temp);
                residuals.Add(temp, vecS);

                // Check if we're converged. If so then stop. Otherwise continue;
                // Calculate the temporary result.
                // Be careful not to change any of the temp vectors, except for
                // temp. Others will be used in the calculation later on.
                // x_i = x_(i-1) + alpha_i * p^_i + s^_i
                vecPdash.Multiply(alpha, temp);
                temp.Add(vecSdash, temp2);
                temp2.CopyTo(temp);
                temp.Add(result, temp2);
                temp2.CopyTo(temp);

                // Check convergence and stop if we are converged.
                if (!ShouldContinue(iterationNumber, temp, input, vecS))
                {
                    temp.CopyTo(result);

                    // Calculate the true residual
                    CalculateTrueResidual(matrix, residuals, result, input);

                    // Now recheck the convergence
                    if (!ShouldContinue(iterationNumber, result, input, residuals))
                    {
                        // We're all good now.
                        return;
                    }

                    // Continue the calculation
                    iterationNumber++;
                    continue;
                }

                // SOLVE Ms~ = s
                _preconditioner.Approximate(vecS, vecSdash);

                // temp = As~
                matrix.Multiply(vecSdash, temp);

                // omega_i = temp^T s / temp^T temp
                omega = temp.DotProduct(vecS) / temp.DotProduct(temp);

                // x_i = x_(i-1) + alpha_i p^ + omega_i s^
                temp.Multiply(-omega, residuals);
                residuals.Add(vecS, temp2);
                temp2.CopyTo(residuals);

                vecSdash.Multiply(omega, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                vecPdash.Multiply(alpha, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                // for continuation it is necessary that omega_i != 0.0
                // If omega is only 1 ULP from zero then we fail.
                if (omega.AlmostEqual(0, 1))
                {
                    // Omega-type breakdown
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                if (!ShouldContinue(iterationNumber, result, input, residuals))
                {
                    // Recalculate the residuals and go round again. This is done to ensure that
                    // we have the proper residuals.
                    // The residual calculation based on omega_i * s can be off by a factor 10. So here
                    // we calculate the real residual (which can be expensive) but we only do it if we're
                    // sufficiently close to the finish.
                    CalculateTrueResidual(matrix, residuals, result, input);
                }

                iterationNumber++;
            }
        }
Exemple #9
0
 /// <summary>
 /// Clones this unnormalised discrete distribution.
 /// </summary>
 /// <returns>An object which is a clone of the current instance. This must be cast
 /// if you want to assign the result to a UnnormalizedDiscrete type</returns>
 public object Clone()
 {
     return(FromLogProbs((DenseVector)logProb.Clone()));
 }
Exemple #10
0
        /// <summary>
        /// Run example
        /// </summary>
        public void Run()
        {
            // Format vector output to console
            var formatProvider = (CultureInfo)CultureInfo.InvariantCulture.Clone();

            formatProvider.TextInfo.ListSeparator = " ";

            // Create new empty vector
            var vectorA = new DenseVector(10);

            Console.WriteLine(@"Empty vector A");
            Console.WriteLine(vectorA.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 1. Fill vector by data using indexer []
            for (var i = 0; i < vectorA.Count; i++)
            {
                vectorA[i] = i;
            }

            Console.WriteLine(@"1. Fill vector by data using indexer []");
            Console.WriteLine(vectorA.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 2. Fill vector by data using SetValues method
            vectorA.SetValues(new[] { 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0 });
            Console.WriteLine(@"2. Fill vector by data using SetValues method");
            Console.WriteLine(vectorA.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 3. Convert Vector to double[]
            var data = vectorA.ToArray();

            Console.WriteLine(@"3. Convert vector to double array");
            for (var i = 0; i < data.Length; i++)
            {
                Console.Write(data[i].ToString("#0.00\t", formatProvider) + @" ");
            }

            Console.WriteLine();
            Console.WriteLine();

            // 4. Convert Vector to column matrix. A matrix based on this vector in column form (one single column)
            var columnMatrix = vectorA.ToColumnMatrix();

            Console.WriteLine(@"4. Convert vector to column matrix");
            Console.WriteLine(columnMatrix.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 5. Convert Vector to row matrix. A matrix based on this vector in row form (one single row)
            var rowMatrix = vectorA.ToRowMatrix();

            Console.WriteLine(@"5. Convert vector to row matrix");
            Console.WriteLine(rowMatrix.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 6. Clone vector
            var cloneA = vectorA.Clone();

            Console.WriteLine(@"6. Clone vector");
            Console.WriteLine(cloneA.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 7. Clear vector
            cloneA.Clear();
            Console.WriteLine(@"7. Clear vector");
            Console.WriteLine(cloneA.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 8. Copy part of vector into another vector. If you need to copy all data then use CopoTy(vector) method.
            vectorA.CopyTo(cloneA, 3, 3, 4);
            Console.WriteLine(@"8. Copy part of vector into another vector");
            Console.WriteLine(cloneA.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 9. Get part of vector as another vector
            var subvector = vectorA.SubVector(0, 5);

            Console.WriteLine(@"9. Get subvector");
            Console.WriteLine(subvector.ToString("#0.00\t", formatProvider));
            Console.WriteLine();

            // 10. Enumerator usage
            Console.WriteLine(@"10. Enumerator usage");
            foreach (var value in vectorA)
            {
                Console.Write(value.ToString("#0.00\t", formatProvider) + @" ");
            }

            Console.WriteLine();
            Console.WriteLine();

            // 11. Indexed enumerator usage
            Console.WriteLine(@"11. Enumerator usage");
            foreach (var value in vectorA.GetIndexedEnumerator())
            {
                Console.WriteLine(@"Index = {0}; Value = {1}", value.Item1, value.Item2.ToString("#0.00\t", formatProvider));
            }

            Console.WriteLine();
        }
Exemple #11
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
        /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
        /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public void Solve(Matrix <Maths.Complex32> matrix, Vector <Maths.Complex32> input, Vector <Maths.Complex32> result, Iterator <Maths.Complex32> iterator, IPreconditioner <Maths.Complex32> preconditioner)
        {
            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException("Matrix must be square.", nameof(matrix));
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException("All vectors must have the same dimensionality.");
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(input, matrix);
            }

            if (iterator == null)
            {
                iterator = new Iterator <Maths.Complex32>();
            }

            if (preconditioner == null)
            {
                preconditioner = new UnitPreconditioner <Maths.Complex32>();
            }

            preconditioner.Initialize(matrix);

            // Compute r_0 = b - Ax_0 for some initial guess x_0
            // In this case we take x_0 = vector
            // This is basically a SAXPY so it could be made a lot faster
            var residuals = new DenseVector(matrix.RowCount);

            CalculateTrueResidual(matrix, residuals, result, input);

            // Choose r~ (for example, r~ = r_0)
            var tempResiduals = residuals.Clone();

            // create seven temporary vectors needed to hold temporary
            // coefficients. All vectors are mangled in each iteration.
            // These are defined here to prevent stressing the garbage collector
            var vecP     = new DenseVector(residuals.Count);
            var vecPdash = new DenseVector(residuals.Count);
            var nu       = new DenseVector(residuals.Count);
            var vecS     = new DenseVector(residuals.Count);
            var vecSdash = new DenseVector(residuals.Count);
            var temp     = new DenseVector(residuals.Count);
            var temp2    = new DenseVector(residuals.Count);

            // create some temporary float variables that are needed
            // to hold values in between iterations
            Maths.Complex32 currentRho = 0;
            Maths.Complex32 alpha      = 0;
            Maths.Complex32 omega      = 0;

            var iterationNumber = 0;

            while (iterator.DetermineStatus(iterationNumber, result, input, residuals) == IterationStatus.Continue)
            {
                // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
                var oldRho = currentRho;
                currentRho = tempResiduals.ConjugateDotProduct(residuals);

                // if (rho_(i-1) == 0) // METHOD FAILS
                // If rho is only 1 ULP from zero then we fail.
                if (currentRho.Real.AlmostEqualNumbersBetween(0, 1) && currentRho.Imaginary.AlmostEqualNumbersBetween(0, 1))
                {
                    // Rho-type breakdown
                    throw new NumericalBreakdownException();
                }

                if (iterationNumber != 0)
                {
                    // beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
                    var beta = (currentRho / oldRho) * (alpha / omega);

                    // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
                    nu.Multiply(-omega, temp);
                    vecP.Add(temp, temp2);
                    temp2.CopyTo(vecP);

                    vecP.Multiply(beta, vecP);
                    vecP.Add(residuals, temp2);
                    temp2.CopyTo(vecP);
                }
                else
                {
                    // p_i = r_(i-1)
                    residuals.CopyTo(vecP);
                }

                // SOLVE Mp~ = p_i // M = preconditioner
                preconditioner.Approximate(vecP, vecPdash);

                // nu_i = Ap~
                matrix.Multiply(vecPdash, nu);

                // alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
                alpha = currentRho * 1 / tempResiduals.ConjugateDotProduct(nu);

                // s = r_(i-1) - alpha_i nu_i
                nu.Multiply(-alpha, temp);
                residuals.Add(temp, vecS);

                // Check if we're converged. If so then stop. Otherwise continue;
                // Calculate the temporary result.
                // Be careful not to change any of the temp vectors, except for
                // temp. Others will be used in the calculation later on.
                // x_i = x_(i-1) + alpha_i * p^_i + s^_i
                vecPdash.Multiply(alpha, temp);
                temp.Add(vecSdash, temp2);
                temp2.CopyTo(temp);
                temp.Add(result, temp2);
                temp2.CopyTo(temp);

                // Check convergence and stop if we are converged.
                if (iterator.DetermineStatus(iterationNumber, temp, input, vecS) != IterationStatus.Continue)
                {
                    temp.CopyTo(result);

                    // Calculate the true residual
                    CalculateTrueResidual(matrix, residuals, result, input);

                    // Now recheck the convergence
                    if (iterator.DetermineStatus(iterationNumber, result, input, residuals) != IterationStatus.Continue)
                    {
                        // We're all good now.
                        return;
                    }

                    // Continue the calculation
                    iterationNumber++;
                    continue;
                }

                // SOLVE Ms~ = s
                preconditioner.Approximate(vecS, vecSdash);

                // temp = As~
                matrix.Multiply(vecSdash, temp);

                // omega_i = temp^T s / temp^T temp
                omega = temp.ConjugateDotProduct(vecS) / temp.ConjugateDotProduct(temp);

                // x_i = x_(i-1) + alpha_i p^ + omega_i s^
                temp.Multiply(-omega, residuals);
                residuals.Add(vecS, temp2);
                temp2.CopyTo(residuals);

                vecSdash.Multiply(omega, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                vecPdash.Multiply(alpha, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                // for continuation it is necessary that omega_i != 0.0f
                // If omega is only 1 ULP from zero then we fail.
                if (omega.Real.AlmostEqualNumbersBetween(0, 1) && omega.Imaginary.AlmostEqualNumbersBetween(0, 1))
                {
                    // Omega-type breakdown
                    throw new NumericalBreakdownException();
                }

                if (iterator.DetermineStatus(iterationNumber, result, input, residuals) != IterationStatus.Continue)
                {
                    // Recalculate the residuals and go round again. This is done to ensure that
                    // we have the proper residuals.
                    // The residual calculation based on omega_i * s can be off by a factor 10. So here
                    // we calculate the real residual (which can be expensive) but we only do it if we're
                    // sufficiently close to the finish.
                    CalculateTrueResidual(matrix, residuals, result, input);
                }

                iterationNumber++;
            }
        }
Exemple #12
0
        public static Vector Fit(Matrix input, Vector y)
        {
            if (input == null || y == null)
            {
                throw new ArgumentNullException("输入不能为空");
            }
            if (input.RowCount != y.Count)
            {
                throw new ArgumentException("输入的长度不一致");
            }
            //tol = 10*eps*norm(C,1)*length(C);
            // norm(C,1) = sum(abs(C))
            var norm = new DenseVector(input.ColumnCount);

            for (int i = 0; i < input.RowCount; i++)
            {
                for (int j = 0; j < input.ColumnCount; j++)
                {
                    norm[j] += Math.Abs(input[i, j]);
                }
            }

            var tol = 10 * Single.Epsilon * norm.Sum() * input.RowCount;


            var P = new DenseVector(input.ColumnCount);
            var Z = new DenseVector(input.ColumnCount);

            for (int i = 1; i <= Z.Count; i++)
            {
                Z[i - 1] = i;
            }
            var ra    = P.Clone();
            var ZZ    = Z.Clone();
            var resid = y - input * ra;
            var w     = input.Transpose() * resid;


            // set up iteration criterion
            var outeriter = 0;
            var iter      = 0;
            var itmax     = 3 * input.ColumnCount;
            var exitflag  = 1;


            while (Z.Any())
            {
                var  widx = ((Vector)w).Slice((Vector)ZZ.Subtract(1));
                bool brk  = true;
                foreach (var www in widx)
                {
                    if ((www - tol) > 0)
                    {
                        brk = false;
                        break;
                    }
                }
                if (brk)
                {
                    break;
                }

                if (!widx.Any())
                {
                    break;
                }
                outeriter++;
                var wt = widx.Maximum();
                var t  = widx.MaximumIndex();
                t        = (int)ZZ[t];
                P[t - 1] = t;
                Z[t - 1] = 0;
                var PP = P.Find();
                ZZ = Z.Find().Add(1);
                var nzz = ZZ.Count;

                var CP = new DenseMatrix(input.RowCount, input.ColumnCount);

                for (int j = 0; j < input.RowCount; j++)
                {
                    foreach (var pj in PP)
                    {
                        CP[j, (int)pj] = input[j, (int)pj];
                    }
                    foreach (var zj in ZZ)
                    {
                        CP[j, (int)zj - 1] = 0;
                    }
                }

                var z = CP.PseudoInverse() * y;
                foreach (var zj in ZZ)
                {
                    z[(int)zj - 1] = 0;
                }


                while (true)
                {
                    var ztemp = ((Vector)z).Slice((Vector)PP);
                    brk = true;
                    foreach (var ztempp in ztemp)
                    {
                        if (ztempp <= tol)
                        {
                            brk = false;
                            break;
                        }
                    }
                    if (brk)
                    {
                        break;
                    }
                    iter = iter + 1;
                    if (iter > itmax)
                    {
                        exitflag = 0;
                        ra       = z;
                        break;
                    }

                    var lst = new List <int>();
                    for (int i = 0; i < z.Count; i++)
                    {
                        if (z[i] <= tol && P[i] != 0)
                        {
                            lst.Add(i);
                        }
                    }
                    var QQ     = lst.ToArray();
                    var ratemp = ((Vector)ra).Slice(QQ);
                    var alpha  = (ratemp.PointwiseDivide(ratemp - ((Vector)z).Slice(QQ))).Min();
                    ra  = ra + alpha * (z - ra);
                    lst = new List <int>();
                    for (int i = 0; i < ra.Count; i++)
                    {
                        if (Math.Abs(ra[i]) < tol && P[i] != 0)
                        {
                            lst.Add(i);
                        }
                    }
                    foreach (var i in lst)
                    {
                        Z[i] = i;
                        P[i] = 0;
                    }
                    PP  = P.Find();
                    ZZ  = Z.Find().Add(1);
                    nzz = ZZ.Count;
                    for (int j = 0; j < input.RowCount; j++)
                    {
                        foreach (var pj in PP)
                        {
                            CP[j, (int)pj] = input[j, (int)pj];
                        }
                        foreach (var zj in ZZ)
                        {
                            CP[j, (int)zj - 1] = 0;
                        }
                    }

                    z = CP.PseudoInverse() * y;
                    foreach (var zj in ZZ)
                    {
                        z[(int)zj - 1] = 0;
                    }
                }
                ra    = z;
                resid = y - input * ra;
                w     = input.Transpose() * resid;
            }

            return((Vector)ra);
        }
        public void Fit(IList <Point> points, ref double alpha, ref double beta, ref double gamma)
        {
            var model = new Model();

            var minimumDeltaValue      = 1;
            var minimumDeltaParameters = 1;
            var maximumIterations      = 10;

            var pointCount = points.Count;

            Vector <double> dataX = new DenseVector(points.Select(p => p.X).ToArray());
            Vector <double> dataY = new DenseVector(points.Select(p => p.Y).ToArray());

            var iterations = new List <Vector <double> >();

            var guess = new[] { alpha, beta, gamma };

            Vector <double> parametersCurrent = new DenseVector(guess);
            Vector <double> parametersNew     = new DenseVector(parametersCurrent.Count);

            var valueCurrent = GetObjectiveValue(model, pointCount, dataX, dataY, parametersCurrent[0],
                                                 parametersCurrent[1], parametersCurrent[2]);

            while (true)
            {
                var jacobian = GetObjectiveJacobian(model, pointCount, dataX, parametersCurrent[0], parametersCurrent[1],
                                                    parametersCurrent[2]);
                var residual = model.GetResidualVector(pointCount, dataX, dataY, parametersCurrent[0],
                                                       parametersCurrent[1], parametersCurrent[2]);

                try
                {
                    var jacobianT = jacobian.Transpose();
                    var res       = jacobianT.Multiply(residual);
                    var jjT       = jacobian.Transpose().Multiply(jacobian);

                    var cholesky = jjT.Cholesky();
                    var step     = cholesky.Solve(res);
                    parametersCurrent.Subtract(step, parametersNew);
                }
                catch (Exception)
                {
                    alpha = 0;
                    beta  = 0;
                    gamma = 0;
                    return;
                }

                var valueNew = GetObjectiveValue(model, pointCount, dataX, dataY, parametersCurrent[0],
                                                 parametersCurrent[1], parametersCurrent[2]);

                iterations.Add(parametersNew.Clone());

                if (ShouldTerminate(valueCurrent, valueNew, iterations.Count, parametersCurrent, parametersNew,
                                    minimumDeltaValue, minimumDeltaParameters, maximumIterations))
                {
                    break;
                }

                parametersNew.CopyTo(parametersCurrent);
                valueCurrent = valueNew;
            }

            alpha = parametersCurrent[0];
            beta  = parametersCurrent[1];
            gamma = parametersCurrent[2];
        }