/*******************************************************************************
* Copyright 2014 Felipe Takiyama
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package br.usp.poli.takiyama.acfove;
import static org.hamcrest.collection.IsIn.isIn;
import static org.junit.Assert.assertEquals;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import br.usp.poli.takiyama.acfove.AggParfactor.AggParfactorBuilder;
import br.usp.poli.takiyama.cfove.StdParfactor.StdParfactorBuilder;
import br.usp.poli.takiyama.common.Constraint;
import br.usp.poli.takiyama.common.InequalityConstraint;
import br.usp.poli.takiyama.common.Marginal;
import br.usp.poli.takiyama.common.Parfactor;
import br.usp.poli.takiyama.common.StdMarginal.StdMarginalBuilder;
import br.usp.poli.takiyama.prv.And;
import br.usp.poli.takiyama.prv.Constant;
import br.usp.poli.takiyama.prv.CountingFormula;
import br.usp.poli.takiyama.prv.LogicalVariable;
import br.usp.poli.takiyama.prv.Or;
import br.usp.poli.takiyama.prv.Prv;
import br.usp.poli.takiyama.prv.RandomVariableSet;
import br.usp.poli.takiyama.prv.StdLogicalVariable;
import br.usp.poli.takiyama.prv.StdPrv;
import br.usp.poli.takiyama.utils.Sets;
import br.usp.poli.takiyama.utils.TestUtils;
@RunWith(Enclosed.class)
public class MacroOperationTest {
public static class UnificationBetweenStandardParfactors {
@Ignore("Recalculate expected result")
@Test
public void test() {
LogicalVariable x = StdLogicalVariable.getInstance("X", "x", 5);
LogicalVariable y = StdLogicalVariable.getInstance("Y", "y", 6);
LogicalVariable z = StdLogicalVariable.getInstance("Z", "y", 6);
Constant x1 = Constant.getInstance("x1");
Constant x2 = Constant.getInstance("x2");
Constant y1 = Constant.getInstance("y1");
Prv f_x_y = StdPrv.getBooleanInstance("f", x, y);
Prv f_x_z = StdPrv.getBooleanInstance("f", x, z);
Prv f_x1_y = StdPrv.getBooleanInstance("f", x1, y);
Prv f_x1_z = StdPrv.getBooleanInstance("f", x1, z);
Prv f_x1_y1 = StdPrv.getBooleanInstance("f", x1, y1);
Prv q_y = StdPrv.getBooleanInstance("q", y);
Prv q_y1 = StdPrv.getBooleanInstance("q", y1);
Prv q_z = StdPrv.getBooleanInstance("q", z);
Prv p_x = StdPrv.getBooleanInstance("p", x);
Constraint x_x1 = InequalityConstraint.getInstance(x, x1);
Constraint x_x2 = InequalityConstraint.getInstance(x, x2);
Constraint y_y1 = InequalityConstraint.getInstance(y, y1);
Constraint z_y1 = InequalityConstraint.getInstance(z, y1);
double [] vals = {0.2, 0.3, 0.5, 0.7};
Parfactor g1 = new StdParfactorBuilder().variables(f_x_y, q_y).constraints(x_x2).values(vals).build();
Parfactor g2 = new StdParfactorBuilder().variables(p_x, f_x1_z).constraints(x_x1, z_y1).values(vals).build();
// Parfactor g3 = new StdParfactorBuilder().variables(p_x, f_x1_z).constraints(x_x1, z_y1).values(vals).build();
// Parfactor g4 = new StdParfactorBuilder().variables(f_x_z, q_z).constraints(x_x1, x_x2).values(vals).build();
// Parfactor g5 = new StdParfactorBuilder().variables(f_x1_y1, q_y1).values(vals).build();
// Parfactor g6 = new StdParfactorBuilder().variables(f_x1_z, q_z).constraints(z_y1).values(vals).build();
Parfactor g3 = new StdParfactorBuilder().variables(p_x, f_x1_y).constraints(x_x1, y_y1).values(vals).build();
Parfactor g4 = new StdParfactorBuilder().variables(f_x_y, q_y).constraints(x_x1, x_x2).values(vals).build();
Parfactor g5 = new StdParfactorBuilder().variables(f_x1_y1, q_y1).values(vals).build();
Parfactor g6 = new StdParfactorBuilder().variables(f_x1_y, q_y).constraints(y_y1).values(vals).build();
Marginal input = new StdMarginalBuilder(2).parfactors(g1, g2).build();
MacroOperation shatter = new Shatter(input);
Marginal result = shatter.run();
Marginal expected = new StdMarginalBuilder(4).parfactors(g3, g4, g5, g6).build();
assertEquals(expected, result);
}
/**
* Creates data structures to test unification between two counting
* formulas.
* <br>
* The input is
* <br>
* Φ<sub>0</sub> = {<br>
* < { }, { #<sub>A:{A ≠ x1}</sub>[f(A)], h(A) }, F1 >, [1] <br>
* < { }, { #<sub>A:{A ≠ x2}</sub>[f(A)] }, F2 > } [2] <br>
* <br>
* Where D(A) = {x1,x2,x3}.
* The result is
* <br>
* Φ<sub>1</sub> = {<br>
* < { }, { f(x0), f(x1) }, F2' >, [3] <br>
* < { A ≠ x2 }, { f(x0), f(x2), h(A) }, F1' > [4] <br>
* < { }, { f(x0), f(x2), h(x2) }, F1' > } [5] <br>
*
*/
@Test
public void testUnificationWithTwoCountingFormulas() {
LogicalVariable a = StdLogicalVariable.getInstance("A", "x", 3);
Constant x1 = Constant.getInstance("x1");
Constant x2 = Constant.getInstance("x2");
Constant x3 = Constant.getInstance("x3");
Constraint a_x2 = InequalityConstraint.getInstance(a, x2);
Constraint a_x3 = InequalityConstraint.getInstance(a, x3);
Prv f = StdPrv.getBooleanInstance("f", a);
Prv f_x1 = StdPrv.getBooleanInstance("f", x1);
Prv f_x2 = StdPrv.getBooleanInstance("f", x2);
Prv f_x3 = StdPrv.getBooleanInstance("f", x3);
Prv h = StdPrv.getBooleanInstance("h", a);
Prv h_x3 = StdPrv.getBooleanInstance("h", x3);
Prv cf1 = CountingFormula.getInstance(a, f, a_x2);
Prv cf2 = CountingFormula.getInstance(a, f, a_x3);
double [] f1 = {2, 3, 5, 7, 11, 13};
double [] f3 = {2, 3, 5, 7, 5, 7, 11, 13};
Parfactor g1 = new StdParfactorBuilder().variables(cf1, h).values(f1).build();
Parfactor g2 = new StdParfactorBuilder().variables(cf2).values(2, 3, 5).build();
Parfactor g3 = new StdParfactorBuilder().variables(f_x1, f_x2).values(2, 3, 3, 5).build();
Parfactor g4 = new StdParfactorBuilder().variables(f_x1, f_x3, h).values(f3).constraints(a_x3).build();
Parfactor g5 = new StdParfactorBuilder().variables(f_x1, f_x3, h_x3).values(f3).build();
Marginal input = new StdMarginalBuilder(2).parfactors(g1, g2).build();
MacroOperation shatter = new Shatter(input);
Marginal result = shatter.run();
Marginal expected = new StdMarginalBuilder(3).parfactors(g3, g4, g5).build();
assertEquals(expected, result);
}
/**
* Creates data structures to test unification between two counting
* formulas in a bigger population.
* <br>
* The input is
* <br>
* Φ<sub>0</sub> = {<br>
* < { }, { #<sub>A:{A ≠ x1}</sub>[f(A)], h(A) }, F1 >, [1] <br>
* < { }, { #<sub>A:{A ≠ x2}</sub>[f(A)] }, F2 > } [2] <br>
* <br>
* Where D(A) = {x1,x2,x3,x4}.
* The result is
* <br>
* Φ<sub>1</sub> = {<br>
* < { }, { #<sub>A:{A ≠ x1, A ≠ x2}</sub>[f(A)], f(x1) }, F2' >, [3] <br>
* < { A ≠ x2 }, { #<sub>A:{A ≠ x1, A ≠ x2}</sub>[f(A)], f(x2), h(A) }, F1' > [4] <br>
* < { }, { #<sub>A:{A ≠ x1, A ≠ x2}</sub>[f(A)], f(x2), h(x2) }, F1' > } [5] <br>
*/
@Test
public void testUnificationWithTwoCountingFormulasAndBiggerPopulation() {
LogicalVariable a = StdLogicalVariable.getInstance("A", "x", 4);
Constant x1 = Constant.getInstance("x1");
Constant x2 = Constant.getInstance("x2");
Constraint a_x1 = InequalityConstraint.getInstance(a, x1);
Constraint a_x2 = InequalityConstraint.getInstance(a, x2);
Set<Constraint> a_x1_a_x2 = Sets.setOf(a_x1, a_x2);
Prv f = StdPrv.getBooleanInstance("f", a);
Prv f_x1 = StdPrv.getBooleanInstance("f", x1);
Prv f_x2 = StdPrv.getBooleanInstance("f", x2);
Prv h = StdPrv.getBooleanInstance("h", a);
Prv h_x2 = StdPrv.getBooleanInstance("h", x2);
Prv cf1 = CountingFormula.getInstance(a, f, a_x1);
Prv cf2 = CountingFormula.getInstance(a, f, a_x2);
Prv cf3 = CountingFormula.getInstance(a, f, a_x1_a_x2);
double [] f1 = {2, 3, 5, 7, 11, 13, 17, 23};
double [] f2 = {2, 3, 5, 7};
double [] f3 = {2, 3, 3, 5, 5, 7};
double [] f4 = {2, 3, 5, 7, 5, 7, 11, 13, 11, 13, 17, 23};
Parfactor g1 = new StdParfactorBuilder().variables(cf1, h).values(f1).build();
Parfactor g2 = new StdParfactorBuilder().variables(cf2).values(f2).build();
Parfactor g3 = new StdParfactorBuilder().variables(cf3, f_x1).values(f3).build();
Parfactor g4 = new StdParfactorBuilder().variables(cf3, f_x2, h).values(f4).constraints(a_x2).build();
Parfactor g5 = new StdParfactorBuilder().variables(cf3, f_x2, h_x2).values(f4).build();
Marginal input = new StdMarginalBuilder(2).parfactors(g1, g2).build();
MacroOperation shatter = new Shatter(input);
Marginal result = shatter.run();
Marginal expected = new StdMarginalBuilder(3).parfactors(g3, g4, g5).build();
assertEquals(expected, result);
}
/**
* Creates data structures to test unification between a counting formula
* and a standard parameterized random variable.
* <br>
* The input is
* <br>
* Φ<sub>0</sub> = {<br>
* < { }, { #<sub>A:{A ≠ x1}</sub>[f(A)], h(A) }, F1 >, [1] <br>
* < { }, { f(A) }, F2 > } [2] <br>
* <br>
* The result is
* <br>
* Φ<sub>1</sub> = {<br>
* < { }, { #<sub>X2:{X2 ≠ x1}</sub>[f(X2)], h(X2) }, F1 >, [3] <br>
* < { }, { f(x1) }, F2 >, [4] <br>
* < { X2 ≠ x1 }, { f(X2) }, F2 > } [5] <br>
*
*/
@Test
public void testUnificationTestWithCountingFormulaAndPrv() {
LogicalVariable a = StdLogicalVariable.getInstance("A", "x", 3);
Constant x1 = Constant.getInstance("x1");
Constraint a_x1 = InequalityConstraint.getInstance(a, x1);
Prv f = StdPrv.getBooleanInstance("f", a);
Prv f_x1 = StdPrv.getBooleanInstance("f", x1);
Prv h = StdPrv.getBooleanInstance("h", a);
Prv cf1 = CountingFormula.getInstance(a, f, a_x1);
double [] f1 = {2, 3, 5, 7, 11, 13};
double [] f2 = {2, 3};
Parfactor g1 = new StdParfactorBuilder().variables(cf1, h).values(f1).build();
Parfactor g2 = new StdParfactorBuilder().variables(f).values(f2).build();
Parfactor g3 = new StdParfactorBuilder().variables(cf1, h).values(f1).build();
Parfactor g4 = new StdParfactorBuilder().variables(f_x1).values(f2).build();
Parfactor g5 = new StdParfactorBuilder().variables(f).values(f2).constraints(a_x1).build();
Marginal input = new StdMarginalBuilder(2).parfactors(g1, g2).build();
MacroOperation shatter = new Shatter(input);
Marginal result = shatter.run();
Marginal expected = new StdMarginalBuilder(3).parfactors(g3, g4, g5).build();
assertEquals(expected, result);
}
}
/**
* Tests unification/shattering between aggregation parfactors and
* standard parfactors.
*/
@RunWith(Parameterized.class)
public static class UnificationTest {
@Parameters
public static Collection<Object[]> data() {
LogicalVariable a = StdLogicalVariable.getInstance("A", "x", 10);
LogicalVariable b = StdLogicalVariable.getInstance("B", "x", 10);
LogicalVariable e = StdLogicalVariable.getInstance("E", "x", 10);
LogicalVariable f = StdLogicalVariable.getInstance("F", "x", 10);
Constant x1 = Constant.getInstance("x1");
Constant x2 = Constant.getInstance("x2");
Constant x3 = Constant.getInstance("x3");
Constant x4 = Constant.getInstance("x4");
Prv p_a_b = StdPrv.getBooleanInstance("p", a, b);
Prv c_b = StdPrv.getBooleanInstance("c", b);
Prv cPrime = StdPrv.getBooleanInstance("c'", b);
Prv u = StdPrv.getBooleanInstance("u");
Prv v_f = StdPrv.getBooleanInstance("v", f);
Prv w_b = StdPrv.getBooleanInstance("w", b);
Prv p_a_x1 = StdPrv.getBooleanInstance("p", a, x1);
Prv p_a_x3 = StdPrv.getBooleanInstance("p", a, x3);
Prv p_a_e = StdPrv.getBooleanInstance("p", a, e);
Prv p_x1_x2 = StdPrv.getBooleanInstance("p", x1, x2);
Prv p_x1_x3 = StdPrv.getBooleanInstance("p", x1, x3);
Prv p_x1_e = StdPrv.getBooleanInstance("p", x1, e);
Prv p_x1_b = StdPrv.getBooleanInstance("p", x1, b);
Prv p_x2_x1 = StdPrv.getBooleanInstance("p", x2, x1);
Prv p_x4_x1 = StdPrv.getBooleanInstance("p", x4, x1);
Prv p_f_e = StdPrv.getBooleanInstance("p", f, e);
Prv c_x1 = StdPrv.getBooleanInstance("c", x1);
Prv c_x3 = StdPrv.getBooleanInstance("c", x3);
Prv c_e = StdPrv.getBooleanInstance("c", e);
Prv cPrime_x1 = StdPrv.getBooleanInstance("c'", x1);
Prv cPrime_x3 = StdPrv.getBooleanInstance("c'", x3);
Prv cPrime_e = StdPrv.getBooleanInstance("c'", e);
Constraint a_x1 = InequalityConstraint.getInstance(a, x1);
Constraint a_x2 = InequalityConstraint.getInstance(a, x2);
Constraint a_x4 = InequalityConstraint.getInstance(a, x4);
Constraint b_x1 = InequalityConstraint.getInstance(b, x1);
Constraint b_x2 = InequalityConstraint.getInstance(b, x2);
Constraint b_x3 = InequalityConstraint.getInstance(b, x3);
Constraint e_x1 = InequalityConstraint.getInstance(e, x1);
Constraint e_x2 = InequalityConstraint.getInstance(e, x2);
Constraint e_x3 = InequalityConstraint.getInstance(e, x3);
Constraint f_x3 = InequalityConstraint.getInstance(f, x3);
Parfactor g_1_in_1 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).build();
Parfactor g_1_in_2 = new StdParfactorBuilder().variables(p_a_x1).build();
Parfactor g_1_out_1 = new AggParfactorBuilder(p_a_x1, c_x1, Or.OR).build();
Parfactor g_1_out_2 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).constraint(b_x1).build();
Parfactor g_1_out_3 = new StdParfactorBuilder().variables(p_a_x1).build();
Marginal in1 = new StdMarginalBuilder().parfactors(g_1_in_1, g_1_in_2).build();
Marginal out1 = new StdMarginalBuilder().parfactors(g_1_out_1, g_1_out_2, g_1_out_3).build();
Parfactor g_2_in_1 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).build();
Parfactor g_2_in_2 = new StdParfactorBuilder().variables(p_x1_e).build();
Parfactor g_2_out_1 = new AggParfactorBuilder(p_a_e, cPrime_e, Or.OR).constraint(a_x1).build();
Parfactor g_2_out_2 = new StdParfactorBuilder().variables(p_x1_e, cPrime_e, c_e).values(new double[] {1, 0, 0, 1, 0, 1, 0, 1}).build();
Parfactor g_2_out_3 = new StdParfactorBuilder().variables(p_x1_e).build();
Parfactor g_2_out_4 = new AggParfactorBuilder(p_a_b, cPrime, Or.OR).constraint(a_x1).build();
Parfactor g_2_out_5 = new StdParfactorBuilder().variables(p_x1_b, cPrime, c_b).values(new double[] {1, 0, 0, 1, 0, 1, 0, 1}).build();
Parfactor g_2_out_6 = new StdParfactorBuilder().variables(p_x1_b).build();
Marginal in2 = new StdMarginalBuilder().parfactors(g_2_in_1, g_2_in_2).build();
Marginal out2_1 = new StdMarginalBuilder().parfactors(g_2_out_1, g_2_out_2, g_2_out_3).build();
Marginal out2_2 = new StdMarginalBuilder().parfactors(g_2_out_4, g_2_out_5, g_2_out_6).build();
Parfactor g_3_in_1 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).constraints(b_x2, a_x4).build();
Parfactor g_3_in_2 = new StdParfactorBuilder().variables(p_x1_e).constraints(e_x3).build();
Marginal in3 = new StdMarginalBuilder().parfactors(g_3_in_1, g_3_in_2).build();
Set<Parfactor> out = new HashSet<Parfactor>();
out.add(new AggParfactorBuilder(p_a_b, cPrime, Or.OR).constraints(b_x2, b_x3, a_x1, a_x4).build());
out.add(new AggParfactorBuilder(p_a_x3, cPrime_x3, Or.OR).constraints(a_x1, a_x4).build());
out.add(new StdParfactorBuilder().variables(p_x1_x3, cPrime_x3, c_x3).values(new double[] {1, 0, 0, 1, 0, 1, 0, 1}).build());
out.add(new StdParfactorBuilder().variables(p_x1_b, cPrime, c_b).constraints(b_x2, b_x3).values(new double[] {1, 0, 0, 1, 0, 1, 0, 1}).build());
out.add(new StdParfactorBuilder().variables(p_x1_x2).build());
out.add(new StdParfactorBuilder().variables(p_x1_b).constraints(b_x3, b_x2).build());
Marginal out3_1 = new StdMarginalBuilder().parfactors(out).build();
out.clear();
out.add(new AggParfactorBuilder(p_a_e, cPrime_e, Or.OR).constraints(e_x2, e_x3, a_x1, a_x4).build());
out.add(new AggParfactorBuilder(p_a_x3, cPrime_x3, Or.OR).constraints(a_x1, a_x4).build());
out.add(new StdParfactorBuilder().variables(p_x1_x3, cPrime_x3, c_x3).values(new double[] {1, 0, 0, 1, 0, 1, 0, 1}).build());
out.add(new StdParfactorBuilder().variables(p_x1_e, cPrime_e, c_e).constraints(e_x2, e_x3).values(new double[] {1, 0, 0, 1, 0, 1, 0, 1}).build());
out.add(new StdParfactorBuilder().variables(p_x1_x2).build());
out.add(new StdParfactorBuilder().variables(p_x1_e).constraints(e_x3, e_x2).build());
Marginal out3_2 = new StdMarginalBuilder().parfactors(out).build();
Parfactor g_4_in_1 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).build();
Parfactor g_4_in_2 = new AggParfactorBuilder(p_f_e, c_e, Or.OR).build();
// expected result is g1,g2 or g3,g4 where:
// - g.4.out.1 == g.4.out.2
// - g.4.out.3 == g.4.out.4
Parfactor g_4_out_1 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).build();
Parfactor g_4_out_2 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).build();
Parfactor g_4_out_3 = new AggParfactorBuilder(p_f_e, c_e, Or.OR).build();
Parfactor g_4_out_4 = new AggParfactorBuilder(p_f_e, c_e, Or.OR).build();
Marginal in4 = new StdMarginalBuilder().parfactors(g_4_in_1, g_4_in_2).build();
Marginal out4_1 = new StdMarginalBuilder().parfactors(g_4_out_1, g_4_out_2).build();
Marginal out4_2 = new StdMarginalBuilder().parfactors(g_4_out_3, g_4_out_4).build();
Parfactor g_5_in_1 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).context(u).build();
Parfactor g_5_in_2 = new AggParfactorBuilder(p_f_e, c_e, Or.OR).build();
// expected result is g1,g2 or g3,g4
Parfactor g_5_out_1 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).context(u).build();
Parfactor g_5_out_2 = new AggParfactorBuilder(p_a_b, c_b, Or.OR).build();
Parfactor g_5_out_3 = new AggParfactorBuilder(p_f_e, c_e, Or.OR).context(u).build();
Parfactor g_5_out_4 = new AggParfactorBuilder(p_f_e, c_e, Or.OR).build();
Marginal in5 = new StdMarginalBuilder().parfactors(g_5_in_1, g_5_in_2).build();
Marginal out5_1 = new StdMarginalBuilder().parfactors(g_5_out_1, g_5_out_2).build();
Marginal out5_2 = new StdMarginalBuilder().parfactors(g_5_out_3, g_5_out_4).build();
Parfactor g_6_in_1 = new AggParfactorBuilder(p_a_x1, c_x1, Or.OR).context(u).build();
Parfactor g_6_in_2 = new AggParfactorBuilder(p_a_e, c_e, Or.OR).context(v_f).build();
Parfactor g_6_out_1 = new AggParfactorBuilder(p_a_x1, c_x1, Or.OR).context(u).build();
Parfactor g_6_out_2 = new AggParfactorBuilder(p_a_x1, c_x1, Or.OR).context(v_f).build();
Parfactor g_6_out_3 = new AggParfactorBuilder(p_a_e, c_e, Or.OR).context(v_f).constraint(e_x1).build();
Marginal in6 = new StdMarginalBuilder().parfactors(g_6_in_1, g_6_in_2).build();
Marginal out6 = new StdMarginalBuilder().parfactors(g_6_out_1, g_6_out_2, g_6_out_3).build();
Parfactor g_7_in_1 = new AggParfactorBuilder(p_a_x1, c_x1, Or.OR).context(w_b).constraints(b_x1, a_x2).build();
Parfactor g_7_in_2 = new AggParfactorBuilder(p_a_e, c_e, Or.OR).context(v_f).constraints(f_x3, a_x4).build();
Parfactor g_7_out_1 = new AggParfactorBuilder(p_a_x1, cPrime_x1, Or.OR).context(v_f).constraints(f_x3, a_x2, a_x4).build();
Parfactor g_7_out_2 = new StdParfactorBuilder().variables(p_x2_x1, v_f, cPrime_x1, c_x1).constraints(f_x3).values(new double[] {1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}).build();
Parfactor g_7_out_3 = new AggParfactorBuilder(p_a_x1, cPrime_x1, Or.OR).context(w_b).constraints(b_x1, a_x2, a_x4).build();
Parfactor g_7_out_4 = new StdParfactorBuilder().variables(p_x4_x1, w_b, cPrime_x1, c_x1).constraints(b_x1).values(new double[] {1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}).build();
Parfactor g_7_out_5 = new AggParfactorBuilder(p_a_e, c_e, Or.OR).context(v_f).constraints(f_x3, a_x4, e_x1).build();
Marginal in7 = new StdMarginalBuilder().parfactors(g_7_in_1, g_7_in_2).build();
Marginal out7 = new StdMarginalBuilder().parfactors(g_7_out_1, g_7_out_2, g_7_out_3, g_7_out_4, g_7_out_5).build();
return Arrays.asList(new Object[][] {
{in1, new Object[] {out1}},
{in2, new Object[] {out2_1, out2_2}},
{in3, new Object[] {out3_1, out3_2}},
{in4, new Object[] {out4_1, out4_2}},
{in5, new Object[] {out5_1, out5_2}},
{in6, new Object[] {out6}},
{in7, new Object[] {out7}},
});
}
private Marginal input;
private List<Object> expected;
public UnificationTest(Marginal in, Object ... out) {
input = in;
expected = Arrays.asList(out);
}
@Test
public void testUnification() {
MacroOperation shatter = new Shatter(input);
Marginal result = shatter.run();
org.junit.Assert.assertThat(result, isIn(expected));
}
}
/**
* Example 2.19 to 2.22 from Kisynki[2010] - unification of standard
* parfactors.
*/
public static class ShatterTest {
@Test
public void testShatter() {
LogicalVariable lot = StdLogicalVariable.getInstance("Lot", "lot", 15);
Constant lot1 = Constant.getInstance("lot1");
Prv rain = StdPrv.getBooleanInstance("rain");
Prv sprinkler = StdPrv.getBooleanInstance("sprinkler", lot);
Prv wet_grass = StdPrv.getBooleanInstance("wet_grass", lot);
Prv wet_grass_lot1 = StdPrv.getBooleanInstance("wet_grass", lot1);
Prv sprinkler_lot1 = StdPrv.getBooleanInstance("sprinkler", lot1);
Constraint lot_lot1 = InequalityConstraint.getInstance(lot, lot1);
double [] f1 = {0.8, 0.2};
double [] f2 = {0.6, 0.4};
double [] f3 = {1.0, 0.0, 0.2, 0.8, 0.1, 0.9, 0.01, 0.99};
double [] f4 = {0, 1};
Parfactor g1 = new StdParfactorBuilder().variables(rain).values(f1).build();
Parfactor g2 = new StdParfactorBuilder().variables(sprinkler).values(f2).build();
Parfactor g3 = new StdParfactorBuilder().variables(rain, sprinkler, wet_grass).values(f3).build();
Parfactor g4 = new StdParfactorBuilder().variables(wet_grass_lot1).values(f4).build();
Parfactor g5 = new StdParfactorBuilder().variables(rain, sprinkler_lot1, wet_grass_lot1).values(f3).build();
Parfactor g6 = new StdParfactorBuilder().variables(rain, sprinkler, wet_grass).constraints(lot_lot1).values(f3).build();
Parfactor g7 = new StdParfactorBuilder().variables(sprinkler_lot1).values(f2).build();
Parfactor g8 = new StdParfactorBuilder().variables(sprinkler).constraints(lot_lot1).values(f2).build();
Marginal marginal = new StdMarginalBuilder().parfactors(g1, g2, g3, g4).build();
MacroOperation shatter = new Shatter(marginal);
Marginal result = shatter.run();
Marginal expected = new StdMarginalBuilder().parfactors(g1, g4, g5, g6, g7, g8).build();
assertEquals(expected, result);
}
@Test
public void testShatterThatResultsInPropositionalization() {
LogicalVariable lot = StdLogicalVariable.getInstance("Lot", "lot", 3);
Constant lot1 = Constant.getInstance("lot1");
Constant lot2 = Constant.getInstance("lot2");
Constant lot3 = Constant.getInstance("lot3");
Prv rain = StdPrv.getBooleanInstance("rain");
Prv sprinkler = StdPrv.getBooleanInstance("sprinkler", lot);
Prv wet_grass_lot1 = StdPrv.getBooleanInstance("wet_grass", lot1);
Prv wet_grass_lot2 = StdPrv.getBooleanInstance("wet_grass", lot2);
Prv wet_grass_lot3 = StdPrv.getBooleanInstance("wet_grass", lot3);
Prv sprinkler_lot1 = StdPrv.getBooleanInstance("sprinkler", lot1);
Prv sprinkler_lot2 = StdPrv.getBooleanInstance("sprinkler", lot2);
Prv sprinkler_lot3 = StdPrv.getBooleanInstance("sprinkler", lot3);
double [] f1 = {0.8, 0.2};
double [] f2 = {0.6, 0.4};
double [] f3 = {1.0, 0.0, 0.2, 0.8, 0.1, 0.9, 0.01, 0.99};
double [] f4 = {0.0, 1.0};
Parfactor g1 = new StdParfactorBuilder().variables(rain).values(f1).build();
Parfactor g2 = new StdParfactorBuilder().variables(sprinkler).values(f2).build();
Parfactor g4 = new StdParfactorBuilder().variables(wet_grass_lot1).values(f4).build();
Parfactor g2_1 = new StdParfactorBuilder().variables(sprinkler_lot1).values(f2).build();
Parfactor g2_2 = new StdParfactorBuilder().variables(sprinkler_lot2).values(f2).build();
Parfactor g2_3 = new StdParfactorBuilder().variables(sprinkler_lot3).values(f2).build();
Parfactor g3_1 = new StdParfactorBuilder().variables(rain, sprinkler_lot1, wet_grass_lot1).values(f3).build();
Parfactor g3_2 = new StdParfactorBuilder().variables(rain, sprinkler_lot2, wet_grass_lot2).values(f3).build();
Parfactor g3_3 = new StdParfactorBuilder().variables(rain, sprinkler_lot3, wet_grass_lot3).values(f3).build();
Marginal marginal = new StdMarginalBuilder().parfactors(g1, g2, g3_1, g3_2, g3_3, g4).build();
MacroOperation shatter = new Shatter(marginal);
Marginal result = shatter.run();
Marginal expected = new StdMarginalBuilder().parfactors(g1, g4, g2_1, g2_2, g2_3, g3_1, g3_2, g3_3).build();
assertEquals(expected, result);
}
@Test
public void testSimpleTrickyShatter() {
LogicalVariable a = StdLogicalVariable.getInstance("A", "x", 2);
Constant x1 = Constant.getInstance("x1");
Constant x2 = Constant.getInstance("x2");
Prv f = StdPrv.getBooleanInstance("f", a);
Prv f_x1 = StdPrv.getBooleanInstance("f", x1);
Prv f_x2 = StdPrv.getBooleanInstance("f", x2);
double [] val = {0, 1};
Parfactor g1 = new StdParfactorBuilder().variables(f).values(val).build();
Parfactor g2 = new StdParfactorBuilder().variables(f_x1).values(val).build();
Parfactor g3 = new StdParfactorBuilder().variables(f_x2).values(val).build();
Marginal input = new StdMarginalBuilder(2).parfactors(g1, g2).build();
MacroOperation shatter = new Shatter(input);
Marginal result = shatter.run();
Marginal expected = new StdMarginalBuilder().parfactors(g2, g2, g3).build();
assertEquals(expected, result);
}
@Test
public void testShatterWithCountingFormula() {
int n = 3;
LogicalVariable x = StdLogicalVariable.getInstance("X", "x", n);
LogicalVariable y = StdLogicalVariable.getInstance("Y", "x", n);
Constant x1 = Constant.getInstance("x1");
Constraint x_x1 = InequalityConstraint.getInstance(x, x1);
Prv b = StdPrv.getBooleanInstance("b", x);
Prv c = StdPrv.getBooleanInstance("c", x);
Prv e = StdPrv.getBooleanInstance("e", x);
Prv e_x1 = StdPrv.getBooleanInstance("e", x1);
Prv r = StdPrv.getBooleanInstance("r", x, y);
Prv r_x1_y = StdPrv.getBooleanInstance("r", x1, y);
Prv cf = CountingFormula.getInstance(y, r);
Prv cf_x1 = CountingFormula.getInstance(y, r_x1_y);
Parfactor g1 = new StdParfactorBuilder().variables(cf, e).build();
Parfactor g2 = new StdParfactorBuilder().variables(b, e, c).constraints(x_x1).build();
Parfactor g3 = new StdParfactorBuilder().variables(cf, e).constraints(x_x1).build();
Parfactor g4 = new StdParfactorBuilder().variables(cf_x1, e_x1).build();
Marginal input = new StdMarginalBuilder().parfactors(g1, g2).build();
MacroOperation shatter = new Shatter(input);
Marginal result = shatter.run();
Marginal expected = new StdMarginalBuilder().parfactors(g2, g3, g4).build();
assertEquals(expected, result);
}
@Test
public void testShatterOnCralcExample() {
int n = 3;
LogicalVariable x = StdLogicalVariable.getInstance("X", "x", n);
LogicalVariable y = StdLogicalVariable.getInstance("Y", "x", n);
Constant x1 = Constant.getInstance("x1");
Prv a = StdPrv.getBooleanInstance("a", x);
Prv b = StdPrv.getBooleanInstance("b", x);
Prv c = StdPrv.getBooleanInstance("c", x);
Prv d = StdPrv.getBooleanInstance("d", x);
Prv e = StdPrv.getBooleanInstance("e", x);
Prv f = StdPrv.getBooleanInstance("f", x);
Prv r = StdPrv.getBooleanInstance("r", x, y);
Prv r1 = StdPrv.getBooleanInstance("r1", x, y);
Prv r2 = StdPrv.getBooleanInstance("r2", x, y);
Prv c1 = StdPrv.getBooleanInstance("c", x1);
List<BigDecimal> f1 = TestUtils.toBigDecimalList(0.1, 0.9);
List<BigDecimal> f2 = TestUtils.toBigDecimalList(1.0, 0.0, 0.55, 0.45);
List<BigDecimal> f3 = TestUtils.toBigDecimalList(1, 0, 0, 1, 0, 1, 0, 1);
List<BigDecimal> f5 = TestUtils.toBigDecimalList(1, 0, 0, 1);
List<BigDecimal> f7 = TestUtils.toBigDecimalList(1, 0, 0, 1, 0, 1, 0, 1);
List<BigDecimal> f8 = TestUtils.toBigDecimalList(0.7, 0.3);
List<BigDecimal> f9 = TestUtils.toBigDecimalList(1, 0, 1, 0, 1, 0, 0, 1);
Parfactor g1 = new StdParfactorBuilder().variables(a).values(f1).build();
Parfactor g2 = new StdParfactorBuilder().variables(a, b).values(f2).build();
Parfactor g3 = new StdParfactorBuilder().variables(b, e, c).values(f3).build();
Parfactor g4 = new AggParfactorBuilder(r1, f, And.AND).build();
Parfactor g5 = new StdParfactorBuilder().variables(f, d).values(f5).build();
Parfactor g6 = new AggParfactorBuilder(r2, e, Or.OR).build();
Parfactor g7 = new StdParfactorBuilder().variables(a, r, r1).values(f7).build();
Parfactor g8 = new StdParfactorBuilder().variables(r).values(f8).build();
Parfactor g9 = new StdParfactorBuilder().variables(d, r, r2).values(f9).build();
Parfactor g10 = new StdParfactorBuilder().variables(c1).build();
RandomVariableSet query = RandomVariableSet.getInstance(c1, new HashSet<Constraint>(0));
Marginal input = new StdMarginalBuilder().parfactors(g1, g2, g3, g4, g5, g6, g7, g8, g9, g10).preservable(query).build();
// MacroOperation conversion = new ConvertToStdParfactors(input);
// input = conversion.run();
MacroOperation shatter = new Shatter(input);
Marginal result = shatter.run();
System.out.print(result);
}
}
public static class FullExpandTest {
@Test
public void testFullExpand() {
LogicalVariable a = StdLogicalVariable.getInstance("A", "x", 3);
LogicalVariable b = StdLogicalVariable.getInstance("B", "x", 3);
Constant x1 = Constant.getInstance("x1");
Constant x2 = Constant.getInstance("x2");
Constant x3 = Constant.getInstance("x3");
Constraint a_x1 = InequalityConstraint.getInstance(a, x1);
Constraint a_x2 = InequalityConstraint.getInstance(a, x2);
Constraint a_x3 = InequalityConstraint.getInstance(a, x3);
Prv f_a = StdPrv.getBooleanInstance("f", a);
Prv f_x2 = StdPrv.getBooleanInstance("f", x2);
Prv f_x3 = StdPrv.getBooleanInstance("f", x3);
Prv h_b = StdPrv.getBooleanInstance("h", b);
Prv cf = CountingFormula.getInstance(a, f_a, a_x1);
Parfactor g1 = new StdParfactorBuilder().variables(f_a).values(0.4, 0.6).build();
Parfactor g2 = new StdParfactorBuilder().variables(cf, h_b).values(1, 2, 3, 4, 5, 6).build();
Parfactor g3 = new StdParfactorBuilder().variables(f_a).constraints(a_x2, a_x3).values(0.4, 0.6).build();
Parfactor g4 = new StdParfactorBuilder().variables(f_x2).values(0.4, 0.6).build();
Parfactor g5 = new StdParfactorBuilder().variables(f_x3).values(0.4, 0.6).build();
Parfactor g6 = new StdParfactorBuilder().variables(f_x3, f_x2, h_b).values(1, 2, 3, 4, 3, 4, 5, 6).build();
Marginal marginal = new StdMarginalBuilder(2).parfactors(g1, g2).build();
MacroOperation fullExpand = new FullExpand(marginal, g2, cf);
Marginal result = fullExpand.run();
Marginal expected = new StdMarginalBuilder().parfactors(g3, g4, g5, g6).build();
assertEquals(expected, result);
}
}
public static class PropositionalizationTest {
@Test
public void testPropositionalize() {
LogicalVariable lot = StdLogicalVariable.getInstance("Lot", "lot", 3);
Constant lot1 = Constant.getInstance("lot1");
Constant lot2 = Constant.getInstance("lot2");
Constant lot3 = Constant.getInstance("lot3");
Prv rain = StdPrv.getBooleanInstance("rain");
Prv sprinkler = StdPrv.getBooleanInstance("sprinkler", lot);
Prv wet_grass = StdPrv.getBooleanInstance("wet_grass", lot);
Prv wet_grass_lot1 = StdPrv.getBooleanInstance("wet_grass", lot1);
Prv wet_grass_lot2 = StdPrv.getBooleanInstance("wet_grass", lot2);
Prv wet_grass_lot3 = StdPrv.getBooleanInstance("wet_grass", lot3);
Prv sprinkler_lot1 = StdPrv.getBooleanInstance("sprinkler", lot1);
Prv sprinkler_lot2 = StdPrv.getBooleanInstance("sprinkler", lot2);
Prv sprinkler_lot3 = StdPrv.getBooleanInstance("sprinkler", lot3);
double [] f1 = {0.8, 0.2};
double [] f2 = {0.6, 0.4};
double [] f3 = {1.0, 0.0, 0.2, 0.8, 0.1, 0.9, 0.01, 0.99};
double [] f4 = {0.0, 1.0};
Parfactor g1 = new StdParfactorBuilder().variables(rain).values(f1).build();
Parfactor g2 = new StdParfactorBuilder().variables(sprinkler).values(f2).build();
Parfactor g3 = new StdParfactorBuilder().variables(rain, sprinkler, wet_grass).values(f3).build();
Parfactor g4 = new StdParfactorBuilder().variables(wet_grass_lot1).values(f4).build();
Parfactor g2_1 = new StdParfactorBuilder().variables(sprinkler_lot1).values(f2).build();
Parfactor g2_2 = new StdParfactorBuilder().variables(sprinkler_lot2).values(f2).build();
Parfactor g2_3 = new StdParfactorBuilder().variables(sprinkler_lot3).values(f2).build();
Parfactor g3_1 = new StdParfactorBuilder().variables(rain, sprinkler_lot1, wet_grass_lot1).values(f3).build();
Parfactor g3_2 = new StdParfactorBuilder().variables(rain, sprinkler_lot2, wet_grass_lot2).values(f3).build();
Parfactor g3_3 = new StdParfactorBuilder().variables(rain, sprinkler_lot3, wet_grass_lot3).values(f3).build();
Marginal marginal = new StdMarginalBuilder().parfactors(g1, g2, g3, g4).build();
MacroOperation propositionalize = new Propositionalize(marginal, g3, lot);
Marginal result = propositionalize.run();
Marginal expected = new StdMarginalBuilder().parfactors(g1, g4, g2_1, g2_2, g2_3, g3_1, g3_2, g3_3).build();
assertEquals(expected, result);
}
}
/**
* Tests counting convert.
*/
public static class CountingConvertTest {
/**
* Creates example in section 2.5.2.7 of Kisynski (2010).
* Only sets Φ<sub>4</sub> and Φ<sub>5</sub> are used.
* <p>
* Parfactors [09] and [12] have been changed to use integer numbers,
* otherwise comparison between doubles would complicate the test.
* Precision is not the objective of this test.
* </p>
* <p>
* The population of logical variable Lot is set to 16 individuals.
* Factor F7 will have 32 rows.
* </p>
*/
@Test
public void testSimpleCountingConvert() {
LogicalVariable lot = StdLogicalVariable.getInstance("Lot", "lot", 16);
Constant lot1 = Constant.getInstance("lot1");
Constraint lot_lot1 = InequalityConstraint.getInstance(lot, lot1);
Prv rain = StdPrv.getBooleanInstance("rain");
Prv wet_grass = StdPrv.getBooleanInstance("wet_grass", lot);
Prv formula = CountingFormula.getInstance(lot, wet_grass, lot_lot1);
double [] f1 = {0.8, 0.2};
double [] f5 = {2, 3, 5, 7};
double [] f6 = {0.32, 0.936};
double [] f7 = {32768, 49152, 73728, 110592, 165888, 248832, 373248,
559872, 839808, 1259712, 1889568, 2834352, 4251528, 6377292,
9565938, 14348907, 30517578125.0, 42724609375.0, 59814453125.0,
83740234375.0, 117236328125.0, 164130859375.0, 229783203125.0,
321696484375.0, 450375078125.0, 630525109375.0, 882735153125.0,
1235829214375.0, 1730160900125.0, 2422225260175.0,
3391115364245.0, 4747561509943.0};
Parfactor g1 = new StdParfactorBuilder().variables(rain).values(f1).build();
Parfactor g9 = new StdParfactorBuilder().variables(rain, wet_grass).constraints(lot_lot1).values(f5).build();
Parfactor g11 = new StdParfactorBuilder().variables(rain).values(f6).build();
Parfactor g12 = new StdParfactorBuilder().variables(rain, formula).values(f7).build();
Marginal input = new StdMarginalBuilder().parfactors(g1, g9, g11).build();
MacroOperation countingConvert = new CountingConvert(input, g9, lot);
Marginal result = countingConvert.run();
Marginal expected = new StdMarginalBuilder().parfactors(g1, g11, g12).build();
assertEquals(expected, result);
}
}
/**
* Tests global sum out.
*/
public static class GlobalSumOutTest {
private final LogicalVariable lot = StdLogicalVariable.getInstance("Lot", "lot", 10);
private final Constant lot1 = Constant.getInstance("lot1");
private final Constraint lot_lot1 = InequalityConstraint.getInstance(lot, lot1);
private final Prv rain = StdPrv.getBooleanInstance("rain");
private final Prv another_rain = StdPrv.getBooleanInstance("another_rain");
private final Prv sprinkler = StdPrv.getBooleanInstance("sprinkler", lot);
private final Prv sprinkler_lot1 = StdPrv.getBooleanInstance("sprinkler", lot1);
private final Prv wet_grass = StdPrv.getBooleanInstance("wet_grass", lot);
private final Prv wet_grass_lot1 = StdPrv.getBooleanInstance("wet_grass", lot1);
private final double [] f1 = {1, 2};
private final double [] f2 = {2, 3};
private final double [] f3 = {1, 2, 3, 4, 5, 6, 7, 8};
private final double [] f6 = {3, 5};
private final double [] f7 = {2, 3, 5, 7};
private final double [] f8 = {56, 79};
private final double [] f9 = {11, 16, 31, 36};
private final Parfactor g1 = new StdParfactorBuilder().variables(rain).values(f1).build();
private final Parfactor g4 = new StdParfactorBuilder().variables(wet_grass_lot1).values(f1).build();
private final Parfactor g5 = new StdParfactorBuilder().variables(rain, sprinkler_lot1, wet_grass_lot1).values(f3).build();
private final Parfactor g6 = new StdParfactorBuilder().variables(rain, sprinkler, wet_grass).values(f3).constraints(lot_lot1).build();
private final Parfactor g7 = new StdParfactorBuilder().variables(sprinkler_lot1).values(f2).build();
private final Parfactor g8 = new StdParfactorBuilder().variables(sprinkler).values(f2).constraints(lot_lot1).build();
private final Parfactor g9 = new StdParfactorBuilder().variables(rain, wet_grass).values(f9).constraints(lot_lot1).build();
private final Parfactor g10 = new StdParfactorBuilder().variables(rain, wet_grass_lot1).values(f9).build();
private final Parfactor g11 = new StdParfactorBuilder().variables(rain).values(f6).build();
private final Parfactor g12 = new StdParfactorBuilder().variables(rain, another_rain).values(f7).build();
private final Parfactor g13 = new StdParfactorBuilder().variables(another_rain).values(f8).build();
@Test
public void testGlobalSumOutWithConstraintSimplified() {
Marginal input = new StdMarginalBuilder(2).parfactors(g6, g8).build();
Set<Constraint> constraints = Sets.setOf(lot_lot1);
RandomVariableSet eliminables = RandomVariableSet.getInstance(sprinkler, constraints);
MacroOperation globalSumOut = new GlobalSumOut(input, eliminables);
Marginal result = globalSumOut.run();
Marginal expected = new StdMarginalBuilder(5).parfactors(g9).build();
assertEquals(expected, result);
}
@Test
public void testGlobalSumOutWithConstraint() {
Marginal input = new StdMarginalBuilder(6).parfactors(g1, g4, g5, g6, g7, g8).build();
Set<Constraint> constraints = Sets.setOf(lot_lot1);
RandomVariableSet eliminables = RandomVariableSet.getInstance(sprinkler, constraints);
MacroOperation globalSumOut = new GlobalSumOut(input, eliminables);
Marginal result = globalSumOut.run();
Marginal expected = new StdMarginalBuilder(5).parfactors(g1, g4, g5, g7, g9).build();
assertEquals(expected, result);
}
@Test
public void testGlobalSumOutNoConstraints() {
Marginal input = new StdMarginalBuilder(5).parfactors(g1, g4, g5, g7, g9).build();
Set<Constraint> constraints = Sets.getInstance(0);
RandomVariableSet eliminables = RandomVariableSet.getInstance(sprinkler_lot1, constraints);
MacroOperation globalSumOut = new GlobalSumOut(input, eliminables);
Marginal result = globalSumOut.run();
Marginal expected = new StdMarginalBuilder(4).parfactors(g1, g4, g9, g10).build();
assertEquals(expected, result);
}
@Test
public void testGlobalSumWithThreeStdParfactors() {
Marginal input = new StdMarginalBuilder(3).parfactors(g1, g11, g12).build();
Set<Constraint> constraints = Sets.getInstance(0);
RandomVariableSet eliminables = RandomVariableSet.getInstance(rain, constraints);
MacroOperation globalSumOut = new GlobalSumOut(input, eliminables);
Marginal result = globalSumOut.run();
Marginal expected = new StdMarginalBuilder(1).parfactors(g13).build();
assertEquals(expected, result);
}
}
}