/** * Invertion of cdf by bisection numeric root finding of "cdf(x) = p" * for discrete distribution.* Returns integer n such that * P(<n) ≤ p ≤ P(<n+1). */ protected double quantile(double p, int xmin, int xmax) { while (xmax - xmin > 1) { int xmed = (xmax + xmin) / 2; if (cdf(xmed) > p) { xmax = xmed; } else { xmin = xmed; } } if (cdf(xmin) >= p) return xmin; else return xmax; } }
/** * The likelihood given a sample set following the distribution. */ public double likelihood(int[] x) { return Math.exp(logLikelihood(x)); }
/** * The likelihood given a sample set following the distribution. */ public double logLikelihood(int[] x) { double L = 0.0; for (double xi : x) L += logp(xi); return L; }
@Override public double p(double x) { if (x - Math.floor(x) != 0) return 0.0; else return p((int)x); }
/** * Generate the quantile-quantile pairs. */ private static double[][] quantile(int[] x, DiscreteDistribution d) { Arrays.sort(x); int n = x.length; double[][] q = new double[n][2]; for (int i = 0; i < n; i++) { double p = (i + 1) / (n + 1.0); q[i][0] = x[(int) Math.round(p * x.length)]; q[i][1] = d.quantile(p); } return q; }
@Override public double var() { if (components.isEmpty()) { throw new IllegalStateException("Mixture is empty!"); } double variance = 0.0; for (Component c : components) { variance += c.priori * c.priori * c.distribution.var(); } return variance; }
@Override public double mean() { if (components.isEmpty()) { throw new IllegalStateException("Mixture is empty!"); } double mu = 0.0; for (Component c : components) { mu += c.priori * c.distribution.mean(); } return mu; }
@Override public int npara() { if (components.isEmpty()) { throw new IllegalStateException("Mixture is empty!"); } int f = 0; for (int i = 0; i < components.size(); i++) { f += components.get(i).distribution.npara(); } return f; }
@Override public double rand() { if (components.isEmpty()) { throw new IllegalStateException("Mixture is empty!"); } double r = Math.random(); double p = 0.0; for (Component g : components) { p += g.priori; if (r <= p) { return g.distribution.rand(); } } // we should not arrive here. return components.get(components.size() - 1).distribution.rand(); }
@Override public double p(int x) { if (components.isEmpty()) { throw new IllegalStateException("Mixture is empty!"); } double p = 0.0; for (Component c : components) { p += c.priori * c.distribution.p(x); } return p; }
/** * Create a plot canvas with the one sample Q-Q plot to given distribution. * The x-axis is the quantiles of x and the y-axis is the quantiles of * given distribution. * @param x a sample set. * @param d a distribution. */ public static PlotCanvas plot(int[] x, DiscreteDistribution d) { double[] lowerBound = {Math.min(x), d.quantile(1 / (x.length + 1.0))}; double[] upperBound = {Math.max(x), d.quantile(x.length / (x.length + 1.0))}; PlotCanvas canvas = new PlotCanvas(lowerBound, upperBound); canvas.add(new QQPlot(x, d)); return canvas; }
@Override public double logp(double x) { if (x - Math.floor(x) != 0) return Double.NaN; else return logp((int)x); }
@Override public double cdf(double x) { if (components.isEmpty()) { throw new IllegalStateException("Mixture is empty!"); } double p = 0.0; for (Component c : components) { p += c.priori * c.distribution.cdf(x); } return p; }