1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.distribution.discrete;
23
24 import org.hipparchus.exception.LocalizedCoreFormats;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.MathUtils;
28
29
30
31
32
33
34
35 public class GeometricDistribution extends AbstractIntegerDistribution {
36
37
38 private static final long serialVersionUID = 20130507L;
39
40 private final double probabilityOfSuccess;
41
42 private final double logProbabilityOfSuccess;
43
44 private final double log1mProbabilityOfSuccess;
45
46
47
48
49
50
51
52 public GeometricDistribution(double p)
53 throws MathIllegalArgumentException {
54 if (p <= 0 || p > 1) {
55 throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_LEFT, p, 0, 1);
56 }
57
58 probabilityOfSuccess = p;
59 logProbabilityOfSuccess = FastMath.log(p);
60 log1mProbabilityOfSuccess = FastMath.log1p(-p);
61 }
62
63
64
65
66
67
68 public double getProbabilityOfSuccess() {
69 return probabilityOfSuccess;
70 }
71
72
73 @Override
74 public double probability(int x) {
75 if (x < 0) {
76 return 0.0;
77 } else {
78 return FastMath.exp(log1mProbabilityOfSuccess * x) * probabilityOfSuccess;
79 }
80 }
81
82
83 @Override
84 public double logProbability(int x) {
85 if (x < 0) {
86 return Double.NEGATIVE_INFINITY;
87 } else {
88 return x * log1mProbabilityOfSuccess + logProbabilityOfSuccess;
89 }
90 }
91
92
93 @Override
94 public double cumulativeProbability(int x) {
95 if (x < 0) {
96 return 0.0;
97 } else {
98 return -FastMath.expm1(log1mProbabilityOfSuccess * (x + 1));
99 }
100 }
101
102
103
104
105
106
107 @Override
108 public double getNumericalMean() {
109 return (1 - probabilityOfSuccess) / probabilityOfSuccess;
110 }
111
112
113
114
115
116
117
118 @Override
119 public double getNumericalVariance() {
120 return (1 - probabilityOfSuccess) / (probabilityOfSuccess * probabilityOfSuccess);
121 }
122
123
124
125
126
127
128
129
130 @Override
131 public int getSupportLowerBound() {
132 return 0;
133 }
134
135
136
137
138
139
140
141
142
143 @Override
144 public int getSupportUpperBound() {
145 return Integer.MAX_VALUE;
146 }
147
148
149
150
151
152
153
154
155 @Override
156 public boolean isSupportConnected() {
157 return true;
158 }
159
160
161
162
163 @Override
164 public int inverseCumulativeProbability(double p) throws MathIllegalArgumentException {
165 MathUtils.checkRangeInclusive(p, 0, 1);
166
167 if (p == 1) {
168 return Integer.MAX_VALUE;
169 }
170 if (p == 0) {
171 return 0;
172 }
173 return Math.max(0, (int) Math.ceil(FastMath.log1p(-p)/log1mProbabilityOfSuccess-1));
174 }
175 }