use of com.sri.ai.grinder.sgdpllt.theory.linearrealarithmetic.LinearRealArithmeticTheory in project aic-expresso by aic-sri-international.
the class ExpressionStepSolverToLiteralSplitterStepSolverAdapterTest method testLinearRealArithmeticTheoryWithRandomDisjunctiveFormulas.
@Ignore("Random generation of linear real arithmetic not yet implemented")
@Test
public void testLinearRealArithmeticTheoryWithRandomDisjunctiveFormulas() {
TheoryTestingSupport theoryTestingSupport = TheoryTestingSupport.make(makeRandom(), new LinearRealArithmeticTheory(true, true));
extendTestingVaribles("X", theoryTestingSupport, "S", "T", "U", "V", "W");
runRandomDisjunctiveFormulasTest(theoryTestingSupport);
}
use of com.sri.ai.grinder.sgdpllt.theory.linearrealarithmetic.LinearRealArithmeticTheory in project aic-expresso by aic-sri-international.
the class ExpressoAPIExamples method main.
public static void main(String[] args) {
// Symbols are expressions representing Java values, such as a string,
// a number, a boolean, and even any other objects (Expressions themselves will throw an error, though, to prevent common mistakes)
Expression a = DefaultSymbol.createSymbol("a");
Expression ten = DefaultSymbol.createSymbol(10);
Expression trueValue = DefaultSymbol.createSymbol(true);
Expression object = DefaultSymbol.createSymbol(Car.ferrari);
// Below, we use Util.println to avoid having to write System.out.println.
// Util has lots and lots and lots of very useful methods that eliminate boring Java chores.
// We definitely recommend studying it carefully!
// To easily write just "println" and have it work, write "println" and use Ctrl-1 to be offered the option
// of statically importing Util.println.
// You can statically import an identifier in Eclipse by placing the cursor on it and pressing Shift-Ctrl-M in Windows.
println("a : " + a);
println("ten : " + ten);
println("trueValue: " + trueValue);
println("object : " + object);
// It is easier to remember to make symbols using Expressions.makeSymbol:
// 'Expressions' is a class with lots of useful static methods for working with expressions.
// This of it as the counterpart of 'Util', but for expressions.
// Having many useful expression classes in a single place makes it easier to remember them and access them through code completion.
// As with 'Util', we often import its methods statically.
a = makeSymbol("a");
ten = makeSymbol(10);
trueValue = makeSymbol(true);
object = makeSymbol(Car.ferrari);
println("a : " + a);
println("ten : " + ten);
println("trueValue: " + trueValue);
println("object : " + object);
// The second most important type of expressions are function applications.
// They consist of a functor (an expression representing a function, typically a symbol) applied to zero or more arguments:
Expression f = makeSymbol("f");
Expression g = makeSymbol("g");
Expression fATen = new DefaultFunctionApplication(f, list(a, ten));
Expression gOnNothing = new DefaultFunctionApplication(g, list());
println("function f applied to a and ten: " + fATen);
println("function g applied to nothing: " + gOnNothing);
// It is much easier to use Expressions.apply:
fATen = apply(f, a, ten);
gOnNothing = apply(g);
println("function f applied to a and ten: " + fATen);
println("function g applied to nothing: " + gOnNothing);
// Naturally, function applications can be applied to any expression, including other function applications:
Expression gFATen = apply(g, apply(f, a, ten));
println("function g applied to function f applied to a and ten: " + gFATen);
// If we do not create symbols for Java values, apply does it automatically for us:
gFATen = apply("g", apply("f", "a", 10));
println("function g applied to function f applied to a and ten: " + gFATen);
// Some operators are output in special infix notation for readability:
// again not creating symbols first
Expression twoPlusTwoPlusThree = apply("+", 2, 2, 3);
println("two plus two plus three: " + twoPlusTwoPlusThree);
Expression arithmetic1 = apply("*", 2, apply("+", 2, 3));
Expression arithmetic2 = apply("+", 2, apply("*", 2, 3));
println("Arithmetic gets printed while respecting usual precedence rules by using parentheses: " + arithmetic1);
println("Arithmetic gets printed while respecting usual precedence rules by using parentheses: " + arithmetic2);
// Same for logic:
Expression logic1 = apply("and", "p", apply("or", "q", "r"));
Expression logic2 = apply("or", "p", apply("and", "q", "r"));
println("Same for logic: " + logic1);
println("Same for logic: " + logic2);
// It is not good practice to use separate strings for referring to the same operators.
// In the future, we may decide to change the string associated to an operator
// and have that string used in many places would make that hard to effect.
// FunctorConstants is a class with lots of static fields for operator strings:
arithmetic1 = apply(FunctorConstants.TIMES, 2, apply(FunctorConstants.PLUS, 2, 3));
logic1 = apply(FunctorConstants.AND, "p", apply(FunctorConstants.OR, "q", "r"));
// Functor constants can also be statically imported:
arithmetic1 = apply(TIMES, 2, apply(PLUS, 2, 3));
logic1 = apply(AND, "p", apply(OR, "q", "r"));
// We can access the functor and arguments of a function application:
println("The functor of " + gFATen + " is " + gFATen.getFunctor());
println("The second argument of " + fATen + " is " + fATen.get(1));
// returns a List<Expression>
println("All arguments of " + fATen + " are " + fATen.getArguments());
// We can also set new functors or arguments.
// IMPORTANT: expressions are IMMUTABLE, so this creates a new expression,
// although it does re-use the unchanged parts.
Expression newArgument = gFATen.set(0, a);
println("Changed first argument of " + gFATen + " to " + a + " and obtained " + newArgument);
println("Original expression continues the same, since they are immutable: " + gFATen);
// getFunctor returns a symbol, so to check if it is, for example, "f", we need
// to write expression.getFunctor().equals(makeSymbol("f"))
// which is too long.
// Instead, we can use 'hasFunctor'
println(fATen + " has functor \"f\": " + fATen.hasFunctor("f"));
// Finally, we can parse expressions for strings.
// BUT we should never use that to construct expressions if we have the sub-expressions already represented as Java objects.
// For example, don't do this: parse("f(" + a + ", " + b + ")");
// Instead, use apply("f", a, b);
ten = parse("10");
trueValue = parse("true");
fATen = parse("f(a,10)");
arithmetic1 = parse("2*(2 + 3)");
arithmetic2 = parse("2+(2 * 3)");
println(ten);
println(trueValue);
println(fATen);
println(arithmetic1);
println(arithmetic2);
// Another important type of expression is sets.
// There are two dimensions for sets: they can be uni- or multi-sets, and they can be extensionally or intensionally defined.
//
// A uni-set has at most one instance of each element in it. This is the typical mathematical set.
// A multi-set may have multiple instances of the same element in it.
// For example, the multi-set {1,2,2,3} is distinct from multi-set {1,2,2,2,3}.
// In Expresso, we use double-brackets for denoting multi-sets: {{ 1, 2, 2, 3 }}.
// {{ }} denotes the empty multi-set.
// The singleton uni-set with an empty set in it is denoted { {} }.
// You need a space between the brackets to avoid them being parsed as a double bracket.
//
// An extensionally defined set is an explicit enumeration of its elements: {1, 2, 3}, {{1, 2, 2, 3}}, {}, {{ }}.
// An intensionally defined set is defined by a condition: { (on I in Integer) I^2 : I > 3 and I <= 100 }, for example,
// which is equal to { 16, 25, 36, ..., 10000 }.
// The general form of an intensionally defined set (or, less precisely but more succinctly, an intensional set) is
// { (on Index1 in Index1Domain, Index2 in Index2Domain, ..., Index_n in Index_nDomain) Head : Condition }
// We can also have intensionally defined multi-sets using double brackets.
// Here are some ways of constructing sets:
a = makeSymbol("a");
Expression b = makeSymbol("b");
Expression c = makeSymbol("c");
Expression d = makeSymbol("d");
Expression extensionalUniSet = ExtensionalSets.makeUniSet(a, b, c, d);
Expression extensionalMultiSet = ExtensionalSets.makeMultiSet(a, b, c, d);
println(extensionalUniSet);
println(extensionalMultiSet);
// Creating an intensionally defined set programmatically (as opposed to parsing a string description of it)
// is a bit of work (this will be shown below).
// Here's an example of parsing one:
Expression intensionalUniSet = parse("{ ( on P in People, F in Foods ) eats(P, F) : not (P = Rodrigo and F = shrimp) }");
println(intensionalUniSet);
// Here's how to do it from scratch, but see next the way we typically actually do it.
Expression p = makeSymbol("P");
Expression people = makeSymbol("People");
f = makeSymbol("F");
Expression foods = makeSymbol("Foods");
IndexExpressionsSet indices = new ExtensionalIndexExpressionsSet(apply(IN, p, people), apply(IN, f, foods));
// The "extensional" in ExtensionalIndexExpressionsSet means that the list/set of indices is extensionally defined,
// even though they will be the indices of an intensionally defined set.
intensionalUniSet = // IntensionalSet.intensionalUniSet, or simply intensionalUniSet, also works
IntensionalSet.makeUniSet(indices, apply("eats", p, f), apply(NOT, apply(AND, Equality.make(p, "Rodrigo"), Equality.make(f, "shrimp"))));
// Note that Equality.make(p, "Rodrigo") is the same as apply(FunctorConstants.EQUAL, p, "Rodrigo").
// We often have 'make' methods for many operators: And.make, Or.make and so on.
// packages in com.sri.ai.expresso.grinder.sgdpllt.library have many such operator-specific classes.
println(intensionalUniSet);
// When writing code on sets, we typically are modifying an existing set expression, so we can re-use its parts,
// by using special part-replacement methods.
// This requires the variable to implement the IntensionalSet interface, though.
// IMPORTANT: expressions are IMMUTABLE, so setCondition and other part-replacement methods return a NEW expression,
// although the parts not replaced are re-used.
IntensionalSet intensionalSetCast = (IntensionalSet) intensionalUniSet;
Expression noCondition = intensionalSetCast.setCondition(makeSymbol(true));
println("Set with no condition: " + noCondition);
Expression headSaysLoveInsteadOfEats = intensionalSetCast.setHead(apply("loves", p, f));
println("Set with new head: " + headSaysLoveInsteadOfEats);
Expression withNewIndices = intensionalSetCast.setIndexExpressions(new ExtensionalIndexExpressionsSet(apply(IN, p, people), apply(IN, f, foods), apply(IN, "D", "Days")));
println("Set with new indices: " + withNewIndices);
// summations and products are just function applications of FunctorConstants.SUM and FunctorConstants.PRODUCT on intensional multi-sets.
// sum( {{ (on Indices) Head : Condition }} ) represents the summation (in Latex notation) sum_{Indices : Condition} Head
Expression summation = apply(SUM, intensionalSetCast);
println(summation);
Expression product = apply(PRODUCT, intensionalSetCast);
println(product);
///// Evaluating expressions
// The above code shows how to deal with the syntax of expressions.
// Evaluating expressions requires knowing about the semantics, that is, to what functions each operator corresponds to ("+" to addition, etc).
// This is provided by a theory, which for now it suffices to know is a collection of methods for evaluating expressions
// according to an interpretation to some symbols.
Theory theory = new CompoundTheory(new EqualityTheory(false, true), new DifferenceArithmeticTheory(false, false), new LinearRealArithmeticTheory(false, false), new TupleTheory(), new PropositionalTheory());
// Because this evaluation is symbolic, evaluated expressions may involve free variables.
// In this case, the result of the evaluation will be a simplified expression that
// is equivalent to the original expression for all possible assignments to the free variables.
// For example, X + 0*Y is evaluate to X because, for any assignment to (X,Y), X + 0*Y = X.
// true context: all assignments to free variables are of interest
Context context = new TrueContext(theory);
// We will later see how we can use contexts that restrict the free variable assignments of interest.
// Now that we have a theory and a context, we can evaluate expressions:
println("1 + 0*X + 1 = " + theory.evaluate(parse("1 + 1"), context));
evaluate(new String[] { "1 + 1", "2", "X + 1 + 1", "X + 2", "sum({{ (on I in 1..10) I }})", "55", "product({{ (on I in 1..5) 2 : I != 3 and I != 5 }})", "8" }, theory, context);
// now let us assume we have a free variable J which is an integer
// Contexts are, like expressions, also IMMUTABLE:
Context context2 = context.extendWithSymbolsAndTypes("J", "Integer");
// However, here we just want to use the same variable 'context' all along, so we keep the updated context in it:
context = context2;
// Because we store the reference to the modified context in the same variable, we lose the reference to the original one,
// but, if we wanted, we could keep contexts in a stack, for example,
// so that we could always easily revert back to a previous context if needed.
evaluate(new String[] { "X + 1 + 1 + J", "X + 2 + J", "sum({{ (on I in 1..10) I : I != J }})", "if J > 0 then if J <= 10 then -1 * J + 55 else 55 else 55" }, theory, context);
// now let us assume we have a free variable J which is an integer
// The context is also a boolean formula (a constraint)
// Current, its value is "true", but we can conjoin it with a literal J < 0
context = context.conjoin(parse("J < 0"));
evaluate(new String[] { "J < 1", "true", // J is irrelevant because it is out of the range of I
"sum({{ (on I in 1..1000) I : I != J }})", // J is irrelevant because it is out of the range of I
"500500" }, theory, context);
// we now add another symbol and constraint
context = context.extendWithSymbolsAndTypes("K", "Integer");
context = context.conjoin(parse("K > 0"));
evaluate(new String[] { "J < K", "true" }, theory, context);
// Obtaining all free variables in an expression.
// In order to obtain all free variables appearing in an expression
// (and therefore excluding quantified variables (for all X, there exists X) and set indices ({ (on Z in Real) Z }))
// we must traverse the expression and select its sub-expressions that are variables.
// However, we need to know what a variable is.
// It is not enough to say that any symbol is a variable, because "1" and "true" are symbols, but not variables.
// It is not enough to say that any symbols that is an identifier (starting with an alphabet letter) is a variable,
// because we may have uniquely named constants such as "john" and "bob" that are not to be treated as variables
// (we want "john = bob" to be evaluated to "false", and if they were variable, this would not happen.
// The way Expresso deals with this question is by letting the user define a predicate in the context that
// encoded what a uniquely named constant is, and considering any other symbol to be considered a variable.
// By default, Expresso follows the Prolog convention of capitalized variables: X is a variable, x is not.
// Note how this takes "Real" to be a variable!
context = new TrueContext();
Expression expression = parse("X + f(g(x, Y, 1, true, false, 10, bob, john, there exists Z in Real : 10, { (on W in Real) 1 } ))");
Set<Expression> variablesInExpression = Expressions.freeVariables(expression, context);
// outputs [X, Y]
println("variables in " + expression + " by Prolog standard: " + variablesInExpression);
// More recently, we have adopted the practice of not caring about capitalization.
// This means that we may, for example, defined uniquely named constants to be any symbols that are not in a given set of variables.
Set<Expression> allVariables = set(parse("x"), parse("X"), parse("Y"), parse("Z"), parse("W"));
context = context.setIsUniquelyNamedConstantPredicate(new UniquelyNamedConstantAreAllSymbolsNotIn(allVariables));
variablesInExpression = Expressions.freeVariables(expression, context);
println("variables in " + expression + " if all variables is " + allVariables + ": " + // outputs [x, X, Y]
variablesInExpression);
// Sometimes, it is useful to replace subexpressions in a given expression by another subexpression:
expression = parse("f(f(f(X))) + X");
Expression valueOfX = parse("10");
Expression replacementOfFirstOccurrenceOnly = expression.replaceFirstOccurrence(parse("X"), valueOfX, context);
println("Replacing only the first occurrence of X by its value gives " + replacementOfFirstOccurrenceOnly);
Expression replacementOfAllOccurrences = expression.replaceAllOccurrences(parse("X"), valueOfX, context);
println("Replacing all occurrences of X by its value gives " + replacementOfAllOccurrences);
// There are a LOT of variants of these functions in Expression (not Expressions),
// including some very flexible ones that allow the user to provide a function for determining the replacement.
// BUG: need to debug
// Here's how to decide if a point is in the convex hull of other two points:
Context convexityContext = context.extendWithSymbolsAndTypes("p", "Real", "p1", "Real", "p2", "Real");
//convexityContext = convexityContext.conjoin(parse("p = 4"));
//convexityContext = convexityContext.conjoin(parse("p1 = 3"));
//convexityContext = convexityContext.conjoin(parse("p2 = 5"));
Expression isInConvexHull = parse("there exists c1 in Real : there exists c2 in Real : " + "0 <= c1 and c1 <= 1 and 0 <= c2 and c2 <= 1 and 4 = c1*3 + c2*5");
Expression result = theory.evaluate(isInConvexHull, convexityContext);
println("4 is in the convex hull of 3 and 5: " + result);
}
use of com.sri.ai.grinder.sgdpllt.theory.linearrealarithmetic.LinearRealArithmeticTheory in project aic-expresso by aic-sri-international.
the class SymbolicShell method main.
public static void main(String[] args) {
CompoundTheory theory = new CompoundTheory(new EqualityTheory(false, true), new DifferenceArithmeticTheory(false, false), new LinearRealArithmeticTheory(false, false), new TupleTheory(), new PropositionalTheory());
Context context = new TrueContext(theory);
context = context.add(BOOLEAN_TYPE);
context = context.add(new Categorical("People", 1000000, makeSymbol("ann"), makeSymbol("bob"), makeSymbol("ciaran")));
context = context.add(new IntegerInterval("Integer"));
context = context.add(new RealInterval("Real"));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("P"), makeSymbol("Boolean")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("Q"), makeSymbol("Boolean")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("R"), makeSymbol("Boolean")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("S"), makeSymbol("Boolean")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("C"), makeSymbol("People")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("D"), makeSymbol("People")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("E"), makeSymbol("People")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("I"), makeSymbol("Integer")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("J"), makeSymbol("Integer")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("K"), makeSymbol("Integer")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("X"), makeSymbol("Real")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("Y"), makeSymbol("Real")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("Z"), makeSymbol("Real")));
context = context.registerAdditionalSymbolsAndTypes(map(makeSymbol("T"), parse("(1..5 x 1..5)")));
ConsoleIterator consoleIterator = getConsole(args);
help(consoleIterator);
Collection<String> examples = list("sum({{ (on C in People) 3 }})", "sum({{ (on C in People) 3 : C != D }})", "product({{ (on C in People) 3 : C != D }})", "| {{ (on C in People) 3 : C != D }} |", "| { (on C in People) tuple(C) : C != D } |", "max({{ (on C in People) 3 : C != D }})", "sum({{ (on C in People, D in People) 3 : C != D }})", "sum({{ (on C in People) 3 : C != D and C != ann }})", "sum({{ (on C in People, P in Boolean) 3 : C != ann }})", "sum({{ (on C in People, P in Boolean) 3 : C != ann and not P }})", "sum({{ (on C in People, D in People) if C = ann and D != bob then 2 else 0 : for all E in People : E = ann => C = E }})", "sum({{ (on I in 1..100) I }})", "sum({{ (on I in 1..100) I : I != 3 and I != 5 and I != 500 }})", "sum({{ (on I in 1..100) I : I != J and I != 5 and I != 500 }})", "sum({{ (on I in 1..100) (I - J)^2 }})", "sum({{ (on I in 1..100) if I != K then (I - J)^2 else 0 }})", "sum({{ (on I in 1..100) I : I >= 3 and I < 21 }})", "sum({{ (on I in 1..100) I : I > J and I < 5 and I < 500 }})", "sum({{ (on I in 1..100) (I - J)^2 : I < 50 }})", "sum({{ (on X in [0;100]) 1 }})", "sum({{ (on X in [0;100[) 1 }})", "sum({{ (on X in ]0;100]) 1 }})", "sum({{ (on X in [0;100]) Y }})", "sum({{ (on X in [0;100]) X }})", "sum({{ (on X in [0;100]) X^2 }})", "sum({{ (on X in [0;100]) X + Y }})", "sum({{ (on X in [0;100]) 1 : Y < X and X < Z}})", "sum({{ (on X in Real) 1 : 0 <= X and X <= 100 and Y < X and X < Z}})", "for all X in Real : X > 0 or X <= 0", "for all X in ]0;10] : X > 0", "for all X in [0;10] : X > 0", "| X in 1..10 : X < 4 or X > 8 |", "| X in 1..10, Y in 3..5 : (X < 4 or X > 8) and Y != 5 |", "sum( {{ (on T in (1..4 x 1..4)) 10 }})", "sum( {{ (on T in (1..4 x 1..4)) 10 : T != (2, 3) }})", "sum( {{ (on T in (1..4 x 1..4)) 10 : T != (I, J) }})", "sum( {{ (on T in (1..4 x 1..4)) 10 : get(T, 1) != 2 }})");
for (String example : examples) {
consoleIterator.getOutputWriter().println(consoleIterator.getPrompt() + example);
interpretedInputParsedAsExpression(consoleIterator, theory, example, context);
consoleIterator.getOutputWriter().println("\n");
}
while (consoleIterator.hasNext()) {
String input = consoleIterator.next();
if (input.equals("")) {
consoleIterator.getOutputWriter().println();
} else if (input.startsWith("show")) {
consoleIterator.getOutputWriter().println("\n" + join(mapIntoList(context.getSymbolsAndTypes().entrySet(), e -> e.getKey() + ": " + e.getValue()), ", ") + "\n");
} else if (input.equals("debug")) {
debug = !debug;
consoleIterator.getOutputWriter().println("\nDebug toggled to " + debug + "\n");
} else if (input.equals("help")) {
help(consoleIterator);
} else {
context = interpretedInputParsedAsExpression(consoleIterator, theory, input, context);
}
}
consoleIterator.getOutputWriter().println("\nGoodbye.");
}
use of com.sri.ai.grinder.sgdpllt.theory.linearrealarithmetic.LinearRealArithmeticTheory in project aic-expresso by aic-sri-international.
the class UnificationStepSolverTest method compundTest.
@Test
public void compundTest() {
TheoryTestingSupport theoryTestingSupport = TheoryTestingSupport.make(seededRandom, new CompoundTheory(new EqualityTheory(false, true), new DifferenceArithmeticTheory(false, true), new LinearRealArithmeticTheory(false, true), new PropositionalTheory()));
// NOTE: passing explicit FunctionTypes will prevent the general variables' argument types being randomly changed.
theoryTestingSupport.setVariableNamesAndTypesForTesting(map("P", BOOLEAN_TYPE, "Q", BOOLEAN_TYPE, "R", BOOLEAN_TYPE, "unary_prop", new FunctionType(BOOLEAN_TYPE, BOOLEAN_TYPE), "binary_prop", new FunctionType(BOOLEAN_TYPE, BOOLEAN_TYPE, BOOLEAN_TYPE), "S", TESTING_CATEGORICAL_TYPE, "T", TESTING_CATEGORICAL_TYPE, "U", TESTING_CATEGORICAL_TYPE, "unary_eq", new FunctionType(TESTING_CATEGORICAL_TYPE, TESTING_CATEGORICAL_TYPE), "binary_eq", new FunctionType(TESTING_CATEGORICAL_TYPE, TESTING_CATEGORICAL_TYPE, TESTING_CATEGORICAL_TYPE), "I", TESTING_INTEGER_INTERVAL_TYPE, "J", TESTING_INTEGER_INTERVAL_TYPE, "K", TESTING_INTEGER_INTERVAL_TYPE, "unary_dar", new FunctionType(TESTING_INTEGER_INTERVAL_TYPE, TESTING_INTEGER_INTERVAL_TYPE), "binary_dar", new FunctionType(TESTING_INTEGER_INTERVAL_TYPE, TESTING_INTEGER_INTERVAL_TYPE, TESTING_INTEGER_INTERVAL_TYPE), "X", TESTING_REAL_INTERVAL_TYPE, "Y", TESTING_REAL_INTERVAL_TYPE, "Z", TESTING_REAL_INTERVAL_TYPE, "unary_lra", new FunctionType(TESTING_REAL_INTERVAL_TYPE, TESTING_REAL_INTERVAL_TYPE), "binary_lra", new FunctionType(TESTING_REAL_INTERVAL_TYPE, TESTING_REAL_INTERVAL_TYPE, TESTING_REAL_INTERVAL_TYPE)));
Context rootContext = theoryTestingSupport.makeContextWithTestingInformation();
UnificationStepSolver unificationStepSolver = new UnificationStepSolver(parse("unary_prop(P)"), parse("unary_prop(P)"));
StepSolver.Step<Boolean> step = unificationStepSolver.step(rootContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_prop(P)"), parse("unary_prop(Q)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("P = Q"), step.getSplitter());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).itDepends());
Assert.assertEquals(true, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).getValue());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).itDepends());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).getValue());
Context localTestContext = rootContext.conjoinWithConjunctiveClause(parse("P and not Q"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_prop(P)"), parse("unary_prop(true)"));
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("P"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("not P"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("binary_prop(P, unary_prop(P))"), parse("binary_prop(unary_prop(Q), Q)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("P = unary_prop(Q)"), step.getSplitter());
//
//
unificationStepSolver = new UnificationStepSolver(parse("unary_eq(S)"), parse("unary_eq(S)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_eq(S)"), parse("unary_eq(T)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("S = T"), step.getSplitter());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).itDepends());
Assert.assertEquals(true, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).getValue());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).itDepends());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).getValue());
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("S = a and T = b"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_eq(S)"), parse("unary_eq(a)"));
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("S = a"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("S = b"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("binary_eq(S, unary_eq(S))"), parse("binary_eq(unary_eq(T), T)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("S = unary_eq(T)"), step.getSplitter());
//
//
unificationStepSolver = new UnificationStepSolver(parse("unary_dar(I)"), parse("unary_dar(I)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_dar(I)"), parse("unary_dar(J)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("I = J"), step.getSplitter());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).itDepends());
Assert.assertEquals(true, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).getValue());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).itDepends());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).getValue());
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("I = 0 and J = 1"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_dar(I)"), parse("unary_dar(0)"));
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("I = 0"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("I = 1"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("binary_dar(I, unary_dar(I))"), parse("binary_dar(unary_dar(J), J)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("I = unary_dar(J)"), step.getSplitter());
//
//
unificationStepSolver = new UnificationStepSolver(parse("unary_lra(X)"), parse("unary_lra(X)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_lra(X)"), parse("unary_lra(Y)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("X = Y"), step.getSplitter());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).itDepends());
Assert.assertEquals(true, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).getValue());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).itDepends());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).getValue());
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("X = 0 and Y = 1"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_lra(X)"), parse("unary_lra(0)"));
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("X = 0"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("X = 1"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("binary_lra(X, unary_lra(X))"), parse("binary_lra(unary_lra(Y), Y)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("X = unary_lra(Y)"), step.getSplitter());
}
use of com.sri.ai.grinder.sgdpllt.theory.linearrealarithmetic.LinearRealArithmeticTheory in project aic-expresso by aic-sri-international.
the class UnificationStepSolverTest method linearRealArithmeticTest.
@Test
public void linearRealArithmeticTest() {
TheoryTestingSupport theoryTestingSupport = TheoryTestingSupport.make(seededRandom, new LinearRealArithmeticTheory(true, true));
// NOTE: passing explicit FunctionTypes will prevent the general variables' argument types being randomly changed.
theoryTestingSupport.setVariableNamesAndTypesForTesting(map("X", TESTING_REAL_INTERVAL_TYPE, "Y", TESTING_REAL_INTERVAL_TYPE, "Z", TESTING_REAL_INTERVAL_TYPE, "unary_lra", new FunctionType(TESTING_REAL_INTERVAL_TYPE, TESTING_REAL_INTERVAL_TYPE), "binary_lra", new FunctionType(TESTING_REAL_INTERVAL_TYPE, TESTING_REAL_INTERVAL_TYPE, TESTING_REAL_INTERVAL_TYPE)));
Context rootContext = theoryTestingSupport.makeContextWithTestingInformation();
UnificationStepSolver unificationStepSolver = new UnificationStepSolver(parse("unary_lra(X)"), parse("unary_lra(X)"));
StepSolver.Step<Boolean> step = unificationStepSolver.step(rootContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_lra(X)"), parse("unary_lra(Y)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("X = Y"), step.getSplitter());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).itDepends());
Assert.assertEquals(true, step.getStepSolverForWhenSplitterIsTrue().step(rootContext).getValue());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).itDepends());
Assert.assertEquals(false, step.getStepSolverForWhenSplitterIsFalse().step(rootContext).getValue());
Context localTestContext = rootContext.conjoinWithConjunctiveClause(parse("X = 0 and Y = 1"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("unary_lra(X)"), parse("unary_lra(0)"));
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("X = 0"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(true, step.getValue());
localTestContext = rootContext.conjoinWithConjunctiveClause(parse("X = 1"), rootContext);
step = unificationStepSolver.step(localTestContext);
Assert.assertEquals(false, step.itDepends());
Assert.assertEquals(false, step.getValue());
unificationStepSolver = new UnificationStepSolver(parse("binary_lra(X, unary_lra(X))"), parse("binary_lra(unary_lra(Y), Y)"));
step = unificationStepSolver.step(rootContext);
Assert.assertEquals(true, step.itDepends());
Assert.assertEquals(Expressions.parse("X = unary_lra(Y)"), step.getSplitter());
}
Aggregations