示例#1
0
        public double Bidon()
        {
            ReferencePoints rp         = new ReferencePoints(this.Ob01, this.A, this.Start.Copy(), this.Range, this.InestimableLowerLimit, epsilon: this.Precision);
            LModeExt        refPtsMode = rp.GetPoints();
            bool            cntn       = false;
            double          uMode;
            double          x;
            double          target;
            double          areaMode;
            bool            distrnLeftSide = false;
            double          mathLowerLimit = this.Ob01.MathLowerLimit;
            bool            converged      = false;
            double          areaX;
            double          precision = this.Precision;
            Func <double, SGNFnAParam, double> area;

            if (refPtsMode.Found)
            {
                // A$f < -o$f
                this.A.F          = this.Ob01.F;
                this.A.LowerLimit = refPtsMode.Remote[0];
                this.A.M          = refPtsMode.H; // # (kind of a) standardizing constant
                area = this.A.AreaFnFromALLimToX;
                double areaTot = WebExpoFunctions3.SmoothedAreaEstimate(
                    area,
                    refPtsMode.Remote[1],
                    this.A,
                    mathLowerLimit,
                    refPtsMode.Remote,
                    this.InestimableLowerLimit,
                    remoteRight: true);

                target    = this.U * areaTot;
                precision = this.Precision * areaTot;
                x         = refPtsMode.X;
                areaX     = 0;
                areaMode  = WebExpoFunctions3.SmoothedAreaEstimate(area, x, this.A, mathLowerLimit, refPtsMode.Remote, this.InestimableLowerLimit);
                uMode     = areaMode / areaTot;
                converged = Math.Abs(areaMode - target) < precision;
                cntn      = !converged;
            }
            else
            {
                throw new WEException("Mode not found");
            }

            if (cntn)
            {
                distrnLeftSide = this.U < uMode;
                if (distrnLeftSide)
                {
                    area = this.A.AreaFn_FromXToAULim;
                    this.A.UpperLimit = refPtsMode.X;
                    this.Range        = Tools.Combine(refPtsMode.Remote[0], refPtsMode.X);
                }
                else
                {
                    this.A.LowerLimit = refPtsMode.X;
                    this.Range        = Tools.Combine(refPtsMode.X, refPtsMode.Remote[1]);
                }
            }

            //converged = true;
            if (cntn && this.Ob01.PotentiallyBimodal)
            {
                // Slower but safer algorithm for posterior distrns that are potentially bimodal
                double fMode = A.F(refPtsMode.X, A);
                double start = refPtsMode.X + (target - areaMode) / fMode;
                cntn      = false;
                converged = true; // voir l'impact !!!

                double highestPoint;
                double hMax;
                if (distrnLeftSide)
                {
                    highestPoint = refPtsMode.Remote[0];
                    hMax         = areaMode;
                    target       = (uMode - this.U) / uMode * hMax;
                }
                else
                {
                    highestPoint = refPtsMode.Remote[1];
                    hMax         = WebExpoFunctions3.SmoothedAreaEstimate(area, refPtsMode.Remote[1], this.A, mathLowerLimit, this.Range, this.InestimableLowerLimit, remoteRight: true);
                    target       = (this.U - uMode) / (1 - uMode) * hMax;
                }

                SecuredNRA      oCum = new SecuredNRA(area, this.Ob01.F);
                SecuredNRSearch nr   = new SecuredNRSearch(oCum, this.A, start, precision, this.Range,
                                                           maxPoint: new LMode(highestPoint, hMax), target: target, inestimableLowerLimit: this.InestimableLowerLimit);
                // le dernier paramètre a une valeur par défaut: expectedHpSign = -1
                if (nr.Converged)
                {
                    x = nr.X;
                }
                else
                {
                    //# it seems we were caught in an infinite loop, had we not limited the number of iterations;
                    //# see if we can rule that problem out
                    x = nr.Bounds.X[0];
                    double h = nr.Bounds.H[0];
                    x = ICDFFunctions.PingpongTieBreaker(area, this.A, x, h, target, mathLowerLimit, this.Range, this.InestimableLowerLimit, precision, distrnLeftSide);
                }
            }

            int direction = 0;
            int count     = 0;

            if (cntn)
            {
                direction = distrnLeftSide ? -1 : 1;
                if (distrnLeftSide)
                {
                    target = (uMode - this.U) / uMode * areaMode;
                }
                else
                {
                    double areaRemoteRight = WebExpoFunctions3.SmoothedAreaEstimate(
                        area,
                        refPtsMode.Remote[1],
                        this.A,
                        mathLowerLimit,
                        this.Range,
                        this.InestimableLowerLimit,
                        remoteRight: true);
                    target = (this.U - uMode) / (1 - uMode) * areaRemoteRight;
                }
            }

            while (cntn)
            {
                double hp     = this.Ob01.F(x, A);
                double change = (target - areaX) / hp * direction;
                x         = x + change;
                areaX     = area(x, A);
                count     = count + 1;
                converged = Math.Abs(areaX - target) < precision;
                cntn      = !converged && count <= this.NRMaxIter;
            }

            if (!converged)
            {
                if (x > refPtsMode.Remote[1] || x < refPtsMode.Remote[0])
                {
                    throw new WEException("Stepped out of bounds -- due to numerical imprecision?");
                }
                else
                {
                    //# it seems we were caught in an infinite loop, had we not limited the number of iterations;
                    //# see if we can rule that problem out
                    x = ICDFFunctions.PingpongTieBreaker(area, this.A, x, areaX, target, mathLowerLimit, this.Range, this.InestimableLowerLimit, precision, distrnLeftSide);
                }
            }
            return(x);
        }
