// Mixture
package distributions;
public class MixtureDistribution extends Distribution{
Distribution[] dist;
int n, type;
double minValue, maxValue, lowerValue, upperValue, stepSize;
double[] prob;
//Constructors
public MixtureDistribution(Distribution[] d, double[] p){
setParameters(d, p);
}
public MixtureDistribution(Distribution d0, Distribution d1, double a){
setParameters(d0, d1, a);
}
public void setParameters(Distribution[] d, double[] p){
double minLower = Double.POSITIVE_INFINITY, maxUpper = Double.NEGATIVE_INFINITY, minWidth = Double.POSITIVE_INFINITY;
double a, b, w;
dist = d;
prob = p;
int t0 = dist[0].getType(), t;
n = dist.length;
boolean mixed = false;
for (int i = 0; i < n; i++){
t = dist[i].getType();
if (t == DISCRETE) a = dist[i].getDomain().getLowerValue(); else a = dist[i].getDomain().getLowerBound();
if (a < minLower) minLower = a;
if (t == DISCRETE) b = dist[i].getDomain().getUpperValue(); else b = dist[i].getDomain().getUpperBound();
if (b > maxUpper) maxUpper = b;
w = dist[i].getDomain().getWidth();
if (w < minWidth) minWidth = w;
if (t != t0) mixed = true;
}
if (mixed) t = 2; else t = t0;
super.setParameters(minLower, maxUpper, minWidth, t);
}
public void setParameters(Distribution d0, Distribution d1, double a){
setParameters(new Distribution[]{d0, d1}, new double[]{1 - a, a});
}
//Density
public double getDensity(double x){
double d = 0;
for (int i = 0; i < n; i++) d = d + prob[i] * dist[i].getDensity(x);
return d;
}
//Mean
public double getMean(){
double sum = 0;
for (int i = 0; i < n; i++) sum = sum + prob[i] * dist[i].getMean();
return sum;
}
//Variance
public double getVariance(){
double sum = 0, mu = getMean(), m;
for (int i = 0; i < n; i++){
m = dist[i].getMean();
sum = sum + prob[i] * (dist[i].getVariance() + m * m);
}
return sum - mu * mu;
}
//Simulate
public double simulate(){
double sum = 0, p = Math.random();
int i = -1;
while (sum < p & i < n){
sum = sum + prob[i];
i = i + 1;
}
return dist[i].simulate();
}
}