package org.eclipse.recommenders.jayes.transformation; import static org.junit.Assert.*; import java.util.Arrays; import org.eclipse.recommenders.jayes.BayesNet; import org.eclipse.recommenders.jayes.BayesNode; import org.eclipse.recommenders.jayes.inference.jtree.JunctionTreeAlgorithm; import org.eclipse.recommenders.jayes.transformation.util.ArrayFlatten; import org.eclipse.recommenders.jayes.transformation.util.DecompositionFailedException; import org.junit.Test; public class DecompositionTest { private static final double TOLERANCE = 0.0001; // Tests the "normal" case where no reordering has to take place to make the decomposition useful @Test public void testLDDNoReordering() throws DecompositionFailedException { BayesNet net = new BayesNet(); BayesNode a = net.createNode("A"); a.addOutcomes("true", "false"); a.setProbabilities(new double[] { 0.8, 0.2 }); BayesNode b = net.createNode("B"); b.setParents(Arrays.asList(a)); b.addOutcomes("a", "b"); b.setProbabilities(ArrayFlatten.flatten(new double[][] { { 0.25, 0.75 }, { 0.75, 0.25 } })); JunctionTreeAlgorithm algo = new JunctionTreeAlgorithm(); algo.setNetwork(net); algo.addEvidence(b, "b"); double[] beliefA = algo.getBeliefs(a); double[] beliefB = algo.getBeliefs(b); LatentDeterministicDecomposition ldd = new LatentDeterministicDecomposition(); ldd.decompose(net, b); algo = new JunctionTreeAlgorithm(); algo.setNetwork(net); algo.addEvidence(b, "b"); assertArrayEquals(beliefA, algo.getBeliefs(net.getNode("A")), TOLERANCE); assertArrayEquals(beliefB, algo.getBeliefs(net.getNode("B")), TOLERANCE); } @Test public void testLDD2() throws DecompositionFailedException { exerciseAndVerifyReordering(new LatentDeterministicDecomposition()); } // Test the case where the factor cannot be expressed perfectly as // combination of base vectors @Test public void testLDD3() throws DecompositionFailedException { BayesNet net = new BayesNet(); BayesNode a = net.createNode("A"); a.addOutcomes("true", "false"); a.setProbabilities(new double[] { 0.8, 0.2 }); BayesNode b = net.createNode("B"); b.setParents(Arrays.asList(a)); b.addOutcomes("a", "b", "c", "d", "e"); b.setProbabilities(ArrayFlatten.flatten(new double[][] { { 0.1, 0.05, 0.05, 0.4, 0.4 }, { 0.1, 0.4, 0.4, 0.05, 0.05 } })); JunctionTreeAlgorithm algo = new JunctionTreeAlgorithm(); algo.setNetwork(net); algo.addEvidence(b, "a"); double[] beliefA = algo.getBeliefs(a); double[] beliefB = algo.getBeliefs(b); LatentDeterministicDecomposition ldd = new LatentDeterministicDecomposition(); ldd.decompose(net, b); algo = new JunctionTreeAlgorithm(); algo.setNetwork(net); algo.addEvidence(b, "a"); assertArrayEquals(beliefA, algo.getBeliefs(net.getNode("A")), TOLERANCE); assertArrayEquals(beliefB, algo.getBeliefs(net.getNode("B")), TOLERANCE); } // tests a case where LDD will explicitly fail on node B @Test public void testLDD4() { BayesNet net = new BayesNet(); BayesNode a = net.createNode("A"); a.addOutcomes("true", "false"); a.setProbabilities(new double[] { 0.8, 0.2 }); BayesNode b = net.createNode("B"); b.setParents(Arrays.asList(a)); b.addOutcomes("a", "b", "c", "e", "f"); b.setProbabilities(ArrayFlatten.flatten(new double[][] { { 0.25, 0.75, 0.25, 0.75, 0 }, { 0.75, 0.25, 0.75, 0.25, 1 } })); JunctionTreeAlgorithm algo = new JunctionTreeAlgorithm(); algo.setNetwork(net); algo.addEvidence(b, "b"); double[] beliefA = algo.getBeliefs(a); double[] beliefB = algo.getBeliefs(b); LatentDeterministicDecomposition ldd = new LatentDeterministicDecomposition(); try { ldd.decompose(net, b); fail("Decomposition should have failed, but didn't"); } catch (DecompositionFailedException e) { } // just sanity check that nothing got screwed up algo = new JunctionTreeAlgorithm(); algo.setNetwork(net); algo.addEvidence(b, "b"); assertArrayEquals(beliefA, algo.getBeliefs(net.getNode("A")), TOLERANCE); assertArrayEquals(beliefB, algo.getBeliefs(net.getNode("B")), TOLERANCE); } @Test public void testSFD() throws DecompositionFailedException { exerciseAndVerifyReordering(new SmoothedFactorDecomposition()); } // Tests the case where the lowest dimension is the biggest, and the factor needs to be reordered private void exerciseAndVerifyReordering(IDecompositionStrategy decomposition) throws DecompositionFailedException { BayesNet net = new BayesNet(); BayesNode a = net.createNode("A"); a.addOutcomes("true", "false"); a.setProbabilities(new double[] { 0.8, 0.2 }); BayesNode b = net.createNode("B"); b.setParents(Arrays.asList(a)); b.addOutcomes("a", "b", "c", "d"); b.setProbabilities(ArrayFlatten.flatten(new double[][] { { 0.1, 0.3, 0.3, 0.1 }, { 0.1, 0.3, 0.3, 0.1 } })); JunctionTreeAlgorithm algo = new JunctionTreeAlgorithm(); algo.setNetwork(net); algo.addEvidence(b, "b"); double[] beliefA = algo.getBeliefs(a); double[] beliefB = algo.getBeliefs(b); decomposition.decompose(net, b); algo = new JunctionTreeAlgorithm(); algo.setNetwork(net); algo.addEvidence(b, "b"); assertArrayEquals(beliefA, algo.getBeliefs(net.getNode("A")), TOLERANCE); assertArrayEquals(beliefB, algo.getBeliefs(net.getNode("B")), TOLERANCE); } }