/*
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
This file is part of GeoGebra.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation.
*/
package org.geogebra.common.kernel.statistics;
import java.util.ArrayList;
import org.apache.commons.math3.distribution.BinomialDistribution;
import org.apache.commons.math3.distribution.CauchyDistribution;
import org.apache.commons.math3.distribution.ChiSquaredDistribution;
import org.apache.commons.math3.distribution.ExponentialDistribution;
import org.apache.commons.math3.distribution.FDistribution;
import org.apache.commons.math3.distribution.GammaDistribution;
import org.apache.commons.math3.distribution.HypergeometricDistribution;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.PascalDistribution;
import org.apache.commons.math3.distribution.PoissonDistribution;
import org.apache.commons.math3.distribution.TDistribution;
import org.apache.commons.math3.distribution.WeibullDistribution;
import org.apache.commons.math3.distribution.ZipfDistribution;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.algos.AlgoElement;
import org.geogebra.common.kernel.geos.GeoBoolean;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoList;
import org.geogebra.common.kernel.geos.GeoNumberValue;
import org.geogebra.common.kernel.geos.GeoNumeric;
/**
*
* @author Michael Borcherds
* @version 20090730
*/
public abstract class AlgoDistribution extends AlgoElement {
/** input: dist. parameter */
protected GeoNumberValue a;
/** input: dist. parameter or variable value */
protected GeoNumberValue b;
/** input: dist. parameter or variable value */
protected GeoNumberValue c;
/** input: variable value */
protected GeoNumberValue d;
/** input: flag for cumulative function */
protected GeoBoolean isCumulative;
/** output number */
protected GeoNumeric num;
private TDistribution t = null;
private ChiSquaredDistribution chisquared = null;
private FDistribution f = null;
private GammaDistribution gamma = null;
private CauchyDistribution cauchy = null;
private ExponentialDistribution exponential = null;
private HypergeometricDistribution hypergeometric = null;
private PascalDistribution pascal = null;
private BinomialDistribution binomial = null;
private WeibullDistribution weibull = null;
private ZipfDistribution zipf = null;
private NormalDistribution normal = null;
private PoissonDistribution poisson = null;
protected GeoList list;
/**
* @param cons
* construction
* @param label
* label for output
* @param a
* first input element
* @param b
* second input element
* @param c
* third input element
* @param d
* fourth input element
*/
public AlgoDistribution(Construction cons, String label, GeoNumberValue a,
GeoNumberValue b, GeoNumberValue c, GeoNumberValue d) {
super(cons);
this.a = a;
this.b = b;
this.c = c;
this.d = d;
num = new GeoNumeric(cons);
setInputOutput();
compute();
num.setLabel(label);
}
/**
* @param cons
* construction
* @param label
* label for output
* @param a
* first input element
* @param b
* second input element
* @param c
* third input element
* @param isCumulative
* flag for cumulative
*/
public AlgoDistribution(Construction cons, String label, GeoNumberValue a,
GeoNumberValue b, GeoNumberValue c, GeoBoolean isCumulative) {
this(cons, a, b, c, isCumulative);
num.setLabel(label);
}
/**
* @param cons
* construction
* @param a
* first input element
* @param b
* second input element
* @param c
* third input element
* @param isCumulative
* flag for cumulative
*/
public AlgoDistribution(Construction cons, GeoNumberValue a,
GeoNumberValue b, GeoNumberValue c, GeoBoolean isCumulative) {
super(cons);
this.a = a;
this.b = b;
this.c = c;
this.isCumulative = isCumulative;
num = new GeoNumeric(cons);
setInputOutput();
compute();
}
/**
* @param cons
* construction
* @param label
* label for output
* @param a
* first input element
* @param b
* second input element
* @param c
* third input element
* @param d
* fourth input element
* @param isCumulative
* flag for cumulative
*/
public AlgoDistribution(Construction cons, String label, GeoNumberValue a,
GeoNumberValue b, GeoNumberValue c, GeoNumberValue d,
GeoBoolean isCumulative) {
this(cons, a, b, c, d, isCumulative);
num.setLabel(label);
}
/**
* @param cons
* construction
* @param a
* first input element
* @param b
* second input element
* @param c
* third input element
* @param d
* fourth input element
* @param isCumulative
* flag for cumulative
*/
public AlgoDistribution(Construction cons, GeoNumberValue a,
GeoNumberValue b, GeoNumberValue c, GeoNumberValue d,
GeoBoolean isCumulative) {
super(cons);
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.isCumulative = isCumulative;
num = new GeoNumeric(cons);
setInputOutput();
compute();
}
public AlgoDistribution(Construction cons, String label, GeoNumberValue a,
GeoNumberValue b, GeoList list) {
super(cons);
this.a = a;
this.b = b;
this.list = list;
num = new GeoNumeric(cons);
setInputOutput();
compute();
num.setLabel(label);
}
public AlgoDistribution(Construction cons, String label, GeoNumberValue a,
GeoList list) {
super(cons);
this.a = a;
this.list = list;
num = new GeoNumeric(cons);
setInputOutput();
compute();
num.setLabel(label);
}
@Override
protected void setInputOutput() {
// build array list of possible arguments
ArrayList<GeoElement> inputList = new ArrayList<GeoElement>();
inputList.add(a.toGeoElement());
inputList.add(b.toGeoElement());
if (c != null) {
inputList.add(c.toGeoElement());
}
if (d != null) {
inputList.add(d.toGeoElement());
}
if (isCumulative != null) {
inputList.add(isCumulative.toGeoElement());
}
// convert to array
input = new GeoElement[inputList.size()];
inputList.toArray(input);
setOnlyOutput(num);
setDependencies(); // done by AlgoElement
}
/**
* @return resulting number
*/
public GeoNumeric getResult() {
return num;
}
@Override
public abstract void compute();
/**
* @param param
* degrees of freedom
* @return T-distribution
*/
protected TDistribution getTDistribution(double param) {
if (t == null || t.getDegreesOfFreedom() != param) {
t = new TDistribution(param);
}
return t;
}
/**
* @param param
* degrees of freedom (numerator)
* @param param2
* degrees of freedom (denominator)
* @return F-distribution
*/
protected FDistribution getFDistribution(double param, double param2) {
if (f == null || f.getDenominatorDegreesOfFreedom() != param2
|| f.getNumeratorDegreesOfFreedom() != param) {
f = new FDistribution(param, param2);
}
return f;
}
/**
* @param param
* parameter beta
* @param param2
* parameter alpha
* @return gamma distribution
*/
protected GammaDistribution getGammaDistribution(double param,
double param2) {
if (gamma == null || gamma.getBeta() != param2
|| gamma.getAlpha() != param) {
gamma = new GammaDistribution(param, param2);
}
return gamma;
}
/**
* @param param
* median
* @param param2
* scale
* @return cauchy distribution
*/
protected CauchyDistribution getCauchyDistribution(double param,
double param2) {
if (cauchy == null || cauchy.getMedian() != param
|| cauchy.getScale() != param2) {
cauchy = new CauchyDistribution(param, param2);
}
return cauchy;
}
/**
* @param param
* degrees of freedom
* @return chi squared distribution
*/
protected ChiSquaredDistribution getChiSquaredDistribution(double param) {
if (chisquared == null || chisquared.getDegreesOfFreedom() != param) {
chisquared = new ChiSquaredDistribution(param);
}
return chisquared;
}
/**
* @param param
* mean
* @return exponential distribution
*/
protected ExponentialDistribution getExponentialDistribution(double param) {
if (exponential == null || exponential.getMean() != param) {
exponential = new ExponentialDistribution(1.0 / param);
}
return exponential;
}
/**
* @param param
* population size
* @param param2
* number of successes
* @param param3
* sample size
* @return hypergeometric distribution
*/
protected HypergeometricDistribution getHypergeometricDistribution(
int param, int param2, int param3) {
if (hypergeometric == null
|| hypergeometric.getNumberOfSuccesses() != param2
|| hypergeometric.getPopulationSize() != param
|| hypergeometric.getSampleSize() != param3) {
hypergeometric = new HypergeometricDistribution(param, param2,
param3);
}
return hypergeometric;
}
/**
* @param param
* number of successes
* @param param2
* prob. of success
* @return Pascal distribution
*/
protected PascalDistribution getPascalDistribution(int param,
double param2) {
if (pascal == null || pascal.getNumberOfSuccesses() != param
|| pascal.getProbabilityOfSuccess() != param2) {
pascal = new PascalDistribution(param, param2);
}
return pascal;
}
/**
* @param param
* mean
* @return Poisson distribution
*/
protected PoissonDistribution getPoissonDistribution(double param) {
if (poisson == null || poisson.getMean() != param) {
poisson = new PoissonDistribution(param);
}
return poisson;
}
/**
* @param param
* number of trials
* @param param2
* prob. of success
* @return binomial distribution
*/
protected BinomialDistribution getBinomialDistribution(int param,
double param2) {
if (binomial == null || binomial.getNumberOfTrials() != param
|| binomial.getProbabilityOfSuccess() != param2) {
binomial = new BinomialDistribution(param, param2);
}
return binomial;
}
/**
* @param param
* shape
* @param param2
* scale
* @return Weibull distribution
*/
WeibullDistribution getWeibullDistribution(double param, double param2) {
if (weibull == null || weibull.getShape() != param
|| weibull.getScale() != param2) {
weibull = new WeibullDistribution(param, param2);
}
return weibull;
}
/**
* @param param
* mean
* @param param2
* standard deviation
* @return normal distribution
*/
NormalDistribution getNormalDistribution(double param, double param2) {
if (normal == null || normal.getMean() != param
|| normal.getStandardDeviation() != param2) {
normal = new NormalDistribution(param, param2);
}
return normal;
}
/**
* @param param
* number of elements
* @param param2
* exponent
* @return Zipf distribution
*/
ZipfDistribution getZipfDistribution(int param, double param2) {
if (zipf == null || zipf.getNumberOfElements() != param
|| zipf.getExponent() != param2) {
zipf = new ZipfDistribution(param, param2);
}
return zipf;
}
}