示例#1
0
        public static fsValue Calculate(fsFunction function, fsValue beginArg, fsValue endArg, fsValue tolerance)
        {
            if (beginArg > endArg)
            {
                throw new Exception("fsDefiniteIntegral: provided limits are: beginAng > endArg");
            }

            if (beginArg == endArg)
            {
                return(fsValue.Zero);
            }

            fsValue kronrodValue, gaussValue;

            EvalIntegrals(function, beginArg, endArg, out kronrodValue, out gaussValue);
            fsValue kronrodResult = kronrodValue;
            fsValue gaussResult   = gaussValue;

            var queue = new SortedDictionary <fsIntegrationSegment, int>
            {
                { new fsIntegrationSegment(kronrodValue, gaussValue, beginArg, endArg), 0 }
            };
            int iterationsCount = 0;

            while (fsValue.Abs(kronrodResult - gaussResult) > tolerance ||
                   fsValue.Abs(kronrodResult / gaussResult - 1) > tolerance)
            {
                if (++iterationsCount >= 1000)  // If we made too many iterations
                {                               // and still don't have proper precision
                    break;                      // then just return not precise answer.
                }

                fsIntegrationSegment currentSegment = queue.Last().Key;
                queue.Remove(currentSegment);

                beginArg = currentSegment.BeginArg;
                endArg   = currentSegment.EndArg;
                if (IsNeighbouringNumbers(beginArg, endArg))
                {
                    continue;
                }

                kronrodResult -= currentSegment.KronrodIntergralValue;
                gaussResult   -= currentSegment.GaussIntergralValue;

                EvalIntegrals(function, beginArg, 0.5 * (beginArg + endArg), out kronrodValue, out gaussValue);
                kronrodResult += kronrodValue;
                gaussResult   += gaussValue;
                queue.Add(new fsIntegrationSegment(kronrodValue, gaussValue, beginArg, 0.5 * (beginArg + endArg)), 0);

                EvalIntegrals(function, 0.5 * (beginArg + endArg), endArg, out kronrodValue, out gaussValue);
                kronrodResult += kronrodValue;
                gaussResult   += gaussValue;
                queue.Add(new fsIntegrationSegment(kronrodValue, gaussValue, 0.5 * (beginArg + endArg), endArg), 0);
            }

            return((kronrodResult + gaussResult) / 2);
        }
示例#2
0
        public static fsValue FindRoot(fsFunction function, fsValue beginArg, fsValue endArg, int iterationsCount)
        {
            fsValue beginRes;
            fsValue endRes;

            if (FindRootRange(function, beginArg, endArg, iterationsCount, out beginRes, out endRes))
            {
                return(0.5 * (beginRes + endRes));
            }
            return(new fsValue());
        }
示例#3
0
        public static bool FindMinimum(fsFunction function, fsValue beginArg, fsValue endArg, int iterationsCount, out fsValue beginRes, out fsValue endRes)
        {
            beginRes = new fsValue();
            endRes   = new fsValue();

            if (beginArg.Defined == false || endArg.Defined == false)
            {
                return(false);
            }

            fsValue len = endArg - beginArg;

            if (len <= new fsValue(0))
            {
                throw new Exception("Wrong interval for ternary search");
            }

            var eps = new fsValue(1e-8);

            fsValue left  = beginArg;
            fsValue right = endArg;

            for (int i = 0; i < iterationsCount; ++i)
            {
                fsValue middle = 0.5 * (left + right);
                fsValue mid1   = middle - eps * (right - left);
                fsValue mid2   = middle + eps * (right - left);
                fsValue val1   = function.Eval(mid1);
                fsValue val2   = function.Eval(mid2);

                if (!val1.Defined)
                {
                    throw new Exception("Function given to TernaryMethod not defind in point " + mid1.Value);
                }
                if (!val2.Defined)
                {
                    throw new Exception("Function given to TernaryMethod not defind in point " + mid2.Value);
                }

                if (val1 > val2)
                {
                    left = mid1;
                }
                else
                {
                    right = mid2;
                }
            }

            beginRes = left;
            endRes   = right;
            return(true);
        }
示例#4
0
        static private void EvalIntegrals(fsFunction function, fsValue beginArg, fsValue endArg, out fsValue kronrodResult, out fsValue gaussResult)
        {
            fsValue c0 = 0.5 * (endArg + beginArg);
            fsValue c1 = 0.5 * (endArg - beginArg);

            kronrodResult = fsValue.Zero;
            gaussResult   = fsValue.Zero;

            for (int i = 0; i <= 60; ++i)
            {
                fsValue fValue = function.Eval(c0 + c1 * X[i]);
                kronrodResult += WKronrod[i] * fValue;
                gaussResult   += WGauss[i] * fValue;
            }
            kronrodResult *= c1;
            gaussResult   *= c1;
        }
