aima.core.probability.full.FullJointDistributionModel Maven / Gradle / Ivy
package aima.core.probability.full;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import aima.core.probability.CategoricalDistribution;
import aima.core.probability.FiniteProbabilityModel;
import aima.core.probability.ProbabilityModel;
import aima.core.probability.RandomVariable;
import aima.core.probability.proposition.ConjunctiveProposition;
import aima.core.probability.proposition.Proposition;
import aima.core.probability.util.ProbUtil;
import aima.core.probability.util.ProbabilityTable;
/**
* An implementation of the FiniteProbabilityModel API using a full joint
* distribution as the underlying model.
*
* @author Ciaran O'Reilly
*/
public class FullJointDistributionModel implements FiniteProbabilityModel {
private ProbabilityTable distribution = null;
private Set representation = null;
public FullJointDistributionModel(double[] values, RandomVariable... vars) {
if (null == vars) {
throw new IllegalArgumentException(
"Random Variables describing the model's representation of the World need to be specified.");
}
distribution = new ProbabilityTable(values, vars);
representation = new LinkedHashSet();
for (int i = 0; i < vars.length; i++) {
representation.add(vars[i]);
}
representation = Collections.unmodifiableSet(representation);
}
//
// START-ProbabilityModel
public boolean isValid() {
// Handle rounding
return Math.abs(1 - distribution.getSum()) <= ProbabilityModel.DEFAULT_ROUNDING_THRESHOLD;
}
public double prior(Proposition... phi) {
return probabilityOf(ProbUtil.constructConjunction(phi));
}
public double posterior(Proposition phi, Proposition... evidence) {
Proposition conjEvidence = ProbUtil.constructConjunction(evidence);
// P(A | B) = P(A AND B)/P(B) - (13.3 AIMA3e)
Proposition aAndB = new ConjunctiveProposition(phi, conjEvidence);
double probabilityOfEvidence = prior(conjEvidence);
if (0 != probabilityOfEvidence) {
return prior(aAndB) / probabilityOfEvidence;
}
return 0;
}
public Set getRepresentation() {
return representation;
}
// END-ProbabilityModel
//
//
// START-FiniteProbabilityModel
public CategoricalDistribution priorDistribution(Proposition... phi) {
return jointDistribution(phi);
}
public CategoricalDistribution posteriorDistribution(Proposition phi,
Proposition... evidence) {
Proposition conjEvidence = ProbUtil.constructConjunction(evidence);
// P(A | B) = P(A AND B)/P(B) - (13.3 AIMA3e)
CategoricalDistribution dAandB = jointDistribution(phi, conjEvidence);
CategoricalDistribution dEvidence = jointDistribution(conjEvidence);
return dAandB.divideBy(dEvidence);
}
public CategoricalDistribution jointDistribution(
Proposition... propositions) {
ProbabilityTable d = null;
final Proposition conjProp = ProbUtil
.constructConjunction(propositions);
final LinkedHashSet vars = new LinkedHashSet(
conjProp.getUnboundScope());
if (vars.size() > 0) {
RandomVariable[] distVars = new RandomVariable[vars.size()];
vars.toArray(distVars);
final ProbabilityTable ud = new ProbabilityTable(distVars);
final Object[] values = new Object[vars.size()];
ProbabilityTable.Iterator di = new ProbabilityTable.Iterator() {
public void iterate(Map possibleWorld,
double probability) {
if (conjProp.holds(possibleWorld)) {
int i = 0;
for (RandomVariable rv : vars) {
values[i] = possibleWorld.get(rv);
i++;
}
int dIdx = ud.getIndex(values);
ud.setValue(dIdx, ud.getValues()[dIdx] + probability);
}
}
};
distribution.iterateOverTable(di);
d = ud;
} else {
// No Unbound Variables, therefore just return
// the singular probability related to the proposition.
d = new ProbabilityTable();
d.setValue(0, prior(propositions));
}
return d;
}
// END-FiniteProbabilityModel
//
//
// PRIVATE METHODS
//
private double probabilityOf(final Proposition phi) {
final double[] probSum = new double[1];
ProbabilityTable.Iterator di = new ProbabilityTable.Iterator() {
public void iterate(Map possibleWorld,
double probability) {
if (phi.holds(possibleWorld)) {
probSum[0] += probability;
}
}
};
distribution.iterateOverTable(di);
return probSum[0];
}
}