示例#2
0
        internal static double PingpongTieBreaker(
            Func <double, SGNFnAParam, double> area,
            SGNFnAParam A,
            double start,
            double areaX,
            double target,
            double mathLowerLimit,
            double[] refRange,
            bool inestimableLowerLimit,
            double epsilon,
            bool distrnLeftSide = false,
            int maxCount        = 100)
        {
            int    hpMult   = distrnLeftSide ? -1 : 1;
            bool   cntn     = true;
            int    count    = 0;
            double x        = start;
            Visits visitedX = new Visits(maxCount);

            visitedX.Add(x);
            bool converged    = false;
            bool caughtInLoop = false;

            while (cntn)
            {
                double hp     = A.F(x, A) * hpMult;
                double change = (target - areaX) / hp;
                x = x + change;
                // new_0.11
                if (x < refRange[0])
                {
                    x = (refRange[0] == mathLowerLimit) && inestimableLowerLimit ? (x - change + mathLowerLimit) / 2.0 : refRange[0];
                }

                areaX = WebExpoFunctions3.SmoothedAreaEstimate(area, x, A, mathLowerLimit, refRange, inestimableLowerLimit, hpMult: hpMult);
                count++;
                converged = Math.Abs(areaX - target) < epsilon;
                visitedX.Add(x);
                caughtInLoop = visitedX.CaughtInLoop; // La propiété CaughtInLoop est mise à jour à chaque ajout d'un x.
                                                      // x doit être fini, et avoir déjà été visité.
                cntn = !converged && (visitedX.Count <= maxCount) && !caughtInLoop;
            }

            if (!converged && caughtInLoop)
            {
                //  We have found the series of points that are repeatedly visited:
                // recalibrate and try Newton-Raphson again
                double[] tail = visitedX.GetFromTail(x);

                x     = (distrnLeftSide) ? x = tail.Max() : tail.Min();
                areaX = WebExpoFunctions3.SmoothedAreaEstimate(area, x, A, mathLowerLimit, refRange, inestimableLowerLimit, hpMult: hpMult);

                if (distrnLeftSide)
                {
                    A.UpperLimit = x;
                }
                else
                {
                    A.LowerLimit = x;
                }

                target = target - areaX;
                areaX  = 0.0;
                count  = 0;
                cntn   = true;
                while (cntn)
                {
                    double hp     = A.F(x, A) * hpMult;
                    double change = (target - areaX) / hp;
                    x         = x + change;
                    areaX     = area(x, A);
                    count     = count + 1;
                    converged = Math.Abs(areaX - target) < epsilon;
                    cntn      = !converged && (count <= maxCount);
                }
            }

            if (!converged)
            {
                //TODO Exception
                throw new WEException("Newton-Raphson algorithm did not converge. Sorry.\n");
            }

            return(x);
        } // end of ping.pong.tie.breaker