/** * Tests the hypergeometric distribution code, or other functions provided in this module. * * @param args Either none, and the log add rountines are tested, or the following 4 arguments: k * (cell), n (total), r (row), m (col) */ public static void main(String[] args) { if (args.length == 0) { System.err.println( "Usage: java edu.stanford.nlp.math.SloppyMath " + "[-logAdd|-fishers k n r m|-binomial r n p"); } else if (args[0].equals("-logAdd")) { System.out.println("Log adds of neg infinity numbers, etc."); System.out.println( "(logs) -Inf + -Inf = " + logAdd(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY)); System.out.println("(logs) -Inf + -7 = " + logAdd(Double.NEGATIVE_INFINITY, -7.0)); System.out.println("(logs) -7 + -Inf = " + logAdd(-7.0, Double.NEGATIVE_INFINITY)); System.out.println("(logs) -50 + -7 = " + logAdd(-50.0, -7.0)); System.out.println("(logs) -11 + -7 = " + logAdd(-11.0, -7.0)); System.out.println("(logs) -7 + -11 = " + logAdd(-7.0, -11.0)); System.out.println("real 1/2 + 1/2 = " + logAdd(Math.log(0.5), Math.log(0.5))); } else if (args[0].equals("-fishers")) { int k = Integer.parseInt(args[1]); int n = Integer.parseInt(args[2]); int r = Integer.parseInt(args[3]); int m = Integer.parseInt(args[4]); double ans = SloppyMath.hypergeometric(k, n, r, m); System.out.println("hypg(" + k + "; " + n + ", " + r + ", " + m + ") = " + ans); ans = SloppyMath.oneTailedFishersExact(k, n, r, m); System.out.println( "1-tailed Fisher's exact(" + k + "; " + n + ", " + r + ", " + m + ") = " + ans); double ansChi = SloppyMath.chiSquare2by2(k, n, r, m); System.out.println("chiSquare(" + k + "; " + n + ", " + r + ", " + m + ") = " + ansChi); System.out.println("Swapping arguments should give same hypg:"); ans = SloppyMath.hypergeometric(k, n, r, m); System.out.println("hypg(" + k + "; " + n + ", " + m + ", " + r + ") = " + ans); int othrow = n - m; int othcol = n - r; int cell12 = m - k; int cell21 = r - k; int cell22 = othrow - (r - k); ans = SloppyMath.hypergeometric(cell12, n, othcol, m); System.out.println("hypg(" + cell12 + "; " + n + ", " + othcol + ", " + m + ") = " + ans); ans = SloppyMath.hypergeometric(cell21, n, r, othrow); System.out.println("hypg(" + cell21 + "; " + n + ", " + r + ", " + othrow + ") = " + ans); ans = SloppyMath.hypergeometric(cell22, n, othcol, othrow); System.out.println( "hypg(" + cell22 + "; " + n + ", " + othcol + ", " + othrow + ") = " + ans); } else if (args[0].equals("-binomial")) { int k = Integer.parseInt(args[1]); int n = Integer.parseInt(args[2]); double p = Double.parseDouble(args[3]); double ans = SloppyMath.exactBinomial(k, n, p); System.out.println("Binomial p(X >= " + k + "; " + n + ", " + p + ") = " + ans); } else { System.err.println("Unknown option: " + args[0]); } }
/** * Find a one-tailed Fisher's exact probability. Chance of having seen this or a more extreme * departure from what you would have expected given independence. I.e., k >= the value passed in. * Warning: this was done just for collocations, where you are concerned with the case of k being * larger than predicted. It doesn't correctly handle other cases, such as k being smaller than * expected. * * @param k The number of black balls drawn * @param n The total number of balls * @param r The number of black balls * @param m The number of balls drawn * @return The Fisher's exact p-value */ public static double oneTailedFishersExact(int k, int n, int r, int m) { if (k < 0 || k < (m + r) - n || k > r || k > m || r > n || m > n) { throw new IllegalArgumentException( "Invalid Fisher's exact: " + "k=" + k + " n=" + n + " r=" + r + " m=" + m + " k<0=" + (k < 0) + " k<(m+r)-n=" + (k < (m + r) - n) + " k>r=" + (k > r) + " k>m=" + (k > m) + " r>n=" + (r > n) + "m>n=" + (m > n)); } // exploit symmetry of problem if (m > n / 2) { m = n - m; k = r - k; } if (r > n / 2) { r = n - r; k = m - k; } if (m > r) { int temp = m; m = r; r = temp; } // now we have that k <= m <= r <= n/2 double total = 0.0; if (k > m / 2) { // sum from k to m for (int k0 = k; k0 <= m; k0++) { // System.out.println("Calling hypg(" + k0 + "; " + n + // ", " + r + ", " + m + ")"); total += SloppyMath.hypergeometric(k0, n, r, m); } } else { // sum from max(0, (m+r)-n) to k-1, and then subtract from 1 int min = Math.max(0, (m + r) - n); for (int k0 = min; k0 < k; k0++) { // System.out.println("Calling hypg(" + k0 + "; " + n + // ", " + r + ", " + m + ")"); total += SloppyMath.hypergeometric(k0, n, r, m); } total = 1.0 - total; } return total; }
public double iScore(Edge edge) { return SloppyMath.min(scorer1.iScore(edge), scorer2.iScore(edge)); }