Esempio n. 1
0
        /*
         * log.f.inv.remote <- function(target, A)
         * {
         * tmp <- 1 + c(-1,1)*sqrt(2*A$cv2*abs(target))
         * tmp <- tmp[tmp>0]
         * roots <- log(tmp/A$y)
         *
         * C <- -(A$y-1)^2/2/A$cv2 - A$mu^2/2/A$sigma2
         * B <- -1 + (A$y-1)*A$y/A$cv2 + A$mu/A$sigma2
         * qA <- -A$y2/2/A$cv2 - 1/2/A$sigma2
         * tmp <- quadratic.solution(c(C, B, qA), target=target)
         *
         * roots <- c(roots, tmp)
         * roots
         * } # end of log.f.inv.remote
         * }
         */
        internal override List <double> LogFInvRemote(double target, SGNFnAParam A)
        {
            List <double> roots  = new List <double>();
            double        z      = Math.Sqrt(2.0 * A.CV2 * Math.Abs(target));
            double        pPetit = 1.0 - z;
            double        pGrand = 1.0 + z;

            if (pPetit > 0.0)
            {
                roots.Add(Math.Log(pPetit / A.Y));
                roots.Add(Math.Log(pGrand / A.Y));
            }
            else if (pGrand > 0.0)
            {
                roots.Add(Math.Log(pGrand / A.Y));
            }

            double C =
                -Math.Pow(A.Y - 1.0, 2) / 2.0 / A.CV2
                - Math.Pow(A.Mu, 2) / 2.0 / A.Sigma2;
            double B =
                -1.0
                + (A.Y - 1.0) * A.Y / A.CV2
                + A.Mu / A.Sigma2;
            double qA =
                -A.Y2 / 2.0 / A.CV2
                - 1.0 / 2.0 / A.Sigma2;

            roots.AddRange(QuadraticEquation.GetRealRoots(Tools.Combine(C, B, qA), target, ROrder: true));
            return(roots);
        }
Esempio n. 2
0
        internal override List <double> LogFInvRemote(double target, SGNFnAParam A)
        {
            /*
             # solutions for large s
             #    tmp <- A$y + c(-1,1)*sqrt(2*abs(target)*A$ksi2) # vector of length 2
             #    tmp <- tmp[tmp>0]
             #    roots <- log(tmp)
             #
             */
            // solutions for large s
            List <double> roots = new List <double>();
            double        z     = Math.Sqrt(2 * Math.Abs(target) * A.Ksi2);
            double        pp    = A.Y - z;
            double        pg    = A.Y + z;

            if (pp > 0.0)
            {
                roots.Add(Math.Log(pp));
                roots.Add(Math.Log(pg));
            }
            else if (pg > 0.0)
            {
                roots.Add(Math.Log(pg));
            }

            /*
             *    C <- log(2) -A$y2/2/A$ksi2 - A$mu^2/2/A$sigma2
             *    B <- A$mu/A$sigma2
             *    qA <- -1/2/A$sigma2
             *    tmp <- quadratic.solution(c(C, B, qA), target=target)
             *    roots <- c(roots, tmp)
             *
             */

            //# solutions for small s (large negative values)
            double C  = Math.Log(2) - A.Y2 / 2.0 / A.Ksi2 - Math.Pow(A.Mu, 2) / 2.0 / A.Sigma2;
            double B  = A.Mu / A.Sigma2;
            double qA = -1.0 / 2.0 / A.Sigma2;

            roots.AddRange(QuadraticEquation.GetRealRoots(Tools.Combine(C, B, qA), target, ROrder: true));

            /*
             *    C <- log(2) -A$y2/2/A$ksi2 - A$mu^2/2/A$sigma2
             *    B <- A$mu/A$sigma2
             *    qA <- -1/2/A$sigma2
             *    tmp <- quadratic.solution(c(C, B, qA), target=target)
             *    roots <- c(roots, tmp)
             */

            //# solutions around 0
            C  = Math.Log(1.0 / A.Ksi) - Math.Pow(A.Y - 1.0, 2) / 2.0 / A.Ksi2 - Math.Pow(A.Mu, 2) / 2.0 / A.Sigma2;
            B  = A.Mu / A.Sigma2;
            qA = -1.0 / 2.0 / A.Sigma2;
            roots.AddRange(QuadraticEquation.GetRealRoots(Tools.Combine(C, B, qA), target, ROrder: true));
            return(roots);
        } // # end of log.f.inv.remote
