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<RandomVariable> 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<RandomVariable>(); 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<RandomVariable> 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<RandomVariable> vars = new LinkedHashSet<RandomVariable>( 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<RandomVariable, Object> 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<RandomVariable, Object> possibleWorld, double probability) { if (phi.holds(possibleWorld)) { probSum[0] += probability; } } }; distribution.iterateOverTable(di); return probSum[0]; } }