示例#5
0
        public static bool FindRootRange(fsFunction function, fsValue beginArg, fsValue endArg, int iterationsCount, out fsValue beginRes, out fsValue endRes)
        {
            beginRes = new fsValue();
            endRes   = new fsValue();

            if (beginArg.Defined == false || endArg.Defined == false)
            {
                return(false);
            }

            fsValue len = endArg - beginArg;
            var     eps = new fsValue(1e-8);

            if (len.Value < 0)
            {
                eps = -eps;
            }
            if (fsValue.Abs(len) < new fsValue(1))
            {
                eps = eps * fsValue.Abs(len);
            }

            fsValue beginValue = function.Eval(beginArg + eps);
            fsValue endValue   = function.Eval(endArg - eps);

            if (beginValue.Defined == false || endValue.Defined == false)
            {
                return(false);
            }
            if (beginValue == endValue)
            {
                if (beginValue.Value == 0)
                {
                    if (function.Eval(beginArg).Value == 0)
                    {
                        beginRes = endRes = endArg;
                        return(true);
                    }
                    beginRes = beginArg + eps;
                    endRes   = beginArg + eps;
                    return(true);
                }
                if (function.Eval(endArg).Value == 0)
                {
                    beginRes = endRes = endArg;
                    return(true);
                }

                return(false);
            }

            fsValue beginSign = fsValue.Sign(beginValue, eps);
            fsValue endSign   = fsValue.Sign(endValue, eps);

            if ((beginSign * endSign).Value > 0)
            {
                return(false);
            }

            fsValue left  = beginArg;
            fsValue right = endArg;

            for (int i = 0; i < iterationsCount; ++i)
            {
                fsValue middle = 0.5 * (left + right);
                fsValue value  = function.Eval(middle);

                if (!value.Defined)
                {
                    throw new Exception("Function given to BisectionMethod not defind in point " + middle.Value);
                }

                fsValue midSign = fsValue.Sign(value, eps);
                if (midSign.Value == 0 || midSign == endSign)
                {
                    right = middle;
                }
                else
                {
                    left = middle;
                }
            }

            beginRes = left;
            endRes   = right;
            return(true);
        }
示例#6
0
        public static fsValue FindBreakInUnimodalFunction(fsFunction function, fsValue beginArg, fsValue endArg, int iterationsCount)
        {
            if (beginArg.Defined == false || endArg.Defined == false)
            {
                return(new fsValue());
            }

            fsValue len = endArg - beginArg;
            var     eps = new fsValue(1e-8);

            if (len.Value < 0)
            {
                eps = -eps;
            }

            fsValue beginValue = function.Eval(beginArg);
            fsValue endValue   = function.Eval(endArg);

            if (fsValue.Sign(beginValue, eps) * fsValue.Sign(endValue, eps) == new fsValue(-1))
            {
                throw new Exception("Search limits represent different signs of values already");
            }

            beginValue = function.Eval(beginArg + eps);
            endValue   = function.Eval(endArg - eps);
            if (fsValue.Sign(beginValue, eps) * fsValue.Sign(endValue, eps) == new fsValue(-1))
            {
                throw new Exception("Search limits represent different signs of values already");
            }

            if (beginValue.Defined == false || endValue.Defined == false)
            {
                return(new fsValue());
            }

            fsValue initialSign = fsValue.Sign(beginValue, eps);
            fsValue left        = beginArg;
            fsValue right       = endArg;

            for (int i = 0; i < iterationsCount; ++i)
            {
                fsValue middle = 0.5 * (left + right);
                fsValue mid1   = middle - eps * (right - left);
                fsValue mid2   = middle + eps * (right - left);
                fsValue val1   = function.Eval(mid1);
                fsValue val2   = function.Eval(mid2);

                if (!val1.Defined)
                {
                    throw new Exception("Function given to FindBreakInUnimodalFunction not defind in point " + mid1.Value);
                }
                if (!val2.Defined)
                {
                    throw new Exception("Function given to FindBreakInUnimodalFunction not defind in point " + mid2.Value);
                }

                if (fsValue.Sign(val1, eps) != initialSign)
                {
                    return(mid1);
                }

                if (fsValue.Sign(val2, eps) != initialSign)
                {
                    return(mid2);
                }


                if (fsValue.Sign(val1 - val2, eps) == initialSign)
                {
                    left = middle;
                }
                else
                {
                    right = middle;
                }
            }

            return(new fsValue());
        }