Esempio n. 3
0
        /*
         *  start <- function(A)
         *  {
         *    C <- -1 + A$y2/A$cv2 - A$y/A$cv2 + A$mu/A$sigma2
         *    B <- -2*A$y2/A$cv2 + A$y/A$cv2 - 1/A$sigma2
         *    qA <- 2*A$y2/A$cv2 - A$y/2/A$cv2
         *    tmp <- quadratic.solution(c(C, B, qA))
         *
         *    start <- c(tmp, A$mu - A$sigma2)
         *    start
         *  } # end of start
         */

        internal override double[] Start(SGNFnAParam A)
        {
            double        C     = -1.0 + A.Y2 / A.CV2 - A.Y / A.CV2 + A.Mu / A.Sigma2;
            double        B     = -2.0 * A.Y2 / A.CV2 + A.Y / A.CV2 - 1.0 / A.Sigma2;
            double        qA    = 2.0 * A.Y2 / A.CV2 - A.Y / 2.0 / A.CV2;
            List <double> roots = QuadraticEquation.GetRealRoots(Tools.Combine(C, B, qA), ROrder: true);

            roots.Add(A.Mu - A.Sigma2);
            return(roots.ToArray());
        }
Esempio n. 4
0
        internal override List <double> LogFInvRemote(double target, SGNFnAParam A)
        {
            List <double> roots = new List <double>();
            double        k     = -A.N / 2.0 / A.S2;
            //# right-side roots
            double B = -2.0 * A.MuMean;
            double C = Math.Pow(A.MuMean, 2);

            double[] coeff = Util.Tools.Combine(C, B, 1.0).Multiply(k);
            roots.AddRange(QuadraticEquation.GetRealRoots(coeff, target, ROrder: true));
            //# left-side roots
            double[] lpqac = WebExpoFunctions3.LPQAC2;
            coeff = coeff.Substract(Tools.Combine(A.N * lpqac[0], A.N * lpqac[1] / A.S, A.N * lpqac[2] / A.S2));
            roots.AddRange(QuadraticEquation.GetRealRoots(coeff, target, ROrder: true));
            return(roots);
        } //# end of log.f.inv.remote
Esempio n. 5
0
        internal override double[] Start(SGNFnAParam A)
        {
            List <double> roots = new List <double>();
            //# solutions in small values for t
            double C = A.Y2 / A.CV2;
            double B = -A.Y / A.CV2;

            roots.AddRange(QuadraticEquation.GetRealRoots(Tools.Combine(C, B, -1), l: 0, ROrder: true));
            //# solutions in large values for t
            double D = A.Y / A.CV2;

            B = -A.Mu / A.Sigma2;
            double qA = 1 / A.Sigma2;

            double[] theta = Tools.Combine(D, 1, B, qA);
            roots.AddRange(CubicEquation.GetRealRoots(theta, l: 0, ROrder: true));
            return(roots.ToArray());
        } //# end of start
