SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
NegativeMultinomialDist.java
1/*
2 * Class: NegativeMultinomialDist
3 * Description: negative multinomial distribution
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.probdistmulti;
26
27import umontreal.ssj.util.Num;
28import umontreal.ssj.util.RootFinder;
29import umontreal.ssj.functions.MathFunction;
30
48 protected double n;
49 protected double p[];
50
51 private static class Function implements MathFunction {
52 protected double Fl[];
53 protected int ups[];
54 protected int k;
55 protected int M;
56 protected int sumUps;
57
58 public Function(int k, int m, int ups[], double Fl[]) {
59 this.k = k;
60 this.M = m;
61
62 this.Fl = new double[Fl.length];
63 System.arraycopy(Fl, 0, this.Fl, 0, Fl.length);
64 this.ups = new int[ups.length];
65 System.arraycopy(ups, 0, this.ups, 0, ups.length);
66
67 sumUps = 0;
68 for (int i = 0; i < ups.length; i++)
69 sumUps += ups[i];
70 }
71
72 public double evaluate(double gamma) {
73 double sum = 0.0;
74 for (int l = 0; l < M; l++)
75 sum += (Fl[l] / (gamma + (double) l));
76 return (sum - Math.log1p(sumUps / (k * gamma)));
77 }
78 }
79
80 private static class FuncInv extends Function implements MathFunction {
81
82 public FuncInv(int k, int m, int ups[], double Fl[]) {
83 super(k, m, ups, Fl);
84 }
85
86 public double evaluate(double nu) {
87 double sum = 0.0;
88 for (int l = 0; l < M; l++)
89 sum += Fl[l] / (1.0 + nu * l);
90 return (sum * nu - Math.log1p(sumUps * nu / k));
91 }
92 }
93
99 public NegativeMultinomialDist(double n, double p[]) {
100 setParams(n, p);
101 }
102
103 public double prob(int x[]) {
104 return prob_(n, p, x);
105 }
106
107 /*
108 * public double cdf (int x[]) { throw new UnsupportedOperationException
109 * ("cdf not implemented"); }
110 */
111 public double[] getMean() {
112 return getMean_(n, p);
113 }
114
115 public double[][] getCovariance() {
116 return getCovariance_(n, p);
117 }
118
119 public double[][] getCorrelation() {
120 return getCorrelation_(n, p);
121 }
122
123 private static void verifParam(double n, double p[]) {
124 double sumPi = 0.0;
125
126 if (n <= 0.0)
127 throw new IllegalArgumentException("n <= 0");
128
129 for (int i = 0; i < p.length; i++) {
130 if ((p[i] < 0) || (p[i] >= 1))
131 throw new IllegalArgumentException("p is not a probability vector");
132
133 sumPi += p[i];
134 }
135 if (sumPi >= 1.0)
136 throw new IllegalArgumentException("p is not a probability vector");
137 }
138
139 private static double prob_(double n, double p[], int x[]) {
140 double p0 = 0.0;
141 double sumPi = 0.0;
142 double sumXi = 0.0;
143 double sumLnXiFact = 0.0;
144 double sumXiLnPi = 0.0;
145
146 if (x.length != p.length)
147 throw new IllegalArgumentException("x and p must have the same size");
148
149 for (int i = 0; i < p.length; i++) {
150 sumPi += p[i];
151 sumXi += x[i];
152 sumLnXiFact += Num.lnFactorial(x[i]);
153 sumXiLnPi += x[i] * Math.log(p[i]);
154 }
155 p0 = 1.0 - sumPi;
156
157 return Math.exp(Num.lnGamma(n + sumXi) - (Num.lnGamma(n) + sumLnXiFact) + n * Math.log(p0) + sumXiLnPi);
158 }
159
168 public static double prob(double n, double p[], int x[]) {
169 verifParam(n, p);
170 return prob_(n, p, x);
171 }
172
173 private static double cdf_(double n, double p[], int x[]) {
174 throw new UnsupportedOperationException("cdf not implemented");
175 }
176
182 public static double cdf(double n, double p[], int x[]) {
183 verifParam(n, p);
184
185 return cdf_(n, p, x);
186 }
187
188 private static double[] getMean_(double n, double p[]) {
189 double p0 = 0.0;
190 double sumPi = 0.0;
191 double mean[] = new double[p.length];
192
193 for (int i = 0; i < p.length; i++)
194 sumPi += p[i];
195 p0 = 1.0 - sumPi;
196
197 for (int i = 0; i < p.length; i++)
198 mean[i] = n * p[i] / p0;
199
200 return mean;
201 }
202
207 public static double[] getMean(double n, double p[]) {
208 verifParam(n, p);
209
210 return getMean_(n, p);
211 }
212
213 private static double[][] getCovariance_(double n, double p[]) {
214 double p0 = 0.0;
215 double sumPi = 0.0;
216 double cov[][] = new double[p.length][p.length];
217
218 for (int i = 0; i < p.length; i++)
219 sumPi += p[i];
220 p0 = 1.0 - sumPi;
221
222 for (int i = 0; i < p.length; i++) {
223 for (int j = 0; j < p.length; j++)
224 cov[i][j] = n * p[i] * p[j] / (p0 * p0);
225
226 cov[i][i] = n * p[i] * (p[i] + p0) / (p0 * p0);
227 }
228
229 return cov;
230 }
231
236 public static double[][] getCovariance(double n, double p[]) {
237 verifParam(n, p);
238
239 return getCovariance_(n, p);
240 }
241
242 private static double[][] getCorrelation_(double n, double[] p) {
243 double corr[][] = new double[p.length][p.length];
244 double sumPi = 0.0;
245 double p0;
246
247 for (int i = 0; i < p.length; i++)
248 sumPi += p[i];
249 p0 = 1.0 - sumPi;
250
251 for (int i = 0; i < p.length; i++) {
252 for (int j = 0; j < p.length; j++)
253 corr[i][j] = Math.sqrt(p[i] * p[j] / ((p0 + p[i]) * (p0 + p[j])));
254 corr[i][i] = 1.0;
255 }
256 return corr;
257 }
258
263 public static double[][] getCorrelation(double n, double[] p) {
264 verifParam(n, p);
265 return getCorrelation_(n, p);
266 }
267
295 public static double[] getMLE(int x[][], int m, int d) {
296 int ups[] = new int[m];
297 double mean[] = new double[d];
298
299 int i, j, l;
300 int M;
301 int prop;
302
303 // Initialization
304 for (i = 0; i < d; i++)
305 mean[i] = 0;
306
307 // Ups_j = Sum_k x_ji
308 // mean_i = Sum_m x_ji / m
309 for (j = 0; j < m; j++) {
310 ups[j] = 0;
311 for (i = 0; i < d; i++) {
312 ups[j] += x[j][i];
313 mean[i] += x[j][i];
314 }
315 }
316 for (i = 0; i < d; i++)
317 mean[i] /= m;
318
319 /*
320 * double var = 0.0; if (d > 1) { // Calcule la covariance 0,1 for (j = 0; j <
321 * m; j++) var += (x[j][0] - mean[0])*(x[j][1] - mean[1]); var /= m; } else { //
322 * Calcule la variance 0 for (j = 0; j < m; j++) var += (x[j][0] -
323 * mean[0])*(x[j][0] - mean[0]); var /= m; }
324 */
325
326 // M = Max(Ups_j)
327 M = ups[0];
328 for (j = 1; j < m; j++)
329 if (ups[j] > M)
330 M = ups[j];
331
332 if (M >= Integer.MAX_VALUE)
333 throw new IllegalArgumentException("n/p_i too large");
334
335 double Fl[] = new double[M];
336 for (l = 0; l < M; l++) {
337 prop = 0;
338 for (j = 0; j < m; j++)
339 if (ups[j] > l)
340 prop++;
341
342 Fl[l] = (double) prop / (double) m;
343 }
344
345 /*
346 * // Estime la valeur initiale de n pour brentDekker: pourrait // accélérer
347 * brentDekker (gam0/1000, gam0*1000, f, 1e-5). // Reste à bien tester. if (d >
348 * 1) { double gam0 = mean[0] * mean[1] / var; System.out.println ("gam0 = " +
349 * gam0); } else { double t = var/mean[0] - 1.0; double gam0 = mean[0] / t;
350 * System.out.println ("gam0 = " + gam0); }
351 */
352 double parameters[] = new double[d + 1];
353 Function f = new Function(m, (int) M, ups, Fl);
354 parameters[0] = RootFinder.brentDekker(1e-9, 1e9, f, 1e-5);
355
356 double lambda[] = new double[d];
357 double sumLambda = 0.0;
358 for (i = 0; i < d; i++) {
359 lambda[i] = mean[i] / parameters[0];
360 sumLambda += lambda[i];
361 }
362
363 for (i = 0; i < d; i++) {
364 parameters[i + 1] = lambda[i] / (1.0 + sumLambda);
365 if (parameters[i + 1] > 1.0)
366 throw new IllegalArgumentException("p_i > 1");
367 }
368
369 return parameters;
370 }
371
387 public static double getMLEninv(int x[][], int m, int d) {
388 int ups[] = new int[m];
389 double mean[] = new double[d];
390 int i, j, l;
391 int M;
392 int prop;
393
394 // Initialization
395 for (i = 0; i < d; i++)
396 mean[i] = 0;
397
398 // Ups_j = Sum_k x_ji
399 // mean_i = Sum_m x_ji / m
400 for (j = 0; j < m; j++) {
401 ups[j] = 0;
402 for (i = 0; i < d; i++) {
403 ups[j] += x[j][i];
404 mean[i] += x[j][i];
405 }
406 }
407 for (i = 0; i < d; i++)
408 mean[i] /= m;
409
410 // M = Max(Ups_j)
411 M = ups[0];
412 for (j = 1; j < m; j++)
413 if (ups[j] > M)
414 M = ups[j];
415
416 if (M >= Integer.MAX_VALUE)
417 throw new IllegalArgumentException("n/p_i too large");
418
419 double Fl[] = new double[M];
420 for (l = 0; l < M; l++) {
421 prop = 0;
422 for (j = 0; j < m; j++)
423 if (ups[j] > l)
424 prop++;
425
426 Fl[l] = (double) prop / (double) m;
427 }
428
429 FuncInv f = new FuncInv(m, M, ups, Fl);
430 double nu = RootFinder.brentDekker(1.0e-8, 1.0e8, f, 1e-5);
431 return nu;
432 }
433
437 public double getGamma() {
438 return n;
439 }
440
444 public double[] getP() {
445 return p;
446 }
447
451 public void setParams(double n, double p[]) {
452 if (n <= 0.0)
453 throw new IllegalArgumentException("n <= 0");
454
455 this.n = n;
456 this.dimension = p.length;
457 this.p = new double[dimension];
458
459 double sumPi = 0.0;
460 for (int i = 0; i < dimension; i++) {
461 if ((p[i] < 0) || (p[i] >= 1))
462 throw new IllegalArgumentException("p is not a probability vector");
463
464 sumPi += p[i];
465 this.p[i] = p[i];
466 }
467
468 if (sumPi >= 1.0)
469 throw new IllegalArgumentException("p is not a probability vector");
470 }
471
472}
Classes implementing multi-dimensional discrete distributions over the integers should inherit from t...
double getGamma()
Returns the parameter of this object.
static double cdf(double n, double p[], int x[])
Computes the cumulative probability function of the negative multinomial distribution with parameter...
double[] getP()
Returns the parameters ( , …, ) of this object.
NegativeMultinomialDist(double n, double p[])
Creates a NegativeMultinomialDist object with parameters and ( , …, ) such that ,...
static double[][] getCorrelation(double n, double[] p)
Computes the correlation matrix of the negative multinomial distribution with parameters and ( ,...
static double[][] getCovariance(double n, double p[])
Computes the covariance matrix of the negative multinomial distribution with parameters and ( ,...
static double[] getMean(double n, double p[])
Computes the mean of the negative multinomial distribution with parameters and ( ,...
static double getMLEninv(int x[][], int m, int d)
Estimates and returns the parameter of the negative multinomial distribution using the maximum likel...
static double prob(double n, double p[], int x[])
Computes the probability mass function ( fNegativeMultinomial ) of the negative multinomial distribut...
void setParams(double n, double p[])
Sets the parameters and ( , …, ) of this object.
double prob(int x[])
Returns the probability mass function , which should be a real number in .
double[][] getCorrelation()
Returns the correlation matrix of the distribution, defined as.
double[] getMean()
Returns the mean vector of the distribution, defined as .
static double[] getMLE(int x[][], int m, int d)
Estimates and returns the parameters [ ,.
double[][] getCovariance()
Returns the variance-covariance matrix of the distribution, defined as .
This class provides numerical methods to solve non-linear equations.
static double brentDekker(double a, double b, MathFunction f, double tol)
Computes a root of the function in f using the Brent-Dekker method.
This interface should be implemented by classes which represent univariate mathematical functions.