ValidationUtils.guardGreaterOrEqualDouble(minMax.getMin(), -1000000,
"observation interval is out of range for calcualtion");
ValidationUtils.guardGreaterOrEqualDouble(1000000, minMax.getMax(),
"observation interval is out of range for calcualtion");
NormalDistributionMixture res = initializeOneCompoenent(observations);
invokeStepListener(res);
double resL = Double.NEGATIVE_INFINITY;
double newL = countLnL(observations, res);
int iteration = 0;
while (newL - resL > 0.01 && res.getNumComponents() < maxComponents && iteration < 100) {
++iteration;
resL = newL;
// find the maximum weight
double splitValue = 0;
int splitIdx = 0;
for (int i = 0; i < res.getNumComponents(); ++i) {
if (res.getWeights().get(i) * res.getComponents().get(i).getSigma() > splitValue) {
splitValue = res.getWeights().get(i) * res.getComponents().get(i).getSigma();
splitIdx = i;
}
}
// split the component with highest weight
NormalDistributionMixture.Builder builder = new NormalDistributionMixture.Builder();
for (int i = 0; i < res.getNumComponents(); ++i) {
if (i == splitIdx) {
NormalDistribution comp = res.getComponents().get(i);
builder.addComponent(res.getWeights().get(i) / 2, comp.getMi() + comp.getSigma() / 2, comp.getSigma());
builder.addComponent(res.getWeights().get(i) / 2, comp.getMi() - comp.getSigma() / 2, comp.getSigma());
}
else {
if (res.getWeights().get(i) >= minWeight) {
builder.addComponent(res.getWeights().get(i), res.getComponents().get(i));
}
}
}
NormalDistributionMixture newMixture = builder.build();
// iterations for the new mixture
double help = Double.NEGATIVE_INFINITY;
int emiteration = 0;
while (emiteration < 5 || newL - help > 0.01) {
++emiteration;
help = newL;
newMixture = nextIteration(observations, newMixture);
newL = countLnL(observations, newMixture);
if (getMinWeigth(newMixture) < minWeight) {
newMixture = newMixture.createSignificantComponentMixture(minWeight);
newL = countLnL(observations, newMixture);
}
// assign new L value if possible
if (newL > resL) {
res = newMixture;