/*
* Copyright (c) 2013, SRI International
* All rights reserved.
* Licensed under the The BSD 3-Clause License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://opensource.org/licenses/BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the aic-praise nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.sri.ai.test.praise.sgsolver;
import static com.sri.ai.expresso.helper.Expressions.ZERO;
import static com.sri.ai.expresso.helper.Expressions.apply;
import static com.sri.ai.expresso.helper.Expressions.parse;
import static com.sri.ai.grinder.sgdpllt.library.FunctorConstants.MINUS;
import static com.sri.ai.util.Util.list;
import static org.junit.Assert.assertEquals;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import com.sri.ai.expresso.api.Expression;
import com.sri.ai.expresso.api.Type;
import com.sri.ai.expresso.helper.Expressions;
import com.sri.ai.expresso.type.IntegerInterval;
import com.sri.ai.expresso.type.RealInterval;
import com.sri.ai.grinder.sgdpllt.core.TrueContext;
import com.sri.ai.grinder.sgdpllt.library.number.Times;
import com.sri.ai.praise.sgsolver.solver.ExpressionFactorsAndTypes;
import com.sri.ai.praise.sgsolver.solver.InferenceForFactorGraphAndEvidence;
import com.sri.ai.util.Util;
public class InferenceForFactorGraphAndEvidenceTest {
// The definitions of categorical types
Map<String, String> mapFromCategoricalTypeNameToSizeString;
// The definitions of other types
Collection<Type> additionalTypes;
// The definitions of variables
Map<String, String> mapFromRandomVariableNameToTypeName;
// The definitions of non-uniquely named constants
Map<String, String> mapFromNonUniquelyNamedConstantNameToTypeName;
// The definitions of uniquely named constants
Map<String, String> mapFromUniquelyNamedConstantNameToTypeName;
boolean isBayesianNetwork;
List<Expression> factors;
Expression evidence;
Expression queryExpression;
Expression expected;
Expression expectedWithNoFactorization;
Expression expectedWithFactorization;
@Test
public void test() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map(
"Folks", "10",
"Boolean", "2");
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"earthquake", "Boolean",
"burglar", "Folks", // a multi-value random variable
"alarm", "Boolean"
);
// The definitions of non-uniquely named constants
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map(
"seismicLocation", "Boolean"
);
// The definitions of non-uniquely named constants
mapFromUniquelyNamedConstantNameToTypeName = Util.map("none", "Folks", "tom", "Folks");
// a variant of the earthquake/burglary model in which some burglars are more active than others.
isBayesianNetwork = true;
factors = Times.getMultiplicands(parse("" +
"(if earthquake then 0.01 else 0.99) * " +
"(if burglar = none then 0.7 else if burglar = tom then 0.1 else 0.2 / (|Folks| - 2)) * " +
// note the division above of the potential by number of remaining values, as the probabilities must sum up to 1
"(if burglar != none or earthquake "
+ "then if alarm then 0.9 else 0.1 "
+ "else if alarm then 0.05 else 0.95) " +
""));
queryExpression = parse("earthquake");
evidence = null; // no evidence
expected = parse("if earthquake then 0.01 else 0.99"); // the prior
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("earthquake");
evidence = parse("not alarm"); // can be any boolean expression
expected = parse("if earthquake then 0.00145127349 else 0.998548727");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("earthquake");
evidence = parse("alarm");
expected = parse("if earthquake then 0.0289435601 else 0.97105644");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("earthquake");
evidence = parse("alarm and burglar = none");
expected = parse("if earthquake then 0.153846154 else 0.846153846");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("earthquake");
evidence = parse("alarm or not alarm"); // no information
expected = parse("if earthquake then 0.01 else 0.99"); // the prior
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("earthquake");
evidence = parse("true"); // no information
expected = parse("if earthquake then 0.01 else 0.99"); // the prior
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("alarm");
evidence = null; // no evidence
expected = parse("if alarm then 0.31095 else 0.68905"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("alarm");
evidence = parse("not alarm");
expected = parse("if alarm then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("alarm");
evidence = parse("alarm");
expected = parse("if alarm then 1 else 0");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("alarm");
evidence = parse("alarm and burglar = none");
expected = parse("if alarm then 1 else 0");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("alarm");
evidence = parse("alarm or not alarm"); // no information
expected = parse("if alarm then 0.31095 else 0.68905"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("alarm");
evidence = parse("true"); // no information
expected = parse("if alarm then 0.31095 else 0.68905"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = none");
evidence = null; // no evidence
expected = parse("if burglar = none then 0.7 else 0.3"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = none");
evidence = parse("not alarm");
expected = parse("if burglar = none then 0.956461795 else 0.0435382048");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = none");
evidence = parse("alarm");
expected = parse("if burglar = none then 0.131693198 else 0.868306802");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = none");
evidence = parse("alarm and burglar = none");
expected = parse("if burglar = none then 1 else 0");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = none");
evidence = parse("alarm or not alarm"); // no information
expected = parse("if burglar = none then 0.7 else 0.3"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = none");
evidence = parse("true"); // no information
expected = parse("if burglar = none then 0.7 else 0.3"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = tom");
evidence = null; // no evidence
expected = parse("if burglar = tom then 0.1 else 0.9"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = tom");
evidence = parse("not alarm");
expected = parse("if burglar = tom then 0.0145127349 else 0.985487265");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = tom");
evidence = parse("alarm");
expected = parse("if burglar = tom then 0.289435601 else 0.710564399");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = tom");
evidence = parse("alarm and burglar = none");
expected = parse("if burglar = tom then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = tom");
evidence = parse("alarm or not alarm"); // no information
expected = parse("if burglar = tom then 0.1 else 0.9"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = tom");
evidence = parse("true"); // no information
expected = parse("if burglar = tom then 0.1 else 0.9"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
// queries on non-Boolean variable burglar:
queryExpression = parse("burglar");
evidence = null; // no evidence
expected = parse("if burglar = none then 0.7 else if burglar = tom then 0.1 else 0.025"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar");
evidence = parse("not alarm");
expected = parse("if burglar = none then 0.956461795 else if burglar = tom then 0.0145127349 else 0.00362818373");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar");
evidence = parse("alarm");
expected = parse("if burglar = none then 0.131693198 else if burglar = tom then 0.289435601 else 0.0723589001");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar");
evidence = parse("alarm and burglar = none");
expected = parse("if burglar = none then 1 else 0");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar");
evidence = parse("alarm or not alarm"); // no information
expected = parse("if burglar = none then 0.7 else if burglar = tom then 0.1 else 0.025"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar");
evidence = parse("true"); // no information
expected = parse("if burglar = none then 0.7 else if burglar = tom then 0.1 else 0.025"); // the marginal
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
// now using the constant 'seismicLocation'
factors = Times.getMultiplicands(parse("" +
"(if seismicLocation then if earthquake then 0.1 else 0.9 else if earthquake then 0.01 else 0.99) * " +
"(if burglar = none then 0.7 else if burglar = tom then 0.1 else 0.2 / (|Folks| - 2)) * " +
// note the division above of the potential by number of remaining values, as the probabilities must sum up to 1
"(if burglar != none or earthquake "
+ "then if alarm then 0.9 else 0.1 "
+ "else if alarm then 0.05 else 0.95) " +
""));
queryExpression = parse("earthquake");
evidence = null; // no evidence
expected = parse("if seismicLocation then if earthquake then 0.1 else 0.9 else if earthquake then 0.01 else 0.99"); // the prior, parameterized by seismicLocation
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("earthquake");
evidence = parse("not alarm"); // can be any boolean expression
expected = parse("if seismicLocation then if earthquake then 0.0157356412 else 0.984264359 else if earthquake then 0.00145127349 else 0.998548727");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("burglar = tom");
evidence = parse("alarm");
// Here factorization creates two distinct but equivalent solutions; eventually we should have an equivalence test (didn't do it now because that would require full relational support even in the absence of random relational variables).
expectedWithNoFactorization = parse("if seismicLocation then if burglar = tom then 0.24691358 else 0.75308642 else if burglar = tom then 0.289435601 else 0.710564399");
expectedWithFactorization = parse("if burglar = tom then if seismicLocation then 0.24691358 else 0.289435601 else if seismicLocation then 0.75308642 else 0.710564399");
runTest(queryExpression, evidence, expectedWithNoFactorization, expectedWithFactorization, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
}
@Test
public void testAPI() {
// IMPORTANT: this test is reproduced in the User Guide as an example,
// so it should be kept in sync with it.
String modelString = ""
+
"random earthquake: Boolean;" +
"random burglary: Boolean;" +
"random alarm: Boolean;" +
"" +
"earthquake 0.01;" +
"burglary 0.1;" +
"" +
"if earthquake" +
" then if burglary" +
" then alarm 0.95" +
" else alarm 0.6" +
" else if burglary" +
" then alarm 0.9" +
" else alarm 0.01;" +
" " +
"not alarm;"
+ "";
Expression evidence = parse("not alarm");
// can be any boolean expression
boolean isBayesianNetwork = true;
// is a Bayesian network, that is, factors are normalized
// and the sum of their product over all assignments to random variables is 1.
boolean exploitFactorization = true;
// exploit factorization (that is, employ Variable Elimination,
// as opposed to summing over the entire joint probability distribution).
InferenceForFactorGraphAndEvidence inferencer =
new InferenceForFactorGraphAndEvidence(
new ExpressionFactorsAndTypes(modelString),
isBayesianNetwork ,
evidence,
exploitFactorization,
null /* default theory */);
Expression queryExpression;
Expression marginal;
queryExpression = parse("not earthquake");
// can be any boolean expression, or any random variable
marginal = inferencer.solve(queryExpression);
System.out.println("Marginal is " + marginal);
queryExpression = parse("earthquake");
marginal = inferencer.solve(queryExpression);
System.out.println("Marginal is " + marginal);
}
@Test
public void testBurglary() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map(
"Boolean", "2");
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"burglary", "Boolean",
"alarm", "Boolean",
"call", "Boolean"
);
// The definitions of non-uniquely named constants
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
// The definitions of non-uniquely named constants
mapFromUniquelyNamedConstantNameToTypeName = Util.map();
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if alarm then if call then 0.7 else 0.3 else if call then 0 else 1)*"
+ "(if burglary then if alarm then 0.9 else 0.1 else if alarm then 0.01 else 0.99)*"
+ "(if burglary then 0.1 else 0.9)"));
InferenceForFactorGraphAndEvidence inferencer;
inferencer = new InferenceForFactorGraphAndEvidence(
new ExpressionFactorsAndTypes(factors,
mapFromRandomVariableNameToTypeName,
mapFromNonUniquelyNamedConstantNameToTypeName,
mapFromUniquelyNamedConstantNameToTypeName,
mapFromCategoricalTypeNameToSizeString,
list()),
isBayesianNetwork,
evidence,
false, null);
Expression result = inferencer.sum(list(parse("alarm")), Times.make(factors));
System.out.println(result);
}
@Test
public void relationalConstants() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map(
"Folks", "10",
"Boolean", "2");
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"happy", "Boolean",
"boss", "Folks"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map("tom", "Folks");
isBayesianNetwork = true;
factors = Times.getMultiplicands(parse(""
+ "(1/|Folks|) *" // uniform prior for 'boss' does not depend on the actual value of 'boss'
+ "(if boss = tom then if happy then 1 else 0 else if happy then 0 else 1)"));
queryExpression = parse("happy");
evidence = null; // no evidence
expected = parse("if happy then 0.1 else 0.9");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("happy");
evidence = parse("boss = tom");
expected = parse("if happy then 1 else 0");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
// Now 'boss' is a constant:
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"happy", "Boolean"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map(
"boss", "Folks"
);
isBayesianNetwork = true;
factors = Times.getMultiplicands(parse("" // no need for a prior for 'boss' now
+ "(if boss = tom then if happy then 1 else 0 else if happy then 0 else 1)"));
queryExpression = parse("happy");
evidence = null; // no evidence
expected = parse("if boss = tom then if happy then 1 else 0 else if happy then 0 else 1"); // query is a function of the constant
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
// Ignore: as we implement function-typed theories
// // Now 'boss' is a constant unary predicate:
//
// // The definitions of variables
// mapFromRandomVariableNameToTypeName = Util.map(
// "happy", "Boolean"
// );
//
// mapFromNonUniquelyNamedConstantNameToTypeName = Util.map(
// "boss", "->(x(Folks), Boolean)"
// );
//
// isBayesianNetwork = true;
// factors = Times.getMultiplicands(parse("" // no need for a prior for 'boss' now
// + "(if boss(tom) then if happy then 0.9 else 0.1 else if happy then 0.2 else 0.8)"));
//
// queryExpression = parse("happy");
// evidence = null; // no evidence
// expected = parse("if boss(tom) then if happy then 0.9 else 0.1 else if happy then 0.2 else 0.8"); // query is a function of the constant
// runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
//
// queryExpression = parse("happy");
// evidence = parse("happy");
// expected = parse("if happy then 1 else 0"); // query is NOT a function of the constant in this case
// runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
}
@Test
public void lucky() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map(
"People", "1000",
"Boolean", "2");
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"lucky", "Boolean",
"winner", "People"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map("rodrigo", "People");
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if lucky then 1 else 0)*"
+ "(if lucky then if winner = rodrigo then 1 else 0 else 0.5)"));
queryExpression = parse("winner = rodrigo");
evidence = null;
expected = parse("if winner = rodrigo then 1 else 0");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
}
@Test
public void smartest() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map(
"People", "1000",
"Boolean", "2");
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"boss", "People",
"smartest", "People"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map("bob", "People", "mary", "People", "tom", "People");
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if (for all P in People : smartest = P => boss = P) then 1 else 0) * " + // same as (if smartest = boss then 1 else 0)
"( if smartest != bob and smartest != mary then 1 else 0)" +
""));
queryExpression = parse("boss = tom");
evidence = null;
expected = parse("if boss = tom then 0.00100200401 else 0.998997996"); // tom is 1 out of 998 people left to be the smartest and boss
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
queryExpression = parse("boss");
evidence = null;
expected = parse("if boss = bob then 0 else if boss = mary then 0 else 0.00100200401"); // gives the distribution to all values of queried variable
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, list());
}
@Test
public void differenceArithmeticOnIntervals() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map(
"Boolean", "2",
"Country", "200");
additionalTypes = list(new IntegerInterval(0, 99));
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"age", "0..99",
"country", "Country",
"minor", "Boolean",
"workingAge", "Boolean",
"senior", "Boolean"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map("japan", "Country", "brazil", "Country");
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if age >= 65 then if senior then 1 else 0 else if senior then 0 else 1)"
+ "*(if age < 18 then if minor then 1 else 0 else if minor then 0 else 1)"
+ "*(if age >= 21 and age < 65 then if workingAge then 1 else 0 else if workingAge then 0 else 1)"));
queryExpression = parse("senior");
evidence = null;
expected = parse("if senior then 0.35 else 0.65");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("workingAge");
evidence = null;
expected = parse("if workingAge then 0.44 else 0.56");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor");
evidence = null;
expected = parse("if minor then 0.18 else 0.82");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = null;
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if age < 50 then 2/3 else 1/3)"
+ "*(if age >= 65 then if senior then 1 else 0 else if senior then 0 else 1)"
+ "*(if age < 18 then if minor then 1 else 0 else if minor then 0 else 1)"
+ "*(if age >= 21 and age < 65 then if workingAge then 1 else 0 else if workingAge then 0 else 1)"));
queryExpression = parse("senior");
evidence = null;
expected = parse("if senior then 0.233333333 else 0.766666667");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("workingAge");
evidence = null;
expected = parse("if workingAge then 0.486666667 else 0.513333333");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor");
evidence = null;
expected = parse("if minor then 0.24 else 0.76");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = null;
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if country = brazil then (if age < 50 then 2/3 else 1/3) else 1/100)" // P(age | country)
+ "*(if age >= 65 then if senior then 1 else 0 else if senior then 0 else 1)"
+ "*(if age < 18 then if minor then 1 else 0 else if minor then 0 else 1)"
+ "*(if age >= 21 and age < 65 then if workingAge then 1 else 0 else if workingAge then 0 else 1)"));
queryExpression = parse("senior");
evidence = parse("country = brazil");
expected = parse("if senior then 0.233333333 else 0.766666667");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("workingAge");
evidence = parse("country = brazil");
expected = parse("if workingAge then 0.486666667 else 0.513333333");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor");
evidence = parse("country = brazil");
expected = parse("if minor then 0.24 else 0.76");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = parse("country = brazil");
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("senior");
evidence = parse("country != brazil");
expected = parse("if senior then 0.35 else 0.65");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("workingAge");
evidence = parse("country != brazil");
expected = parse("if workingAge then 0.44 else 0.56");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor");
evidence = parse("country != brazil");
expected = parse("if minor then 0.18 else 0.82");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = parse("country != brazil");
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
}
@Test
public void differenceArithmetic() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map(
"Boolean", "2",
"Country", "200");
additionalTypes = list(new IntegerInterval(0, 99));
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"age", "Integer",
"country", "Country",
"minor", "Boolean",
"workingAge", "Boolean",
"senior", "Boolean"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map("japan", "Country", "brazil", "Country");
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if age >= 65 then if senior then 1 else 0 else if senior then 0 else 1)"
+ "*(if age < 18 then if minor then 1 else 0 else if minor then 0 else 1)"
+ "*(if age >= 21 and age < 65 then if workingAge then 1 else 0 else if workingAge then 0 else 1)"));
queryExpression = parse("senior");
evidence = parse("age >= 0 and age < 100");
expected = parse("if senior then 0.35 else 0.65");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("workingAge");
evidence = parse("age >= 0 and age < 100");
expected = parse("if workingAge then 0.44 else 0.56");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor");
evidence = parse("age >= 0 and age < 100");
expected = parse("if minor then 0.18 else 0.82");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = parse("age >= 0 and age < 100");
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if age < 50 then 2/3 else 1/3)"
+ "*(if age >= 65 then if senior then 1 else 0 else if senior then 0 else 1)"
+ "*(if age < 18 then if minor then 1 else 0 else if minor then 0 else 1)"
+ "*(if age >= 21 and age < 65 then if workingAge then 1 else 0 else if workingAge then 0 else 1)"));
queryExpression = parse("senior");
evidence = parse("age >= 0 and age < 100");
expected = parse("if senior then 0.233333333 else 0.766666667");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("workingAge");
evidence = parse("age >= 0 and age < 100");
expected = parse("if workingAge then 0.486666667 else 0.513333333");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor");
evidence = parse("age >= 0 and age < 100");
expected = parse("if minor then 0.24 else 0.76");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = parse("age >= 0 and age < 100");
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if country = brazil then (if age < 50 then 2/3 else 1/3) else 1/100)" // P(age | country)
+ "*(if age >= 65 then if senior then 1 else 0 else if senior then 0 else 1)"
+ "*(if age < 18 then if minor then 1 else 0 else if minor then 0 else 1)"
+ "*(if age >= 21 and age < 65 then if workingAge then 1 else 0 else if workingAge then 0 else 1)"));
queryExpression = parse("senior");
evidence = parse("age >= 0 and age < 100 and country = brazil");
expected = parse("if senior then 0.233333333 else 0.766666667");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("workingAge");
evidence = parse("age >= 0 and age < 100 and country = brazil");
expected = parse("if workingAge then 0.486666667 else 0.513333333");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor");
evidence = parse("age >= 0 and age < 100 and country = brazil");
expected = parse("if minor then 0.24 else 0.76");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = parse("age >= 0 and age < 100 and country = brazil");
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("senior");
evidence = parse("age >= 0 and age < 100 and country != brazil");
expected = parse("if senior then 0.35 else 0.65");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("workingAge");
evidence = parse("age >= 0 and age < 100 and country != brazil");
expected = parse("if workingAge then 0.44 else 0.56");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor");
evidence = parse("age >= 0 and age < 100 and country != brazil");
expected = parse("if minor then 0.18 else 0.82");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = parse("age >= 0 and age < 100 and country != brazil");
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("minor and senior");
evidence = parse("age = age and age >= 0 and age < 100 and country != brazil");
expected = parse("if minor and senior then 0 else 1");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
}
@Test
public void differenceArithmeticOnIntervalsWithMultipleVariables() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map();
additionalTypes = list(new IntegerInterval(0, 99));
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"I", "0..99",
"J", "0..99",
"K", "0..99"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map();
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(
"(if J > I then 0.3 else 0.7) *" +
"(if K > J then 0.6 else 0.4)"));
queryExpression = parse("I");
evidence = null;
expected = parse("if I < 98 then (-0.04 * I ^ 2 + 23.88 * I + 1520.92) / 257164 else if I < 99 then (-0.06 * I ^ 2 + -0.18 * I + 4070.88) / 257164 else (0.14 * I ^ 2 + 0.42 * I + 2079.28) / 257164");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(
"(if J > I then 0.3*I else 0.7*I) *" +
"(if K > J then 0.6*J else 0.4*J)"));
queryExpression = parse("I");
evidence = null;
expected = parse("if I < 98 then (0.0333333333 * I ^ 4 + 18.01 * I ^ 3 + -1176.08333 * I ^ 2 + 70569.06 * I) / 469273533 else if I < 99 then (-0.16 * I ^ 4 + 23.94 * I ^ 3 + -1212.02 * I ^ 2 + 199067.88 * I) / 469273533 else (0.0933333333 * I ^ 4 + 0.28 * I ^ 3 + 0.186666667 * I ^ 2 + 67914 * I) / 469273533");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
}
@Test
public void linearRealArithmeticOnIntervalsWithMultipleVariables() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map();
additionalTypes = list(new RealInterval("[0;100]"));
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"X", "[0;100]",
"Y", "[0;100]",
"Z", "[0;100]"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map();
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(
"(if X < 50 then 1 else 2)"));
queryExpression = parse("X");
evidence = null;
expected = parse("if X < 50 then 0.00666666667 else 0.0133333333"); // density
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
queryExpression = parse("X < 50");
evidence = null;
expected = parse("if X < 50 then 0.333333333 else 0.666666667"); // probability of the random event
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(
"(if Y > X then 0.3 else 0.7) *" +
"(if Z > Y then 0.6 else 0.4)"));
queryExpression = parse("X");
evidence = null;
expected = parse("if X < 100 then (-0.04 * X ^ 2 + 24 * X + 1500) / 256666.667 else (0.14 * X ^ 2 + 2100) / 256666.667");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(
"(if Y > X then 0.3*X else 0.7*X) *" +
"(if Z > Y then 0.6*Y else 0.4*Y)"));
queryExpression = parse("X");
evidence = null;
expected = parse("if X < 100 then (-0.0266666667 * X ^ 4 + 12 * X ^ 3 + 70000 * X) / 596666667 else (0.0933333333 * X ^ 4 + 70000 * X) / 596666667");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(
"if X = 10 then 1 else 2"));
queryExpression = parse("X");
evidence = null;
expected = parse("if X = 10 then 0.005 else 0.01");
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
}
@Test
public void linearRealArithmeticOnPosition() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map();
additionalTypes = list(new RealInterval("[0;10]"));
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"position", "[0;10]",
"observedPosition", "Real"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map();
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(
"(position)*(if observedPosition > 4 and observedPosition < 5 then 1 else 0)"));
queryExpression = parse("position");
evidence = null;
expected = parse("position/50"); // density
runTest(queryExpression, evidence, expected, expected, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
}
/**
* @param queryExpression
* @param evidence
* @param expectedWithNoFactorization
* @param expectedWithFactorization
* @param isBayesianNetwork
* @param factors
* @param mapFromRandomVariableNameToTypeName
* @param mapFromNonUniquelyNamedConstantNameToTypeName
* @param mapFromUniquelyNamedConstantNameToTypeName
* @param mapFromCategoricalTypeNameToSizeString
* @param additionalTypes TODO
*/
private void runTest(Expression queryExpression, Expression evidence, Expression expectedWithNoFactorization, Expression expectedWithFactorization, boolean isBayesianNetwork, List<Expression> factors, Map<String, String> mapFromRandomVariableNameToTypeName, Map<String, String> mapFromNonUniquelyNamedConstantNameToTypeName, Map<String, String> mapFromUniquelyNamedConstantNameToTypeName, Map<String, String> mapFromCategoricalTypeNameToSizeString, Collection<Type> additionalTypes) {
runTestWithFactorizationOption(false, queryExpression, evidence, expectedWithNoFactorization, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
runTestWithFactorizationOption(true, queryExpression, evidence, expectedWithFactorization, isBayesianNetwork, factors, mapFromRandomVariableNameToTypeName, mapFromNonUniquelyNamedConstantNameToTypeName, mapFromUniquelyNamedConstantNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes);
}
/**
* @param useFactorization
* @param queryExpression
* @param evidence
* @param expected
* @param isBayesianNetwork
* @param factorGraph
* @param mapFromRandomVariableNameToTypeName
* @param mapFromNonUniquelyNamedConstantNameToTypeName
* @param mapFromUniquelyNamedConstantNameToTypeName
* @param mapFromCategoricalTypeNameToSizeString
*/
private void runTestWithFactorizationOption(
boolean useFactorization,
Expression queryExpression,
Expression evidence,
Expression expected,
boolean isBayesianNetwork,
List<Expression> factors,
Map<String, String> mapFromRandomVariableNameToTypeName,
Map<String, String> mapFromNonUniquelyNamedConstantNameToTypeName,
Map<String, String> mapFromUniquelyNamedConstantNameToTypeName,
Map<String, String> mapFromCategoricalTypeNameToSizeString,
Collection<Type> additionalTypes) {
InferenceForFactorGraphAndEvidence inferencer;
Expression marginal;
inferencer = new InferenceForFactorGraphAndEvidence(
new ExpressionFactorsAndTypes(
factors,
mapFromRandomVariableNameToTypeName,
mapFromNonUniquelyNamedConstantNameToTypeName,
mapFromUniquelyNamedConstantNameToTypeName,
mapFromCategoricalTypeNameToSizeString,
additionalTypes),
isBayesianNetwork,
evidence,
useFactorization, null);
marginal = inferencer.solve(queryExpression);
TrueContext context = new TrueContext();
marginal = Expressions.roundToAGivenPrecision(marginal, 9, context);
expected = Expressions.roundToAGivenPrecision(expected, 9, context);
if (expected.equals(marginal)) {
// Ok!
}
// check if they are not identical, but equivalent expressions
else if (inferencer.evaluate(apply(MINUS, expected, marginal)).equals(ZERO)) { // first attempt was to compare with equality, but this requires a more complete test of equality theory literals to exclude such a complex equality from being considered a literal, which is much more expensive
// Ok!
}
else {
throw new AssertionError("expected:<" + expected + "> but was:<" + marginal + ">, which is not even equivalent.");
}
// Not working yet, need to debug
// Expression negationMarginal;
// negationMarginal = inferencer.solve(Not.make(queryExpression));
// negationMarginal = Expressions.roundToAGivenPrecision(negationMarginal, 9, context);
// expected = inferencer.evaluate(parse(negationMarginal + " = 1 - " + marginal));
// assertEquals(expected, TRUE);
}
@Test
public void simplifyTest() {
// The definitions of types
mapFromCategoricalTypeNameToSizeString = Util.map(
"People", "1000",
"Boolean", "2");
// The definitions of variables
mapFromRandomVariableNameToTypeName = Util.map(
"lucky", "Boolean",
"winner", "People"
);
mapFromNonUniquelyNamedConstantNameToTypeName = Util.map();
mapFromUniquelyNamedConstantNameToTypeName = Util.map("rodrigo", "People");
isBayesianNetwork = false;
factors = Times.getMultiplicands(parse(""
+ "(if lucky then 1 else 0)*"
+ "(if lucky then if winner = rodrigo then 1 else 0 else 0.5)"));
queryExpression = parse("true or false");
expected = parse("true");
queryExpression = parse("true and false");
expected = parse("false");
queryExpression = parse("1.2 + 1.3 + if rodrigo = rodrigo then 1 else 2");
expected = parse("3.5");
runSimplifyTest();
}
private void runSimplifyTest() {
InferenceForFactorGraphAndEvidence inferencer;
Expression simplification;
inferencer = new InferenceForFactorGraphAndEvidence(
new ExpressionFactorsAndTypes(
factors,
mapFromRandomVariableNameToTypeName,
mapFromNonUniquelyNamedConstantNameToTypeName,
mapFromUniquelyNamedConstantNameToTypeName,
mapFromCategoricalTypeNameToSizeString,
list()),
isBayesianNetwork,
evidence,
true, null);
simplification = inferencer.simplify(queryExpression);
assertEquals(expected, simplification);
}
}