/// <summary> /// Tests EP and BP gate enter ops for Bernoulli random variable for correctness given message parameters. /// </summary> /// <param name="valueProbTrue">Probability of being true for the variable entering the gate.</param> /// <param name="enterOneProbTrue">Probability of being true for the variable approximation inside the gate when the selector is true.</param> /// <param name="selectorProbTrue">Probability of being true for the selector variable.</param> private void DoBernoulliEnterTest(double valueProbTrue, double enterOneProbTrue, double selectorProbTrue) { var value = new Bernoulli(valueProbTrue); var enterOne = new Bernoulli(enterOneProbTrue); var selector = new Bernoulli(selectorProbTrue); var selectorInverse = new Bernoulli(selector.GetProbFalse()); var discreteSelector = new Discrete(selector.GetProbTrue(), selector.GetProbFalse()); var discreteSelectorInverse = new Discrete(selector.GetProbFalse(), selector.GetProbTrue()); var cases = new[] { Bernoulli.FromLogOdds(selector.GetLogProbTrue()), Bernoulli.FromLogOdds(selector.GetLogProbFalse()) }; // Compute expected message double logShift = enterOne.GetLogNormalizer() + value.GetLogNormalizer() - (value * enterOne).GetLogNormalizer(); double expectedProbTrue = selector.GetProbFalse() + (selector.GetProbTrue() * enterOne.GetProbTrue() * Math.Exp(logShift)); double expectedProbFalse = selector.GetProbFalse() + (selector.GetProbTrue() * enterOne.GetProbFalse() * Math.Exp(logShift)); double expectedNormalizer = expectedProbTrue + expectedProbFalse; expectedProbTrue /= expectedNormalizer; Bernoulli value1, value2; // Enter partial (bernoulli selector, first case) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne }, selector, value, new[] { 0 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne }, selector, value, new[] { 0 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (bernoulli selector, second case) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne }, selectorInverse, value, new[] { 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne }, selectorInverse, value, new[] { 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (bernoulli selector, both cases) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, selector, value, new[] { 0, 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, selector, value, new[] { 0, 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (discrete selector, first case) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne }, discreteSelector, value, new[] { 0 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne }, discreteSelector, value, new[] { 0 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (discrete selector, second case) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne }, discreteSelectorInverse, value, new[] { 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne }, discreteSelectorInverse, value, new[] { 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial (discrete selector, both cases) value1 = GateEnterPartialOp <bool> .ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, discreteSelector, value, new[] { 0, 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, discreteSelector, value, new[] { 0, 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter one (discrete selector, first case) value1 = GateEnterOneOp <bool> .ValueAverageConditional( enterOne, discreteSelector, value, 0, new Bernoulli()); value2 = BeliefPropagationGateEnterOneOp.ValueAverageConditional( enterOne, discreteSelector, value, 0, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter one (discrete selector, second case) value1 = GateEnterOneOp <bool> .ValueAverageConditional( enterOne, discreteSelectorInverse, value, 1, new Bernoulli()); value2 = BeliefPropagationGateEnterOneOp.ValueAverageConditional( enterOne, discreteSelectorInverse, value, 1, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial two (first case) value1 = GateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne }, cases[0], cases[1], value, new[] { 0 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne }, cases[0], cases[1], value, new[] { 0 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial two (second case) value1 = GateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne }, cases[1], cases[0], value, new[] { 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne }, cases[1], cases[0], value, new[] { 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter partial two (both cases) value1 = GateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, cases[0], cases[1], value, new[] { 0, 1 }, new Bernoulli()); value2 = BeliefPropagationGateEnterPartialTwoOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, cases[0], cases[1], value, new[] { 0, 1 }, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); // Enter (discrete selector) value1 = GateEnterOp <bool> .ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, discreteSelector, value, new Bernoulli()); value2 = BeliefPropagationGateEnterOp.ValueAverageConditional( new[] { enterOne, Bernoulli.Uniform() }, discreteSelector, value, new Bernoulli()); Assert.Equal(expectedProbTrue, value1.GetProbTrue(), 1e-4); Assert.Equal(expectedProbTrue, value2.GetProbTrue(), 1e-4); }