Esempio n. 1
0
        // --------------------------------------------
        // --------- ЧИСЛЕННОЕ ИНТЕГРИРОВАНИЕ ---------
        // --------------------------------------------

        /// <summary>
        /// Returns the Monte-Carlo stochastic approximation of the function integral.
        ///
        /// Requirements: calculator for the function argument/value should provide
        /// reasonable implementation of the 'fromDouble()' method.
        /// </summary>
        /// <typeparam name="T">The type of the function's argument/value.</typeparam>
        /// <typeparam name="C">The calculator for the function argument.</typeparam>
        /// <param name="obj">The calling function object.</param>
        /// <param name="generator">The uniform distribution (pseudo)random generator.</param>
        /// <param name="interval">The interval on which the integral will be approximated.</param>
        /// <param name="rectangleHeight">The height of the testing rectangle. Should be more than the function's absolute maximum on the interval tested, otherwise the method would return wrong results. On the other side, the difference between the height and the function's absolute maximum should not be very large as it will reduce the accuracy of the method. The ideal case is equality of the max f(x) on [a; b] and the rectangle height.</param>
        /// <param name="throwsCount">A positive integer value of overall tests.</param>
        /// <returns>The value approximating the function integral on the interval specified.</returns>
        public static T IntegralMonteCarloApproximation <T, C>(this IFunction <T, T> obj, IRandomBounded <T> generator, BoundedInterval <T, C> interval, T rectangleHeight, T throwsCount) where C : ICalc <T>, new()
        {
            ICalc <T> calc = Numeric <T, C> .Calculator;

            T         hits = calc.zero; // overall hits.
            Point <T> randomPoint;      // random point.

            if (!calc.mor(throwsCount, calc.zero))
            {
                throw new ArgumentException("The amount of point throws count should be a positive integer value.");
            }

            for (T i = calc.zero; calc.mor(throwsCount, i); i = calc.increment(i))
            {
                randomPoint = new Point <T>(generator.Next(interval.LeftBound, interval.RightBound), generator.Next(calc.zero, rectangleHeight));

                // Если попали под функцию - увеличиваем количество хитов.

                if (!calc.mor(randomPoint.Y, obj.Value(randomPoint.X)))
                {
                    hits = calc.increment(hits);
                }
            }

            T result = calc.div(calc.mul(calc.mul(interval.Length, rectangleHeight), hits), throwsCount);

            return(result);
        }
Esempio n. 2
0
        /// <summary>
        /// Returns the rectangle approximation of the function integral.
        /// </summary>
        /// <typeparam name="T">The type of function argument/value.</typeparam>
        /// <typeparam name="C">The calculator for the argument type.</typeparam>
        /// <param name="obj">The calling function object.</param>
        /// <param name="interval">The interval to approximate the integral on.</param>
        /// <param name="pointCount">The overall point count used to calculate the integral.</param>
        /// <returns></returns>
        public static T IntegralRectangleApproximation <T, C>(this IFunction <T, T> obj, BoundedInterval <T, C> interval, int pointCount) where C : ICalc <T>, new()
        {
            ICalc <T> calc = Numeric <T, C> .Calculator;

            // Если интервал нулевой, то ваще забей.

            if (interval.IsZeroLength)
            {
                return(calc.zero);
            }

            // Если нет, то ваще не забей.

            Numeric <T, C> step = calc.div(interval.Length, calc.fromInt(pointCount));

            Numeric <T, C> two = (Numeric <T, C>) 2;

            Numeric <T, C> left  = interval.LeftBound + step / two;
            Numeric <T, C> right = interval.RightBound - step / two;

            // Будем хранить элементы по порядку, чтобы при суммировании не терять ерунды.

            SortedSet <Numeric <T, C> > sorted = new SortedSet <Numeric <T, C> >(Numeric <T, C> .NumericComparer);

            for (int i = 0; i < pointCount; i++)
            {
                T current = left + (right - left) * (Numeric <T, C>)i / (Numeric <T, C>)(pointCount - 1);
                sorted.Add(obj.Value(current));
            }

            // Теперь будем суммировать по порядку, начиная с самых маленьких.

            Numeric <T, C> sum = calc.zero;

            foreach (Numeric <T, C> element in sorted)
            {
                sum += element;
            }

            return(sum * step);
        }
Esempio n. 3
0
        // --------- this is the key to happiness

        private static T _PositiveLagrangeBound(IList <Numeric <T, C> > coefficients, Func <int, Numeric <T, C>, Numeric <T, C> > selector)
        {
            // нули в начале нам совсем не нужны.

            int minus = 1;

            while (coefficients[coefficients.Count - minus] == Numeric <T, C> .Zero)
            {
                minus++;

                if (minus > coefficients.Count)
                {
                    throw new ArgumentException("This polynom contains only zero coefficients. Cannot evaluate the finite roots interval.");
                }
                // todo - return INFINITY.
            }

            // ------- начальный коэффициент - меньше нуля?
            // заменяем функцию g(x) = -f(x) и сохраняем корни и нервы.

            if (selector(coefficients.Count - minus, coefficients[coefficients.Count - minus]) < Numeric <T, C> .Zero)
            {
                object     target = selector.Target;
                MethodInfo method = selector.Method;

                selector = delegate(int i, Numeric <T, C> obj) { return(-(Numeric <T, C>)method.Invoke(target, new object[] { i, obj })); };
            }

            // -----------------

            T nCoef = coefficients[coefficients.Count - minus];

            T cur;

            T one = calc.fromInt(1);
            T max = calc.zero;

            int  index = -1;        // индекс первого отрицательного коэффициента
            bool found = false;     // найдены ли отрицательные коэффициенты!

            for (int i = coefficients.Count - minus; i >= 0; i--)
            {
                cur = selector(i, coefficients[i]);

                if (!found && calc.mor(calc.zero, cur))
                {
                    found = true;
                    index = coefficients.Count - i - minus;
                }

                // -- здесь cur больше не нужна, а нужно только ее
                // абсолютное значение. его и используем.

                cur = WhiteMath <T, C> .Abs(cur);

                if (calc.mor(cur, max))
                {
                    max = cur;
                }
            }

            if (!found)
            {
                return(calc.zero);
            }

            return(calc.sum(one, WhiteMath <T, C> .Power(calc.div(max, WhiteMath <T, C> .Abs(nCoef)), calc.div(one, calc.fromInt(index)))));
        }