Esempio n. 6
0
        } //LogFSecond

        internal override List <double> LogFInvRemote(double target, SGNFnAParam A)
        {
            List <double> roots = new List <double>();
            //# small values

            double c3 = -(A.N + 1.0) + A.LM / A.LS2;
            double c2 = A.N + 1 - Math.Pow(A.LM, 2) / 2.0 / A.LS2 - target;
            double c0 = -A.B;

            roots.AddRange(CubicEquation.GetRealRoots(Tools.Combine(c3, c2, 0, c0), l: 0));
            //# large values
            double C  = -Math.Pow(A.LM, 2) / 2.0 / A.LS2 - target;
            double B  = A.LM / A.LS2 - (A.N + 1);
            double vA = -1.0 / 2.0 / A.LS2;

            double[] tmp = QuadraticEquation.GetRealRoots(Tools.Combine(C, B, vA), l: 0, ROrder: true).ToArray().Exp();
            roots.AddRange(tmp);
            return(roots);
        } //LogFInvRemote
Esempio n. 7
0
        } //# end of max.fastTrack

        internal LModeExt GetPoints()
        {
            //# Arguments:
            //# ----------------------------------------------
            //# o: same nature as o in dens.gen.icdf arguments
            //# start: EITHER a vector of length 2 [two potential starting points]
            //#        or a scalar
            //# f.ratio.remote: scalar
            //# epsilon: scalar
            //# range: vector of length 2
            //# --------------------------------------------------------------------------
            //# If range is finite and log.f not inestimable at lower end,
            //# then we first look for values at both ends before searching for a mode

            //mode = list(x = numeric(0), h = numeric(0), found = false) # modif_0.11
            LMode mode = new LMode();

            if ((this.Range[0].IsFinite() && this.Range[1].IsFinite() && !this.InestimableLowerLimit))
            {
                double[] logFPrime = new double[] { this.O.LogFPrime(this.Range[0], A), this.O.LogFPrime(this.Range[1], A) };
                //# If slope (f') is the same at both ends, then there is no mode between the 2 endpoints (assuming a unimodal distrn)
                //# and we then assume that the highest end value for log.f is hence the local mode
                double[] logFPrimeSign = new double[] { Math.Sign(logFPrime[0]), Math.Sign(logFPrime[1]) };
                if (logFPrime.Prod() > 0)
                {
                    double[] logF = new double[] { this.O.LogF(this.Range[0], A), this.O.LogF(this.Range[1], A) };
                    int      w    = (logF[0] >= logF[1]) ? 0 : 1;
                    mode = new LMode(w == 0 ? this.Range[0] : this.Range[1], logF[w], true);
                }
            } // if ((this.Range[0]

            SecuredNRSearch nr = null;
            double          startingPoint;

            if (!mode.Found)
            {
                //# Choose a starting point among suggested starting points, if more than one point was suggested
                if (this.Start.Length > 1)
                {
                    this.Start = Tools.Combine(this.Start, this.Start.Mean());
                    //# Add the middle point to the two potential starting points
                    double[] logF = new double[this.Start.Length];
                    for (int i = 0; i < this.Start.Length; i++)
                    {
                        logF[i] = this.O.LogF(this.Start[i], A);
                    }
                    //double[] logF = new double[] { this.O.LogF(this.Start[0], A), this.O.LogF(this.Start[1], A), this.O.LogF(this.Start.Mean(), A) };
                    //TODO peut planter
                    startingPoint = this.Start[logF.WhichMax()];
                } //if (this.Start.Length > 1)
                else
                {
                    startingPoint = this.Start[0];
                }
                //# Find mode by Newton-Raphson
                SecuredNRA oMode = new SecuredNRA(this.O.LogFPrime, this.O.LogFSecond, this.Range);
                nr = new SecuredNRSearch(oMode, A, startingPoint, this.Epsilon, this.Range);
                // 4 derniers paramètres prennent les valeurs par défaut:
                // maxPoint = null, target = 0, inestimableLowerLimit = false,  expectedHpSign = -1
                if (nr.Converged)
                {
                    double hs = this.O.LogFSecond(nr.X, A);
                    if (hs > 0)
                    {
                        //# we have found a mimimum point (between two local modes):
                        //# we redo the search on both sides of this dip
                        mode.X = HigherLocalMax(this.O, A, nr.X, this.Range, this.Epsilon);
                    } //if (hs > 0)
                    else
                    {
                        mode.X = nr.X;
                    } //if (hs > 0)

                    mode.Found = true;
                } //if (nr.Converged)
                else
                {
                    double[] xA           = nr.Bounds.X;
                    double[] hA           = nr.Bounds.H;
                    bool     hOnBothSides = hA.Aggregate(1, (x, y) => x * Math.Sign(y)) < 0;
                    double   diffX        = xA.Diff()[0];
                    if ((diffX < this.Epsilon) && hOnBothSides)
                    {
                        mode.X     = xA.Mean();
                        mode.Found = true;
                    } //if ((diffX < this.Epsilon) && hOnBothSides)
                    else
                    {
                        bool converged = false;
                        if ((nr.Bounds.X.Diff()[0] < this.Epsilon) && nr.Bounds.H.All(a => a < 0))
                        {
                            if (this.Range[0].IsFinite())
                            {
                                //# We try a little bit further to find the actual mode,
                                //# since it looks like we are almost there...
                                converged = true;
                                MaxFastTrackObject tmp = MaxFastTrack(this.O, A, this.Range[1], nr.Bounds.X[0], nr.Bounds.H[0]); //# yes: 4th argument is bounds$h (and not hp!)

                                if (tmp.Converged)
                                {
                                    mode.X     = tmp.X;
                                    mode.Found = true;
                                } //if (tmp.Converged)
                                else
                                {
                                    mode.X     = this.Range[1];
                                    mode.Found = !this.InestimableLowerLimit;
                                } //if (tmp.Converged)
                            }     //if (this.Range[0].IsFinite())
                            else
                            {
                                double x   = nr.Bounds.X[0];
                                double h   = nr.Bounds.H[0];
                                double tmp = Math.Abs(h / this.O.LogFSecond(x, this.A));
                                if (tmp < 1e-12)
                                {
                                    mode      = new LMode(x, h, true);
                                    converged = true;
                                } //if (tmp < 1e-12)
                            }     //if (this.Range[0].IsFinite())
                        }

                        if (!converged)
                        {
                            throw new WEException("Algorithm did not converge.");
                        } //if (!converged)
                    }     //if ((diffX < this.Epsilon) && hOnBothSides)
                }         //if (nr.Converged)

                if (mode.Found)
                {
                    mode.H = this.O.LogF(mode.X, this.A);
                }
            } //if (!mode.Found)

            double logFRatioRemote = Math.Log(this.FRatioRemote);// # new_0.11
            double target          = Tools.ND; // R n'a pas vraiment de notion de scope

            if (mode.Found)
            {
                target = mode.H + logFRatioRemote;
            }

            this.A.Mode = mode.X; //  # some 'remote.*' functions need that information
                                  //# modif_0.11
                                  //# Find remote points on both sides of mode
            double remoteLeft = 0, remoteRight = 0;

            bool[] modeOnBorder = new bool[2];
            double fs           = Tools.ND;

            if (mode.Found)
            {
                //TODO pourquoi la définition et l'affectation de target ne serait-elle pas ici?
                double[] x  = new double[] { Tools.NA, Tools.NA };
                double[] f  = new double[] { Tools.NA, Tools.NA };
                double[] fp = new double[] { Tools.NA, Tools.NA };
                fs = this.O.LogFSecond(mode.X, A);// # scalar
                double d = 10 / Math.Abs(fs);
                //# new_0.11
                double[] remoteStart = this.O.LogFInvRemote(target, this.A).ToArray();                 //  # vector
                                                                                                       // TODO start est un paramètre de la fonction en R, vérifier l'impact de modifier la référence d'objet ici.
                this.Start = SplitStartingValuesLeftRight(this.O, target, A, this.Range, remoteStart); // # vector of length 2

                modeOnBorder = new bool[2] {
                    this.Range[0] == mode.X, this.Range[1] == mode.X
                };                                                                               //# new_0.11
                List <int> jSeq = new List <int>();
                for (int i = 0; i < 2; i++)
                {
                    if (!modeOnBorder[i] && this.Start[i].IsNA())
                    {
                        jSeq.Add(i);
                    }
                }

                foreach (int j in jSeq)
                {
                    //# modif_0.11 (first block that appeared here was moved above)
                    // condition inutile
                    if (Tools.IsNA(this.Start[j]))
                    {
                        int    dir      = (j == 0) ? -1 : 1;
                        double tmp      = mode.X + dir * d;
                        bool   accepted = (tmp > this.Range[0]) && (tmp < this.Range[1]);
                        if (!accepted)
                        {
                            double myD = d;
                            while (!accepted)
                            {
                                myD      = myD / 2;
                                tmp      = mode.X + dir * myD;
                                accepted = (tmp > this.Range[0]) && (tmp < this.Range[1]);
                            }
                        }

                        fp[0]    = this.O.LogFPrime(tmp, A);
                        accepted = fp[0].IsFinite();
                        while (!accepted)
                        {
                            tmp      = (tmp + mode.X) / 2;
                            fp[0]    = this.O.LogFPrime(tmp, A);
                            accepted = fp[0].IsFinite();
                        }

                        double a  = fp[0] / d;                                                // # estimated rate of slope acceleration
                        double d2 = Math.Sqrt(2 * Math.Abs(Math.Log(this.FRatioRemote) / a)); // # estimated distance we need to get from mode,
                                                                                              //# at the rate above, to reach the f.ratio.remote distance
                        double x2 = mode.X + dir * d2;
                        accepted = (x2 > this.Range[0]) && (x2 < this.Range[1]);
                        while (!accepted)
                        {
                            d2       = d2 / 2;
                            x2       = mode.X + dir * d2;
                            accepted = x2 > this.Range[0] & x2 < this.Range[1];
                        }

                        double fp2 = this.O.LogFPrime(x2, A);
                        accepted = fp2.IsFinite();

                        while (!accepted)
                        {
                            d2       = d2 / 2;
                            x2       = mode.X + dir * d2;
                            fp2      = this.O.LogFPrime(x2, A);
                            accepted = Tools.IsFinite(fp2);
                        }

                        x = new double[2] {
                            tmp, x2
                        };
                        f = new double[2] {
                            Tools.NA, Tools.NA
                        };
                        for (int i = 0; i < 2; i++)
                        {
                            f[i] = this.O.LogF(x[i], A);
                        }
                        fp[1] = fp2;

                        //# Approximating the shape of log.f.prime by a straight line,
                        //# we can estimate the point where the distance
                        //# prescribed by f.ratio.remote is reached

                        double[,] xSolved = Matrix2x2.Solve2x2(new double[] { x[0], x[1], 1, 1 }, byCol: true); // # 2 x 2 matrix
                        double[] theta = Matrix2x2.Product(xSolved, fp);
                        double   qA    = theta[0];
                        double   qB    = theta[1];
                        // ifelse(xor(j==1, x[1]>x[2]), 2, 1)
                        int    innerSide = (j == 0) ^ (x[0] > x[1]) ? 1 : 0;
                        double innerX    = x[innerSide];
                        double qC        = -qA *Math.Pow(innerX, 2) - qB * innerX - (target - f[innerSide]);

                        double l;
                        double u;
                        if (j == 0)
                        {
                            l = this.Range[0];
                            u = mode.X;
                        }
                        else
                        {
                            l = mode.X;
                            u = this.Range[1];
                        }

                        List <double> roots = QuadraticEquation.GetRealRoots(new double[] { qC, qB, qA }, l: l, u: u, ROrder: true);// # modif_0.11
                        switch (roots.Count)
                        {
                        case 0:
                            this.Start[j] = x[1 - innerSide];
                            break;

                        case 1:
                            this.Start[j] = roots[0];
                            break;

                        default:
                            if (j == 1)
                            {
                                this.Start[j] = roots.Max();
                            }
                            else
                            {
                                this.Start[j] = roots.Min();
                            }
                            break;
                        }
                    }
                }
                //# new_0.11
                //# Suggest another starting point (on both sides)
                //# based on the 2nd degree polynomial approximation (Taylor series devpmt) of log.f

                f = new double[0];
                if (!modeOnBorder.Any(pX => pX))
                {
                    double   delta = Math.Sqrt(2 * logFRatioRemote / fs);
                    double[] altStart;

                    //# Left
                    double xScalar = mode.X - delta;
                    if (xScalar > this.Range[0])
                    {
                        altStart = new double[] { this.Start[0], xScalar };
                        f        = new double[] { Math.Abs(this.O.LogF(altStart[0], A) - target), Math.Abs(this.O.LogF(altStart[1], A) - target) };
                        IEnumerable <double> lstD = f.Substract(target).Abs();
                        int w = (lstD.First() < lstD.Last()) ? 0 : 1;
                        this.Start[0] = altStart[w];
                    }

                    //# Right side
                    xScalar = mode.X + delta;
                    if (xScalar < this.Range[1])
                    {
                        altStart = new double[] { this.Start[1], xScalar };
                        f        = new double[] { Math.Abs(this.O.LogF(altStart[0], A) - target), Math.Abs(this.O.LogF(altStart[1], A) - target) };
                        IEnumerable <double> lstD = f.Substract(target).Abs();
                        int w = (lstD.First() < lstD.Last()) ? 0 : 1;
                        this.Start[1] = altStart[w];
                    }
                }
                //oh <- list(h=o$log.f, hp=o$log.f.prime, hs=o$log.f.second)
                SecuredNRA oh = new SecuredNRA(this.O.LogF, this.O.LogFPrime, this.O.LogFSecond);// # modif_0.11
                if (Tools.IsNA(this.Start[0]))
                {
                    remoteLeft = mode.X;
                }
                else
                {
                    double[] range = new double[] { this.Range[0], mode.X };
                    //LMaxPoint lm = new LMaxPoint(mode);
                    nr = new SecuredNRSearch(oh, A, this.Start[0], this.Epsilon, range,
                                             maxPoint: mode, target: target, inestimableLowerLimit: this.InestimableLowerLimit);
                    // le dernier paramètre a une valeur par défaut: expectedHpSign = -1

                    if (nr.Converged)
                    {
                        remoteLeft = nr.X;
                    }
                    else if (this.Range[0].IsFinite())
                    {
                        remoteLeft = this.Range[0];
                    }
                    else
                    {
                        //TODO Exception
                        throw new WEException("Fin temporaire!");
                    }
                }

                if (Tools.IsNA(this.Start[1]))
                {
                    remoteRight = mode.X;
                } // if
                else
                {
                    this.Range = new double[] { mode.X, this.Range[1] };
                    nr         = new SecuredNRSearch(oh, A, this.Start[1], this.Epsilon, this.Range,
                                                     maxPoint: mode, target: target);
                    // les 2 derniers paramètres prennent des valeurs par défaut:
                    // inestimableLowerLimit = false, expectedHpSign = -1
                    if (nr.Converged)
                    {
                        remoteRight = nr.X;
                    }
                    else
                    {
                        throw new WEException("Algorithm did not converge.");// # should not happen
                    }
                }
            }
            else
            {
                //# new_0.11
                //# mode was not found
                remoteLeft  = Tools.NA;
                remoteRight = Tools.NA;
            }

            //list(mode = mode, remote = c(remote.left, remote.right))

            LModeExt lmext = new LModeExt(mode, remoteLeft, remoteRight);

            return(lmext);
        } //# end of ref.points