Esempio n. 1
0
        /// <summary>
        /// Compute the difference of given weights.
        /// </summary>
        /// <param name="weight1">The first weight.</param>
        /// <param name="weight2">The second weight.</param>
        /// <returns>The computed difference.</returns>
        public static Weight AbsoluteDifference(Weight weight1, Weight weight2)
        {
            double min = Math.Min(weight1.LogValue, weight2.LogValue);
            double max = Math.Max(weight1.LogValue, weight2.LogValue);

            return(new Weight(MMath.LogDifferenceOfExp(max, min)));
        }
            /// <summary>
            /// Gets a value indicating how close this weight function is to a given one
            /// in terms of weights they assign to sequences.
            /// </summary>
            /// <param name="that">The other weight function.</param>
            /// <returns>The logarithm of a non-negative value, which is close to zero if the two automata assign similar values to all sequences.</returns>
            protected double GetLogSimilarity(TThis that)
            {
                // Consistently with Automaton.GetLogSimilarity
                var thisIsZero = IsZero();
                var thatIsZero = that.IsZero();

                if (thisIsZero)
                {
                    return(thatIsZero ? double.NegativeInfinity : 1.0);
                }
                if (thatIsZero)
                {
                    return(1.0);
                }

                double logNormProduct = GetLogNormalizerOfProduct(that);

                if (double.IsNegativeInfinity(logNormProduct))
                {
                    return(1.0);
                }

                double logNormThisSquared = GetLogNormalizerOfSquare();
                double logNormThatSquared = that.GetLogNormalizerOfSquare();

                double term1  = MMath.LogSumExp(logNormThisSquared, logNormThatSquared);
                double term2  = logNormProduct + MMath.Ln2;
                double result = MMath.LogDifferenceOfExp(Math.Max(term1, term2), Math.Min(term1, term2)); // To avoid NaN due to numerical instabilities

                System.Diagnostics.Debug.Assert(!double.IsNaN(result), "Log-similarity must be a valid number.");
                return(result);
            }
Esempio n. 3
0
        private static double NormalCdfLn_Quadrature(double x, double y, double r)
        {
            double absr = System.Math.Abs(r);
            Vector nodes, weights;
            int    count = 20;

            if (absr < 0.3)
            {
                count = 6;
            }
            else if (absr < 0.75)
            {
                count = 12;
            }
            nodes   = Vector.Zero(count);
            weights = Vector.Zero(count);
            // hasInfiniteLimit is true if NormalCdf(x,y,-1) is 0
            bool hasInfiniteLimit = false;

            if (r < -0.5)
            {
                if (x > 0)
                {
                    // NormalCdf(y) <= NormalCdf(-x)  iff y <= -x
                    if (y < 0)
                    {
                        hasInfiniteLimit = (y <= -x);
                    }
                }
                else
                {
                    // NormalCdf(x) <= NormalCdf(-y) iff x <= -y
                    if (y > 0)
                    {
                        hasInfiniteLimit = (x <= -y);
                    }
                    else
                    {
                        hasInfiniteLimit = true;
                    }
                }
            }
            if (absr < 0.925 && !hasInfiniteLimit)
            {
                // use equation (3)
                double asinr = System.Math.Asin(r);
                Quadrature.UniformNodesAndWeights(0, asinr, nodes, weights);
                double sq = 0.5 * (x * x + y * y), xy = x * y;
                double logResult     = double.NegativeInfinity;
                bool   useLogWeights = true;
                if (useLogWeights)
                {
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        double sin  = System.Math.Sin(nodes[i]);
                        double cos2 = 1 - sin * sin;
                        logResult = MMath.LogSumExp(logResult, System.Math.Log(System.Math.Abs(weights[i])) + (xy * sin - sq) / cos2);
                    }
                    logResult -= 2 * MMath.LnSqrt2PI;
                }
                else
                {
                    double result = 0.0;
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        double sin  = System.Math.Sin(nodes[i]);
                        double cos2 = 1 - sin * sin;
                        result += weights[i] * System.Math.Exp((xy * sin - sq) / cos2);
                    }
                    result   /= 2 * System.Math.PI;
                    logResult = System.Math.Log(System.Math.Abs(result));
                }
                double r0 = MMath.NormalCdfLn(x, y, 0);
                if (asinr > 0)
                {
                    return(MMath.LogSumExp(r0, logResult));
                }
                else
                {
                    return(MMath.LogDifferenceOfExp(r0, logResult));
                }
            }
            else
            {
                double result = 0.0;
                double sy     = (r < 0) ? -y : y;
                if (absr < 1)
                {
                    // use equation (6) modified by (7)
                    // quadrature part
                    double cos2asinr = (1 - r) * (1 + r), sqrt1mrr = System.Math.Sqrt(cos2asinr);
                    Quadrature.UniformNodesAndWeights(0, sqrt1mrr, nodes, weights);
                    double sxy = x * sy;
                    double diff2 = (x - sy) * (x - sy);
                    double c = (4 - sxy) / 8, d = (12 - sxy) / 16;
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        double cos2     = nodes[i] * nodes[i];
                        double sin      = System.Math.Sqrt(1 - cos2);
                        double series   = 1 + c * cos2 * (1 + d * cos2);
                        double exponent = -0.5 * (diff2 / cos2 + sxy);
                        double f        = System.Math.Exp(-0.5 * sxy * (1 - sin) / (1 + sin)) / sin;
                        result += weights[i] * System.Math.Exp(exponent) * (f - series);
                    }
                    // Taylor expansion part
                    double exponentr = -0.5 * (diff2 / cos2asinr + sxy);
                    double absdiff   = System.Math.Sqrt(diff2);
                    if (exponentr > -800)
                    {
                        double taylor = sqrt1mrr * (1 - c * (diff2 - cos2asinr) * (1 - d * diff2 / 5) / 3 + c * d * cos2asinr * cos2asinr / 5);
                        // avoid 0*Inf problems
                        //result -= Math.Exp(-0.5*sxy + NormalCdfLn(-absdiff/sqrt1mrr))*absdiff*(1 - c*diff2*(1 - d*diff2/5)/3)*Sqrt2PI;
                        taylor -= MMath.NormalCdfRatio(-absdiff / sqrt1mrr) * absdiff * (1 - c * diff2 * (1 - d * diff2 / 5) / 3);
                        result += System.Math.Exp(exponentr) * taylor;
                    }
                    result /= -2 * System.Math.PI;
                }
                if (r > 0)
                {
                    // result += NormalCdf(x, y, 1);
                    double r1 = MMath.NormalCdfLn(x, y, 1);
                    if (result > 0)
                    {
                        result = System.Math.Log(result);
                        return(MMath.LogSumExp(result, r1));
                    }
                    else
                    {
                        return(MMath.LogDifferenceOfExp(r1, System.Math.Log(-result)));
                    }
                }
                else
                {
                    // return NormalCdf(x, y, -1) - result;
                    double r1 = MMath.NormalCdfLn(x, y, -1);
                    if (result > 0)
                    {
                        return(MMath.LogDifferenceOfExp(r1, System.Math.Log(result)));
                    }
                    else
                    {
                        return(MMath.LogSumExp(r1, System.Math.Log(-result)));
                    }
                }
            }
        }