package bayesGame.bayesbayes; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import org.apache.commons.math3.fraction.Fraction; import org.apache.commons.math3.util.Pair; import org.junit.Test; public class BayesNodeTest { @Test public final void testBayesNodeObject() { BayesNode testNode = new BayesNode("Boo"); Object[] scope = testNode.scope; ArrayList<Fraction> fractions = new ArrayList<Fraction>(); assertEquals("The node's scope should contain exactly 1 variable", 1, scope.length); assertEquals("The node's potential should contain 2 items", 2, testNode.getPotential().length); Fraction fraction = Fraction.ZERO; fraction = fraction.add(testNode.getPotential()[0]); assertEquals("The probability of 'Boo' being untrue should be .5", fraction, Fraction.ONE_HALF); fraction = fraction.add(testNode.getPotential()[1]); assertEquals("The sum of node's potentials should equal 1", 1, fraction.doubleValue(), 0.001); } @Test public final void testObserveTrueMarginalProbability(){ String type = "Badger Badger Badger Mushroom Mushroom"; BayesNode testNode = new BayesNode(type); testNode.observe(true); assertEquals("If we've observed badger, we should get P = 1 for badger", Fraction.ONE, testNode.getProbability()); assertEquals("If we've observed badger, we should get P = 0 for !badger", Fraction.ZERO, testNode.getNormalizedMarginalPotential(type)[1]); } @Test public final void testObserveFalseMarginalProbability(){ String type = "Badger Badger Badger Mushroom Mushroom"; BayesNode testNode = new BayesNode(type); testNode.observe(false); assertEquals("If we've observed !badger, we should get P = 0 for badger", Fraction.ZERO, testNode.getProbability()); assertEquals("If we've observed !badger, we should get P = 1 for !badger", Fraction.ONE, testNode.getNormalizedMarginalPotential(type)[1]); } @Test public final void testObserveTrue(){ String type = "Badger Badger Badger Mushroom Mushroom"; BayesNode testNode = new BayesNode(type); testNode.observe(true); assertEquals("If we've observed badger, we should get P = .5 for unnormalized badger", Fraction.ONE_HALF, testNode.getMarginalPotential(type)[0]); assertEquals("If we've observed badger, we should get P = 0 for unnormalized !badger", Fraction.ZERO, testNode.getMarginalPotential(type)[1]); } @Test public final void testObserveReset(){ String type = "Badger Badger Badger Mushroom Mushroom"; BayesNode testNode = new BayesNode(type); testNode.observe(true); testNode.resetNode(); assertEquals("After resetting the node, we should get P = .5 for unnormalized badger", Fraction.ONE_HALF, testNode.getMarginalPotential(type)[0]); assertEquals("After resetting the node, we should get P = .5 for unnormalized !badger", Fraction.ONE_HALF, testNode.getMarginalPotential(type)[1]); } @Test public final void testObserveResetPotential(){ String type = "Badger Badger Badger Mushroom Mushroom"; BayesNode testNode = new BayesNode(type); testNode.observe(true); testNode.resetPotential(); assertEquals("After resetting the node, we should get P = .5 for unnormalized badger", Fraction.ONE_HALF, testNode.getMarginalPotential(type)[0]); assertEquals("After resetting the node, we should get P = 0 for unnormalized !badger", Fraction.ZERO, testNode.getMarginalPotential(type)[1]); } @Test public final void testSynthesizedScope(){ Object[] scope = {"Kind"}; BayesNode testNode = new BayesNode("Trustworthy", scope); scope = testNode.scope; assertEquals("The node's scope should contain exactly 2 variables", 2, scope.length); assertEquals("The node's potential should contain 4 items", 4, testNode.getPotential().length); scope = testNode.scope; assertTrue("The node's scope should contain 'Kind'", Arrays.asList(scope).contains("Kind")); assertTrue("The node's scope should contain 'Trustworthy'", Arrays.asList(scope).contains("Trustworthy")); } @Test public final void testPresetScope(){ Object[] scope = {"Kind", "Trustworthy"}; BayesNode testNode = new BayesNode("Trustworthy", scope); scope = testNode.scope; assertEquals("The node's scope should contain exactly 2 variables", 2, scope.length); assertEquals("The node's potential should contain 4 items", 4, testNode.getPotential().length); scope = testNode.scope; assertTrue("The node's scope should contain 'Kind'", Arrays.asList(scope).contains("Kind")); assertTrue("The node's scope should contain 'Trustworthy'", Arrays.asList(scope).contains("Trustworthy")); } @Test public final void testSPOUTVValidityChecks(){ Object[] scope = {"Rain"}; BayesNode rainNode = new BayesNode(scope[0]); assertTrue("Should be a valid input", rainNode.setProbabilityOfUntrueVariables(new Fraction(7, 10))); assertTrue("Should be a valid input", rainNode.setProbabilityOfUntrueVariables(new Fraction(3, 10), scope)); assertFalse("Probabilities above 1 should be rejected", rainNode.setProbabilityOfUntrueVariables(new Fraction(11, 10), scope)); assertFalse("Probabilities below 0 should be rejected", rainNode.setProbabilityOfUntrueVariables(Fraction.MINUS_ONE, scope)); assertFalse("Should be invalid input", rainNode.setProbabilityOfUntrueVariables(new Fraction(3, 10), "Mushroom")); } @Test public final void testPriorNodeMessageGeneration(){ Object[] scope = {"Rain"}; BayesNode rainNode = new BayesNode(scope[0]); rainNode.setProbabilityOfUntrueVariables(new Fraction(7, 10)); rainNode.setProbabilityOfUntrueVariables(new Fraction(3, 10), scope); rainNode.resetPotential(); Message m = rainNode.generateMessage(true, scope); assertArrayEquals("The scope of the message should match the specified scope", scope, m.scope); assertArrayEquals("The message should match the node's potential", rainNode.getPotential(), m.message); assertEquals("The sender should refer to the creator of the message", rainNode, m.sender); } @Test public final void testPriorMessageSending(){ Object[] scope = {"Rain"}; BayesNode rainNode = new BayesNode(scope[0]); rainNode.setProbabilityOfUntrueVariables(new Fraction(7, 10), new Object[0]); rainNode.setProbabilityOfUntrueVariables(new Fraction(3, 10), scope); Message message = rainNode.generateMessage(true, scope); Object[] mushroomScope = {"Mushroom", "Rain"}; BayesNode mushroomNode = new BayesNode("Rain", mushroomScope); mushroomNode.setProbabilityOfUntrueVariables(Fraction.FOUR_FIFTHS); mushroomNode.setProbabilityOfUntrueVariables(Fraction.ONE_FIFTH, "Mushroom"); mushroomNode.setProbabilityOfUntrueVariables(Fraction.TWO_FIFTHS, "Rain"); mushroomNode.setProbabilityOfUntrueVariables(Fraction.THREE_FIFTHS, "Rain", "Mushroom"); mushroomNode.resetPotential(); mushroomNode.receiveDownstreamMessage(message); Object[] mushroomMushroomScope = {"Mushroom"}; Message mushroomMessage = mushroomNode.generateMessage(false, mushroomMushroomScope); mushroomNode.multiplyPotentialWithMessages(); Fraction mushroomProbability = new Fraction(17, 25); Fraction mushroomNonProbability = new Fraction(8, 25); Fraction[] receivedProbability = mushroomNode.getNormalizedMarginalPotential("Mushroom"); assertEquals("Probability of Mushroom should be 17/25", mushroomProbability, receivedProbability[0]); assertEquals("Probability of !Mushroom should be 8/25", mushroomNonProbability, receivedProbability[1]); assertEquals("Probability of Mushroom in message should equal marginalized probability", mushroomMessage.message[0], receivedProbability[0]); assertEquals("Probability of !Mushroom in message should equal marginalized probability", mushroomMessage.message[1], receivedProbability[1]); } @Test public final void testNetworkMessagePassing(){ // set up rain node BayesNode rainNode = new BayesNode("Rain"); rainNode.setProbabilityOfUntrueVariables(new Fraction(7, 10)); rainNode.setProbabilityOfUntrueVariables(new Fraction(3, 10), "Rain"); // set up mushroom node Object[] mushroomScope = {"Mushroom", "Rain"}; BayesNode mushroomNode = new BayesNode("Rain", mushroomScope); mushroomNode.setProbabilityOfUntrueVariables(Fraction.FOUR_FIFTHS); mushroomNode.setProbabilityOfUntrueVariables(Fraction.ONE_FIFTH, "Mushroom"); mushroomNode.setProbabilityOfUntrueVariables(Fraction.TWO_FIFTHS, "Rain"); mushroomNode.setProbabilityOfUntrueVariables(Fraction.THREE_FIFTHS, "Rain", "Mushroom"); // set up snake node Object[] snakeScope = {"Snake", "Mushroom"}; BayesNode snakeNode = new BayesNode("Snake", snakeScope); snakeNode.setProbabilityOfUntrueVariables(new Fraction(3, 10)); snakeNode.setProbabilityOfUntrueVariables(new Fraction(4, 5), "Mushroom"); snakeNode.setProbabilityOfUntrueVariables(new Fraction(7, 10), "Snake"); snakeNode.setProbabilityOfUntrueVariables(new Fraction(1, 5), "Snake", "Mushroom"); snakeNode.observe(true); // do message passing Message rainMessage = rainNode.generateDownstreamMessage("Rain"); mushroomNode.receiveDownstreamMessage(rainMessage); Message mushroomMessage = mushroomNode.generateDownstreamMessage("Mushroom"); snakeNode.receiveDownstreamMessage(mushroomMessage); Message snakeUpMessage = snakeNode.generateUpstreamMessage("Mushroom"); mushroomNode.receiveUpstreamMessage(snakeUpMessage); Message mushroomUpMessage = mushroomNode.generateUpstreamMessage("Rain"); rainNode.receiveUpstreamMessage(mushroomUpMessage); // calculate outcomes rainNode.multiplyPotentialWithMessages(); mushroomNode.multiplyPotentialWithMessages(); snakeNode.multiplyPotentialWithMessages(); // get and verify probabilities Fraction[] probabilityOfRain = rainNode.getNormalizedMarginalPotential("Rain"); Fraction[] probabilityOfMushroom = mushroomNode.getNormalizedMarginalPotential("Mushroom"); Fraction[] probabilityOfSnake = snakeNode.getNormalizedMarginalPotential("Snake"); assertEquals("Probability of rain should be 60,87%", 0.6087d, probabilityOfRain[0].doubleValue(), 0.01); assertEquals("Probability of mushroom should be 44,35%", 0.4435d, probabilityOfMushroom[0].doubleValue(), 0.01); assertEquals("Probability of snake should be 100,0%", 1.00d, probabilityOfSnake[0].doubleValue(), 0.01); } @Test public void testAssumedValue(){ String type = "Badger Badger Badger Mushroom Mushroom"; BayesNode testNode = new BayesNode(type); testNode.assumeValue(true); assertEquals("If we've assumed badger, we should get P = 1 for badger", Fraction.ONE, testNode.getProbability()); assertEquals("If we've asumed badger, we should get P = 0 for !badger", Fraction.ZERO, testNode.getNormalizedMarginalPotential(type)[1]); } @Test public void testObserveOverridesAssumed(){ String type = "Badger Badger Badger Mushroom Mushroom"; BayesNode testNode = new BayesNode(type); testNode.assumeValue(true); testNode.observe(false); assertEquals("If we've first assumed badger and then observed non-badger, we should get P = 0 for badger", Fraction.ZERO, testNode.getProbability()); assertEquals("If we've first assumed badger and then observed non-badger, we should get P = 1 for !badger", Fraction.ONE, testNode.getNormalizedMarginalPotential(type)[1]); } @Test public void testAssumeDoesNotAffectObserved(){ String type = "Badger Badger Badger Mushroom Mushroom"; BayesNode testNode = new BayesNode(type); testNode.observe(false); testNode.assumeValue(true); assertEquals("If we've first observed non-badger and then assumed badger, we should get P = 0 for badger", Fraction.ZERO, testNode.getProbability()); assertEquals("If we've first observed non-badger and then assumed badger, we should get P = 1 for !badger", Fraction.ONE, testNode.getNormalizedMarginalPotential(type)[1]); } }