// Use the large variance approximation to sigma(m,v) = \int N(x;m,v) logistic(x) private static void BigvProposal(double m, double v, out double mf, out double vf) { double v2 = v + Math.PI * Math.PI / 3.0; double Z = MMath.NormalCdf(m / Math.Sqrt(v2)); double s1 = Math.Exp(Gaussian.GetLogProb(0, m, v2)); double s2 = -s1 * m / v2; mf = m + v * s1 / Z; double Ex2 = v + m * m + 2 * m * v * s1 / Z + v * v * s2 / Z; vf = Ex2 - mf * mf; }
// Helper function for NormalCdfRatioConFrac private static double NormalCdfRatioConFracNumer(double x, double y, double r, double scale, double sqrtomr2, double diff, double Rdiff) { double delta = (1 + r) * (y - x) / sqrtomr2; double numer; if (Math.Abs(delta) > 0.5) { numer = scale * r * Rdiff; double diffy = (y - r * x) / sqrtomr2; if (scale == 1) { numer += MMath.NormalCdfRatio(diffy); } else // this assumes scale = N((y-rx)/sqrt(1-r^2);0,1) { numer += MMath.NormalCdf(diffy); } } else { numer = scale * (NormalCdfRatioDiff(diff, delta) + (1 + r) * Rdiff); } return(numer); }
/// <summary> /// Computes the cumulative bivariate normal distribution. /// </summary> /// <param name="x">First upper limit.</param> /// <param name="y">Second upper limit.</param> /// <param name="r">Correlation coefficient.</param> /// <returns><c>phi(x,y,r)</c></returns> /// <remarks> /// The cumulative bivariate normal distribution is defined as /// <c>int_(-inf)^x int_(-inf)^y N([x;y],[0;0],[1 r; r 1]) dx dy</c> /// where <c>N([x;y],[0;0],[1 r; r 1]) = exp(-0.5*(x^2+y^2-2*x*y*r)/(1-r^2))/(2*pi*sqrt(1-r^2))</c>. /// </remarks> public static double NormalCdf(double x, double y, double r) { if (Double.IsNegativeInfinity(x) || Double.IsNegativeInfinity(y)) { return(0.0); } else if (Double.IsPositiveInfinity(x)) { return(NormalCdf(y)); } else if (Double.IsPositiveInfinity(y)) { return(NormalCdf(x)); } else if (r == 0) { return(NormalCdf(x) * NormalCdf(y)); } else if (r == 1) { return(NormalCdf(Math.Min(x, y))); } else if (r == -1) { return(Math.Max(0.0, NormalCdf(x) + NormalCdf(y) - 1)); } // at this point, both x and y are finite. // swap to ensure |x| > |y| if (Math.Abs(y) > Math.Abs(x)) { double t = x; x = y; y = t; } double offset = 0; double scale = 1; // ensure x <= 0 if (x > 0) { // phi(x,y,r) = phi(inf,y,r) - phi(-x,y,-r) offset = MMath.NormalCdf(y); scale = -1; x = -x; r = -r; } // ensure r <= 0 if (r > 0) { // phi(x,y,r) = phi(x,inf,r) - phi(x,-y,-r) offset += scale * MMath.NormalCdf(x); scale *= -1; y = -y; r = -r; } double omr2 = (1 - r) * (1 + r); // more accurate than 1-r*r double ymrx = (y - r * x) / Math.Sqrt(omr2); double exponent; double result = NormalCdf_Helper(x, y, r, omr2, ymrx, out exponent); return(offset + scale * result * Math.Exp(exponent)); }