/// <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); }
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))); } } } }