}
// Add the calculated marginal to the initial network (pn).
// We already know that every node here is discrete.
clonedPN.compile();
for (Node nodeToGetMarginal : clonedPN.getNodes()) {
TreeVariable variableToGetMarginal = (TreeVariable)nodeToGetMarginal;
TreeVariable variable = (TreeVariable)pn.getNode(nodeToGetMarginal.getName());
float[] values = new float[variable.getStatesSize()];
for (int stateIndex = 0; stateIndex < variable.getStatesSize(); stateIndex++) {
values[stateIndex] = variableToGetMarginal.getMarginalAt(stateIndex);
}
variable.initMarginalList();
variable.addLikeliHood(values);
// Add its name to the list of already visited nodes.
nodeVisitedBeforeMap.put(nodeToGetMarginal.getName(), true);
}
clonedPN = clonePN(this.pn);
}
}
// Now we have the posterior of all parents of the current continuous node.
// Calculate Weighted Gaussian Sum (from Symbolic Probabilistic Inference with both
// Discrete and Continuous Variables, appendix C)
// First lets calculate the mean SumOf(Prob[Parents(node)] * PartialMean), for every
// normal distribution function possible (combination of parents' states).
CNNormalDistribution cDistribution = ((ContinuousNode)node).getCnNormalDistribution();
double[] partialMeanList = new double[cDistribution.functionSize()];
double[] partialVarianceList = new double[cDistribution.functionSize()];
double[] probabilityList = new double[cDistribution.functionSize()];
double weightedMean = 0.0;
for (int ndfIndex = 0; ndfIndex < cDistribution.functionSize(); ndfIndex++) {
// Each normal distribution function has the mean SumOf(PartialMean), for every normal
// distribution in the function (one for each continuous parent and one for the noise
// normal distribution). As each continuous parent distribution is multiplied by a
// constant, its PartialMean = constant * MeanWithoutConstant.
// First we add the mean of the noise normal distribution.
partialMeanList[ndfIndex] = cDistribution.getMean(ndfIndex);
// Each normal distribution function has the variance SumOf(PartialVariance), for every normal
// distribution in the function (one for each continuous parent and one for the noise
// normal distribution). As each continuous parent distribution is multiplied by a
// constant, its PartialVariance = constant^2 * VarianceWithoutConstant.
// For the variance, we first add the variance of the noise normal distribution.
partialVarianceList[ndfIndex] = cDistribution.getVariance(ndfIndex);
// Then, for each continuous parent we add constant * MeanWithoutConstant for the PartialMean
// and constant^2 * VarianceWithoutConstant for the PartialVariance.
double meanWithoutConstant;
double varianceWithoutConstant;
for (int parentIndex = 0; parentIndex < cDistribution.getContinuousParentList().size(); parentIndex++) {
TreeVariable variable = (TreeVariable)cDistribution.getContinuousParentList().get(parentIndex);
// By the time we get here, the continuous parent already calculated its mean and variance previously.
meanWithoutConstant = variable.getMarginalAt(ContinuousNode.MEAN_MARGINAL_INDEX);
varianceWithoutConstant = variable.getMarginalAt(ContinuousNode.VARIANCE_MARGINAL_INDEX);
partialMeanList[ndfIndex] += cDistribution.getConstantAt(parentIndex, ndfIndex) * meanWithoutConstant;
partialVarianceList[ndfIndex] += Math.pow(cDistribution.getConstantAt(parentIndex, ndfIndex), 2) * varianceWithoutConstant;
}
// Now we get the configuration of its parents states to calculate its probability.