Beispiel #1
0
        public void ExtendedVectorNorm()
        {
            // Check that vector norm is correctly computed even when vector is enormous (square would overflow) or tiny (square woudl underflow)

            double x = Double.MaxValue / 32.0;

            // Use the pythagorian quadrouple (2, 3, 6, 7)
            ColumnVector v = new ColumnVector(2.0, 3.0, 6.0);

            Assert.IsTrue(TestUtilities.IsNearlyEqual(v.Norm(), 7.0));
            ColumnVector bv = x * v;

            Assert.IsTrue(TestUtilities.IsNearlyEqual(bv.Norm(), 7.0 * x));
            ColumnVector sv = v / x;

            Assert.IsTrue(TestUtilities.IsNearlyEqual(sv.Norm(), 7.0 / x));

            // Use the pythagorian 7-tuple (1, 2, 3, 4, 5, 27, 28)
            RowVector u = new RowVector(1.0, 2.0, 3.0, 4.0, 5.0, 27.0);

            Assert.IsTrue(TestUtilities.IsNearlyEqual(u.Norm(), 28.0));
            RowVector bu = x * u;

            Assert.IsTrue(TestUtilities.IsNearlyEqual(bu.Norm(), 28.0 * x));
            RowVector su = u / x;

            Assert.IsTrue(TestUtilities.IsNearlyEqual(su.Norm(), 28.0 / x));
        }
Beispiel #2
0
        public void VectorNorm()
        {
            RowVector nR = R / R.Norm();

            Assert.IsTrue(TestUtilities.IsNearlyEqual(nR.Norm(), 1.0));

            ColumnVector nC = C / C.Norm();

            Assert.IsTrue(TestUtilities.IsNearlyEqual(nC.Norm(), 1.0));
        }
Beispiel #3
0
        public static void VectorsAndMatrices()
        {
            ColumnVector v = new ColumnVector(0.0, 1.0, 2.0);
            ColumnVector w = new ColumnVector(new double[] { 1.0, -0.5, 1.5 });

            SquareMatrix A = new SquareMatrix(new double[, ] {
                { 1, -2, 3 },
                { 2, -5, 12 },
                { 0, 2, -10 }
            });

            RowVector u = new RowVector(4);

            for (int i = 0; i < u.Dimension; i++)
            {
                u[i] = i;
            }

            Random            rng = new Random(1);
            RectangularMatrix B   = new RectangularMatrix(4, 3);

            for (int r = 0; r < B.RowCount; r++)
            {
                for (int c = 0; c < B.ColumnCount; c++)
                {
                    B[r, c] = rng.NextDouble();
                }
            }

            SquareMatrix AI = A.Inverse();

            PrintMatrix("A * AI", A * AI);

            PrintMatrix("v + 2.0 * w", v + 2.0 * w);
            PrintMatrix("Av", A * v);
            PrintMatrix("B A", B * A);

            PrintMatrix("v^T", v.Transpose);
            PrintMatrix("B^T", B.Transpose);

            Console.WriteLine($"|v| = {v.Norm()}");
            Console.WriteLine($"sqrt(v^T v) = {Math.Sqrt(v.Transpose * v)}");

            UnitMatrix I = UnitMatrix.OfDimension(3);

            PrintMatrix("IA", I * A);

            Console.WriteLine(v == w);
            Console.WriteLine(I * A == A);
        }
