BinomialDistribution.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.5.0).
003  * Copyright (c) 2007-2013 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019  */
020 package org.jenetics.stat;
021 
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static org.jenetics.util.object.checkProbability;
025 
026 import java.io.Serializable;
027 
028 import org.jscience.mathematics.number.Float64;
029 
030 import org.jenetics.util.Function;
031 import org.jenetics.util.Range;
032 
033 /**
034  * TODO: implement BinomialDistribution
035  *
036  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
037  @since 1.0
038  @version 1.0 &mdash; <em>$Date: 2013-09-01 $</em>
039  */
040 class BinomialDistribution<
041     extends Number & Comparable<? super N>
042 >
043     implements Distribution<N>
044 {
045 
046     static final class PDF<N extends Number & Comparable<? super N>>
047         implements
048             Function<N, Float64>,
049             Serializable
050     {
051         private static final long serialVersionUID = 1L;
052 
053         private final Range<N> _domain;
054 
055         private final long _N;
056         private final double _p;
057         private final double _q;
058 
059         public PDF(final Range<N> domain, final double p) {
060             _domain = domain;
061             _N = domain.getMax().longValue() - domain.getMin().longValue();
062             _p = p;
063             _q = 1.0 - p;
064         }
065 
066         @Override
067         public Float64 apply(final N value) {
068             final long x = value.longValue() - _domain.getMin().longValue();
069 
070             Float64 result = Float64.ZERO;
071             if (_domain.contains(value)) {
072                 result = Float64.valueOf(
073                         binomial(_N, x)*Math.pow(_p, x)*Math.pow(_q, _N - x)
074                     );
075             }
076 
077             return result;
078         }
079 
080         @Override
081         public String toString() {
082             return format("p(x) = %s""");
083         }
084 
085     }
086 
087     static final class CDF<N extends Number & Comparable<? super N>>
088         implements
089             Function<N, Float64>,
090             Serializable
091     {
092         private static final long serialVersionUID = 1L;
093 
094         private final Range<N> _domain;
095 
096         private final long _N;
097         private final double _p;
098         private final double _q;
099 
100         public CDF(final Range<N> domain, final double p) {
101             _domain = domain;
102             _N = domain.getMax().longValue() - domain.getMin().longValue();
103             _p = p;
104             _q = 1.0 - p;
105         }
106 
107         @Override
108         public Float64 apply(final N value) {
109             long x = value.longValue();
110 
111             Float64 result = null;
112             if (_domain.getMin().longValue() > x) {
113                 result = Float64.ZERO;
114             else if (_domain.getMax().longValue() < x) {
115                 result = Float64.ONE;
116             else {
117                 x = x - _domain.getMin().longValue();
118                 double v = 0;
119                 for (long i = 0; i <= x; ++i) {
120                     v += binomial(_N, i)*Math.pow(_p, i)*Math.pow(_q, _N - i);
121                 }
122                 result = Float64.valueOf(v);
123             }
124 
125             return result;
126         }
127 
128         @Override
129         public String toString() {
130             return format("p(x) = %s""");
131         }
132 
133     }
134 
135     private final Range<N> _domain;
136     private final double _p;
137 
138     public BinomialDistribution(final Range<N> domain, final double p) {
139         _domain = requireNonNull(domain, "Domain");
140         _p = checkProbability(p);
141     }
142 
143     @Override
144     public Range<N> getDomain() {
145         return _domain;
146     }
147 
148     @Override
149     public Function<N, Float64> getCDF() {
150         return new CDF<>(_domain, _p);
151     }
152 
153     @Override
154     public Function<N, Float64> getPDF() {
155         return new PDF<>(_domain, _p);
156     }
157 
158     private static double binomial(final long n, final long k) {
159         long b = 1;
160         for (long i = 1; i <= k; ++i) {
161             b *= (n - k + i)/i;
162         }
163         return b;
164     }
165 
166 }