Beispiel #4
0
        /// <summary>
        /// Finds a vector argument which makes a vector function zero.
        /// </summary>
        /// <param name="f">The vector function.</param>
        /// <param name="x0">The vector argument.</param>
        /// <returns>The vector argument which makes all components of the vector function zero.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="f"/> or <paramref name="x0"/> is null.</exception>
        /// <exception cref="DimensionMismatchException">The dimension of <paramref name="f"/> is not equal to the
        /// dimension of <paramref name="x0"/>.</exception>
        public static ColumnVector FindZero(Func <IList <double>, IList <double> > f, IList <double> x0)
        {
            if (f == null)
            {
                throw new ArgumentNullException("f");
            }
            if (x0 == null)
            {
                throw new ArgumentNullException("x0");
            }

            // we will use Broyden's method, which is a generalization of the secant method to the multi-dimensional problem
            // just as the secant method is essentially Newton's method with a crude, numerical value for the slope,
            // Broyden's method is a multi-dimensional Newton's method with a crude, numerical value for the Jacobian matrix

            int d = x0.Count;

            // we should re-engineer this code to work directly on vector/matrix storage rather than go back and forth
            // between vectors and arrays, but for the moment this works; implementing Blas2 rank-1 update would help

            // starting values
            ColumnVector x = new ColumnVector(x0);
            //double[] x = new double[d]; Blas1.dCopy(x0, 0, 1, x, 0, 1, d);
            ColumnVector F = new ColumnVector(f(x.ToArray()));

            //double[] F = f(x);
            if (F.Dimension != d)
            {
                throw new DimensionMismatchException();
            }
            SquareMatrix B = ApproximateJacobian(f, x0);
            double       g = MoreMath.Pow2(F.Norm());

            //double g = Blas1.dDot(F, 0, 1, F, 0, 1, d);

            for (int n = 0; n < Global.SeriesMax; n++)
            {
                // determine the Newton step
                LUDecomposition LU = B.LUDecomposition();
                ColumnVector    dx = -LU.Solve(F);

                //for (int i = 0; i < d; i++) {
                //    Console.WriteLine("F[{0}]={1} x[{0}]={2} dx[{0}]={3}", i, F[i], x[i], dx[i]);
                //}

                // determine how far we will move along the Newton step
                ColumnVector x1 = x + dx;
                ColumnVector F1 = new ColumnVector(f(x1));
                double       g1 = MoreMath.Pow2(F1.Norm());

                // check whether the Newton step decreases the function vector magnitude
                // NR suggest that it's necessary to ensure that it decrease by a certain amount, but I have yet to see that make a diference
                double gm = g - 0.0;
                if (g1 > gm)
                {
                    // the Newton step did not reduce the function vector magnitude, so we won't step that far
                    // determine how far along the descent direction we will step by parabolic interpolation
                    double z = g / (g + g1);
                    //Console.WriteLine("z={0}", z);
                    // take at least a small step in the descent direction
                    if (z < (1.0 / 16.0))
                    {
                        z = 1.0 / 16.0;
                    }
                    dx = z * dx;
                    x1 = x + dx;
                    F1 = new ColumnVector(f(x1.ToArray()));
                    g1 = MoreMath.Pow2(F1.Norm());
                    // NR suggest that this be repeated, but I have yet to see that make a difference
                }

                // take the step
                x = x + dx;

                // check for convergence
                if ((F1.InfinityNorm() < Global.Accuracy) || (dx.InfinityNorm() < Global.Accuracy))
                {
                    //if ((g1 < Global.Accuracy) || (dx.Norm() < Global.Accuracy)) {
                    return(x);
                }

                // update B
                ColumnVector      dF = F1 - F;
                RectangularMatrix dB = (dF - B * dx) * (dx / (dx.Transpose() * dx)).Transpose();
                //RectangularMatrix dB = F1 * ( dx / MoreMath.Pow(dx.Norm(), 2) ).Transpose();
                for (int i = 0; i < d; i++)
                {
                    for (int j = 0; j < d; j++)
                    {
                        B[i, j] += dB[i, j];
                    }
                }

                // prepare for the next iteration
                F = F1;
                g = g1;
            }

            throw new NonconvergenceException();
        }
Beispiel #5
0
        public static void Integration()
        {
            // This is the area of the upper half-circle, so the value should be pi/2.
            IntegrationResult i = FunctionMath.Integrate(x => Math.Sqrt(1.0 - x * x), -1.0, +1.0);

            Console.WriteLine($"i = {i.Estimate} after {i.EvaluationCount} evaluations.");

            Interval          zeroToPi = Interval.FromEndpoints(0.0, Math.PI);
            IntegrationResult watson   = MultiFunctionMath.Integrate(
                x => 1.0 / (1.0 - Math.Cos(x[0]) * Math.Cos(x[1]) * Math.Cos(x[2])),
                new Interval[] { zeroToPi, zeroToPi, zeroToPi }
                );

            IntegrationResult i2 = FunctionMath.Integrate(
                x => Math.Sqrt(1.0 - x * x), -1.0, +1.0,
                new IntegrationSettings()
            {
                RelativePrecision = 1.0E-4
            }
                );

            // This integrand has a log singularity at x = 0.
            // The value of this integral is the Catalan constant.
            IntegrationResult soft = FunctionMath.Integrate(
                x => - Math.Log(x) / (1.0 + x * x), 0.0, 1.0
                );

            // This integral has a power law singularity at x = 0.
            // The value of this integral is 4.
            IntegrationResult hard = FunctionMath.Integrate(
                x => Math.Pow(x, -3.0 / 4.0), 0.0, 1.0,
                new IntegrationSettings()
            {
                RelativePrecision = 1.0E-6
            }
                );

            // The value of this infinite integral is sqrt(pi)
            IntegrationResult infinite = FunctionMath.Integrate(
                x => Math.Exp(-x * x), Double.NegativeInfinity, Double.PositiveInfinity
                );

            Func <IReadOnlyList <double>, double> distance = z => {
                ColumnVector x = new ColumnVector(z[0], z[1], z[2]);
                ColumnVector y = new ColumnVector(z[3], z[4], z[5]);
                ColumnVector d = x - y;
                return(d.Norm());
            };

            Interval oneBox = Interval.FromEndpoints(0.0, 1.0);

            Interval[] sixBox = new Interval[] { oneBox, oneBox, oneBox, oneBox, oneBox, oneBox };

            IntegrationSettings settings = new IntegrationSettings()
            {
                RelativePrecision = 1.0E-4,
                AbsolutePrecision = 0.0,
                Listener          = r => {
                    Console.WriteLine($"Estimate {r.Estimate} after {r.EvaluationCount} evaluations.");
                }
            };

            IntegrationResult numeric = MultiFunctionMath.Integrate(distance, sixBox, settings);

            Console.WriteLine($"The numeric result is {numeric.Estimate}.");

            double analytic = 4.0 / 105.0 + 17.0 / 105.0 * Math.Sqrt(2.0) - 2.0 / 35.0 * Math.Sqrt(3.0)
                              + Math.Log(1.0 + Math.Sqrt(2.0)) / 5.0 + 2.0 / 5.0 * Math.Log(2.0 + Math.Sqrt(3.0))
                              - Math.PI / 15.0;

            Console.WriteLine($"The analytic result is {analytic}.");
        }