SQL: Optimizer tests (elastic/x-pack-elasticsearch#3518)
Unit tests for the Optimizer Disabled for now RemoveDuplicateFunctions until elastic/x-pack-elasticsearch#3527 gets resolved Original commit: elastic/x-pack-elasticsearch@3224e3937f
This commit is contained in:
parent
c204cc0aa3
commit
2870312320
|
@ -126,8 +126,11 @@ public class Optimizer extends RuleExecutor<LogicalPlan> {
|
||||||
new PruneFilters(),
|
new PruneFilters(),
|
||||||
new PruneOrderBy(),
|
new PruneOrderBy(),
|
||||||
new PruneOrderByNestedFields(),
|
new PruneOrderByNestedFields(),
|
||||||
new PruneCast(),
|
new PruneCast()
|
||||||
new PruneDuplicateFunctions()
|
// requires changes in the folding
|
||||||
|
// since the exact same function, with the same ID can appear in multiple places
|
||||||
|
// see https://github.com/elastic/x-pack-elasticsearch/issues/3527
|
||||||
|
//new PruneDuplicateFunctions()
|
||||||
);
|
);
|
||||||
|
|
||||||
Batch local = new Batch("Skip Elasticsearch",
|
Batch local = new Batch("Skip Elasticsearch",
|
||||||
|
@ -914,6 +917,7 @@ public class Optimizer extends RuleExecutor<LogicalPlan> {
|
||||||
return seenFunction;
|
return seenFunction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
seen.add(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return exp;
|
return exp;
|
||||||
|
@ -974,7 +978,7 @@ public class Optimizer extends RuleExecutor<LogicalPlan> {
|
||||||
|
|
||||||
|
|
||||||
// replace attributes of foldable expressions with the foldable trees
|
// replace attributes of foldable expressions with the foldable trees
|
||||||
// SELECT 5 a, a + 3, ...
|
// SELECT 5 a, 3 + 2 b ... WHERE a < 10 ORDER BY b
|
||||||
|
|
||||||
static class ReplaceFoldableAttributes extends Rule<LogicalPlan, LogicalPlan> {
|
static class ReplaceFoldableAttributes extends Rule<LogicalPlan, LogicalPlan> {
|
||||||
|
|
||||||
|
@ -1054,11 +1058,13 @@ public class Optimizer extends RuleExecutor<LogicalPlan> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Expression rule(Expression e) {
|
protected Expression rule(Expression e) {
|
||||||
// preserve aliases
|
// handle aliases to avoid double aliasing of functions
|
||||||
|
// alias points to function which gets folded and wrapped in an alias that is
|
||||||
|
// aliases
|
||||||
if (e instanceof Alias) {
|
if (e instanceof Alias) {
|
||||||
Alias a = (Alias) e;
|
Alias a = (Alias) e;
|
||||||
Expression fold = fold(a.child());
|
Expression fold = fold(a.child());
|
||||||
if (fold != e) {
|
if (fold != a.child()) {
|
||||||
return new Alias(a.location(), a.name(), null, fold, a.id());
|
return new Alias(a.location(), a.name(), null, fold, a.id());
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License;
|
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
|
||||||
*/
|
|
||||||
package org.elasticsearch.xpack.sql.optimizer;
|
|
||||||
|
|
||||||
import org.elasticsearch.test.ESTestCase;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Literal;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.And;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.Or;
|
|
||||||
import org.elasticsearch.xpack.sql.optimizer.Optimizer.BooleanSimplification;
|
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
|
||||||
import org.elasticsearch.xpack.sql.type.DataType;
|
|
||||||
import org.elasticsearch.xpack.sql.type.DataTypes;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
public class BooleanSimplificationTests extends ESTestCase {
|
|
||||||
|
|
||||||
private static final Expression DUMMY_EXPRESSION = new DummyBooleanExpression(Location.EMPTY, 0);
|
|
||||||
|
|
||||||
private static class DummyBooleanExpression extends Expression {
|
|
||||||
|
|
||||||
private final int id;
|
|
||||||
|
|
||||||
DummyBooleanExpression(Location location, int id) {
|
|
||||||
super(location, Collections.emptyList());
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean nullable() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataType dataType() {
|
|
||||||
return DataTypes.BOOLEAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int h = getClass().hashCode();
|
|
||||||
h = 31 * h + id;
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj == null || getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return id == ((DummyBooleanExpression) obj).id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSimplifyOr() {
|
|
||||||
BooleanSimplification simplification = new BooleanSimplification();
|
|
||||||
|
|
||||||
assertEquals(Literal.TRUE, simplification.rule(new Or(Location.EMPTY, Literal.TRUE, Literal.TRUE)));
|
|
||||||
assertEquals(Literal.TRUE, simplification.rule(new Or(Location.EMPTY, Literal.TRUE, DUMMY_EXPRESSION)));
|
|
||||||
assertEquals(Literal.TRUE, simplification.rule(new Or(Location.EMPTY, DUMMY_EXPRESSION, Literal.TRUE)));
|
|
||||||
|
|
||||||
assertEquals(Literal.FALSE, simplification.rule(new Or(Location.EMPTY, Literal.FALSE, Literal.FALSE)));
|
|
||||||
assertEquals(DUMMY_EXPRESSION, simplification.rule(new Or(Location.EMPTY, Literal.FALSE, DUMMY_EXPRESSION)));
|
|
||||||
assertEquals(DUMMY_EXPRESSION, simplification.rule(new Or(Location.EMPTY, DUMMY_EXPRESSION, Literal.FALSE)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSimplifyAnd() {
|
|
||||||
BooleanSimplification simplification = new BooleanSimplification();
|
|
||||||
|
|
||||||
assertEquals(Literal.TRUE, simplification.rule(new And(Location.EMPTY, Literal.TRUE, Literal.TRUE)));
|
|
||||||
assertEquals(DUMMY_EXPRESSION, simplification.rule(new And(Location.EMPTY, Literal.TRUE, DUMMY_EXPRESSION)));
|
|
||||||
assertEquals(DUMMY_EXPRESSION, simplification.rule(new And(Location.EMPTY, DUMMY_EXPRESSION, Literal.TRUE)));
|
|
||||||
|
|
||||||
assertEquals(Literal.FALSE, simplification.rule(new And(Location.EMPTY, Literal.FALSE, Literal.FALSE)));
|
|
||||||
assertEquals(Literal.FALSE, simplification.rule(new And(Location.EMPTY, Literal.FALSE, DUMMY_EXPRESSION)));
|
|
||||||
assertEquals(Literal.FALSE, simplification.rule(new And(Location.EMPTY, DUMMY_EXPRESSION, Literal.FALSE)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCommonFactorExtraction() {
|
|
||||||
BooleanSimplification simplification = new BooleanSimplification();
|
|
||||||
|
|
||||||
Expression a = new DummyBooleanExpression(Location.EMPTY, 1);
|
|
||||||
Expression b = new DummyBooleanExpression(Location.EMPTY, 2);
|
|
||||||
Expression c = new DummyBooleanExpression(Location.EMPTY, 3);
|
|
||||||
|
|
||||||
Expression actual = new Or(Location.EMPTY, new And(Location.EMPTY, a, b), new And(Location.EMPTY, a, c));
|
|
||||||
Expression expected = new And(Location.EMPTY, a, new Or(Location.EMPTY, b, c));
|
|
||||||
|
|
||||||
assertEquals(expected, simplification.rule(actual));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.xpack.sql.optimizer;
|
||||||
|
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.Alias;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.Expressions;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.Literal;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.NamedExpression;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.Order;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.Order.OrderDirection;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.function.aggregate.AggregateFunction;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.function.aggregate.Count;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.function.scalar.arithmetic.Add;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.And;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.Equals;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.GreaterThan;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.GreaterThanOrEqual;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.LessThan;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.LessThanOrEqual;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.Or;
|
||||||
|
import org.elasticsearch.xpack.sql.optimizer.Optimizer.BinaryComparisonSimplification;
|
||||||
|
import org.elasticsearch.xpack.sql.optimizer.Optimizer.BooleanLiteralsOnTheRight;
|
||||||
|
import org.elasticsearch.xpack.sql.optimizer.Optimizer.BooleanSimplification;
|
||||||
|
import org.elasticsearch.xpack.sql.optimizer.Optimizer.CombineProjections;
|
||||||
|
import org.elasticsearch.xpack.sql.optimizer.Optimizer.ConstantFolding;
|
||||||
|
import org.elasticsearch.xpack.sql.optimizer.Optimizer.PruneDuplicateFunctions;
|
||||||
|
import org.elasticsearch.xpack.sql.optimizer.Optimizer.PruneSubqueryAliases;
|
||||||
|
import org.elasticsearch.xpack.sql.optimizer.Optimizer.ReplaceFoldableAttributes;
|
||||||
|
import org.elasticsearch.xpack.sql.plan.logical.Filter;
|
||||||
|
import org.elasticsearch.xpack.sql.plan.logical.LocalRelation;
|
||||||
|
import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan;
|
||||||
|
import org.elasticsearch.xpack.sql.plan.logical.OrderBy;
|
||||||
|
import org.elasticsearch.xpack.sql.plan.logical.Project;
|
||||||
|
import org.elasticsearch.xpack.sql.plan.logical.SubQueryAlias;
|
||||||
|
import org.elasticsearch.xpack.sql.plan.logical.command.ShowTables;
|
||||||
|
import org.elasticsearch.xpack.sql.session.EmptyExecutable;
|
||||||
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
|
import org.elasticsearch.xpack.sql.type.DataType;
|
||||||
|
import org.elasticsearch.xpack.sql.type.DataTypes;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static org.elasticsearch.xpack.sql.tree.Location.EMPTY;
|
||||||
|
|
||||||
|
public class OptimizerTests extends ESTestCase {
|
||||||
|
|
||||||
|
private static final Expression DUMMY_EXPRESSION = new DummyBooleanExpression(EMPTY, 0);
|
||||||
|
|
||||||
|
private static class DummyBooleanExpression extends Expression {
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
DummyBooleanExpression(Location location, int id) {
|
||||||
|
super(location, Collections.emptyList());
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean nullable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType dataType() {
|
||||||
|
return DataTypes.BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int h = getClass().hashCode();
|
||||||
|
h = 31 * h + id;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return id == ((DummyBooleanExpression) obj).id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LogicalPlan FROM() {
|
||||||
|
return new LocalRelation(EMPTY, new EmptyExecutable(emptyList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Literal L(Object value) {
|
||||||
|
return Literal.of(EMPTY, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPruneSubqueryAliases() {
|
||||||
|
ShowTables s = new ShowTables(EMPTY, null);
|
||||||
|
SubQueryAlias plan = new SubQueryAlias(EMPTY, s, "show");
|
||||||
|
LogicalPlan result = new PruneSubqueryAliases().apply(plan);
|
||||||
|
assertEquals(result, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDuplicateFunctions() {
|
||||||
|
AggregateFunction f1 = new Count(EMPTY, Literal.TRUE, false);
|
||||||
|
AggregateFunction f2 = new Count(EMPTY, Literal.TRUE, false);
|
||||||
|
|
||||||
|
assertTrue(f1.functionEquals(f2));
|
||||||
|
|
||||||
|
Project p = new Project(EMPTY, FROM(), Arrays.asList(f1, f2));
|
||||||
|
LogicalPlan result = new PruneDuplicateFunctions().apply(p);
|
||||||
|
assertTrue(result instanceof Project);
|
||||||
|
List<? extends NamedExpression> projections = ((Project) result).projections();
|
||||||
|
assertEquals(2, projections.size());
|
||||||
|
assertSame(projections.get(0), projections.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCombineProjections() {
|
||||||
|
// a
|
||||||
|
Alias a = new Alias(EMPTY, "a", L(5));
|
||||||
|
// b
|
||||||
|
Alias b = new Alias(EMPTY, "b", L(10));
|
||||||
|
// x -> a
|
||||||
|
Alias x = new Alias(EMPTY, "x", a);
|
||||||
|
|
||||||
|
Project lowerP = new Project(EMPTY, FROM(), asList(a, b));
|
||||||
|
Project upperP = new Project(EMPTY, lowerP, singletonList(x));
|
||||||
|
|
||||||
|
LogicalPlan result = new CombineProjections().apply(upperP);
|
||||||
|
assertNotSame(upperP, result);
|
||||||
|
|
||||||
|
assertTrue(result instanceof Project);
|
||||||
|
Project p = (Project) result;
|
||||||
|
assertEquals(1, p.projections().size());
|
||||||
|
Alias al = (Alias) p.projections().get(0);
|
||||||
|
assertEquals("x", al.name());
|
||||||
|
assertTrue(al.child() instanceof Literal);
|
||||||
|
assertEquals(5, al.child().fold());
|
||||||
|
assertTrue(p.child() instanceof LocalRelation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReplaceFoldableAttributes() {
|
||||||
|
// SELECT 5 a, 10 b FROM foo WHERE a < 10 ORDER BY b
|
||||||
|
|
||||||
|
// a
|
||||||
|
Alias a = new Alias(EMPTY, "a", L(5));
|
||||||
|
// b
|
||||||
|
Alias b = new Alias(EMPTY, "b", L(10));
|
||||||
|
// WHERE a < 10
|
||||||
|
LogicalPlan p = new Filter(EMPTY, FROM(), new LessThan(EMPTY, a, L(10)));
|
||||||
|
// SELECT
|
||||||
|
p = new Project(EMPTY, p, Arrays.asList(a, b));
|
||||||
|
// ORDER BY
|
||||||
|
p = new OrderBy(EMPTY, p, singletonList(new Order(EMPTY, b, OrderDirection.ASC)));
|
||||||
|
|
||||||
|
LogicalPlan result = new ReplaceFoldableAttributes().apply(p);
|
||||||
|
assertNotSame(p, result);
|
||||||
|
|
||||||
|
// ORDER BY b -> ORDER BY 10
|
||||||
|
assertTrue(result instanceof OrderBy);
|
||||||
|
OrderBy o = (OrderBy) result;
|
||||||
|
assertEquals(1, o.order().size());
|
||||||
|
Expression oe = o.order().get(0).child();
|
||||||
|
assertTrue(oe instanceof Literal);
|
||||||
|
assertEquals(10, oe.fold());
|
||||||
|
|
||||||
|
// WHERE a < 10
|
||||||
|
assertTrue(o.child() instanceof Project);
|
||||||
|
Project pj = (Project) o.child();
|
||||||
|
assertTrue(pj.child() instanceof Filter);
|
||||||
|
Filter f = (Filter) pj.child();
|
||||||
|
assertTrue(f.condition() instanceof LessThan);
|
||||||
|
LessThan lt = (LessThan) f.condition();
|
||||||
|
assertTrue(lt.left() instanceof Literal);
|
||||||
|
assertTrue(lt.right() instanceof Literal);
|
||||||
|
assertEquals(5, lt.left().fold());
|
||||||
|
assertEquals(10, lt.right().fold());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConstantFolding() {
|
||||||
|
Expression exp = new Add(EMPTY, L(2), L(3));
|
||||||
|
|
||||||
|
assertTrue(exp.foldable());
|
||||||
|
assertTrue(exp instanceof NamedExpression);
|
||||||
|
String n = Expressions.name(exp);
|
||||||
|
|
||||||
|
Expression result = new ConstantFolding().rule(exp);
|
||||||
|
assertTrue(result instanceof Alias);
|
||||||
|
assertEquals(n, Expressions.name(result));
|
||||||
|
Expression c = ((Alias) result).child();
|
||||||
|
assertTrue(c instanceof Literal);
|
||||||
|
assertEquals(5, ((Literal) c).value());
|
||||||
|
|
||||||
|
// check now with an alias
|
||||||
|
result = new ConstantFolding().rule(new Alias(EMPTY, "a", exp));
|
||||||
|
assertTrue(result instanceof Alias);
|
||||||
|
assertEquals("a", Expressions.name(result));
|
||||||
|
c = ((Alias) result).child();
|
||||||
|
assertTrue(c instanceof Literal);
|
||||||
|
assertEquals(5, ((Literal) c).value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testBinaryComparisonSimplification() {
|
||||||
|
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new Equals(EMPTY, L(5), L(5))));
|
||||||
|
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new GreaterThanOrEqual(EMPTY, L(5), L(5))));
|
||||||
|
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new LessThanOrEqual(EMPTY, L(5), L(5))));
|
||||||
|
|
||||||
|
assertEquals(Literal.FALSE, new BinaryComparisonSimplification().rule(new GreaterThan(EMPTY, L(5), L(5))));
|
||||||
|
assertEquals(Literal.FALSE, new BinaryComparisonSimplification().rule(new LessThan(EMPTY, L(5), L(5))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLiteralsOnTheRight() {
|
||||||
|
Alias a = new Alias(EMPTY, "a", L(10));
|
||||||
|
Expression result = new BooleanLiteralsOnTheRight().rule(new Equals(EMPTY, L(5), a));
|
||||||
|
assertTrue(result instanceof Equals);
|
||||||
|
Equals eq = (Equals) result;
|
||||||
|
assertEquals(a, eq.left());
|
||||||
|
assertEquals(L(5), eq.right());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testBoolSimplifyOr() {
|
||||||
|
BooleanSimplification simplification = new BooleanSimplification();
|
||||||
|
|
||||||
|
assertEquals(Literal.TRUE, simplification.rule(new Or(EMPTY, Literal.TRUE, Literal.TRUE)));
|
||||||
|
assertEquals(Literal.TRUE, simplification.rule(new Or(EMPTY, Literal.TRUE, DUMMY_EXPRESSION)));
|
||||||
|
assertEquals(Literal.TRUE, simplification.rule(new Or(EMPTY, DUMMY_EXPRESSION, Literal.TRUE)));
|
||||||
|
|
||||||
|
assertEquals(Literal.FALSE, simplification.rule(new Or(EMPTY, Literal.FALSE, Literal.FALSE)));
|
||||||
|
assertEquals(DUMMY_EXPRESSION, simplification.rule(new Or(EMPTY, Literal.FALSE, DUMMY_EXPRESSION)));
|
||||||
|
assertEquals(DUMMY_EXPRESSION, simplification.rule(new Or(EMPTY, DUMMY_EXPRESSION, Literal.FALSE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBoolSimplifyAnd() {
|
||||||
|
BooleanSimplification simplification = new BooleanSimplification();
|
||||||
|
|
||||||
|
assertEquals(Literal.TRUE, simplification.rule(new And(EMPTY, Literal.TRUE, Literal.TRUE)));
|
||||||
|
assertEquals(DUMMY_EXPRESSION, simplification.rule(new And(EMPTY, Literal.TRUE, DUMMY_EXPRESSION)));
|
||||||
|
assertEquals(DUMMY_EXPRESSION, simplification.rule(new And(EMPTY, DUMMY_EXPRESSION, Literal.TRUE)));
|
||||||
|
|
||||||
|
assertEquals(Literal.FALSE, simplification.rule(new And(EMPTY, Literal.FALSE, Literal.FALSE)));
|
||||||
|
assertEquals(Literal.FALSE, simplification.rule(new And(EMPTY, Literal.FALSE, DUMMY_EXPRESSION)));
|
||||||
|
assertEquals(Literal.FALSE, simplification.rule(new And(EMPTY, DUMMY_EXPRESSION, Literal.FALSE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBoolCommonFactorExtraction() {
|
||||||
|
BooleanSimplification simplification = new BooleanSimplification();
|
||||||
|
|
||||||
|
Expression a1 = new DummyBooleanExpression(EMPTY, 1);
|
||||||
|
Expression a2 = new DummyBooleanExpression(EMPTY, 1);
|
||||||
|
Expression b = new DummyBooleanExpression(EMPTY, 2);
|
||||||
|
Expression c = new DummyBooleanExpression(EMPTY, 3);
|
||||||
|
|
||||||
|
Expression actual = new Or(EMPTY, new And(EMPTY, a1, b), new And(EMPTY, a2, c));
|
||||||
|
Expression expected = new And(EMPTY, a1, new Or(EMPTY, b, c));
|
||||||
|
|
||||||
|
assertEquals(expected, simplification.rule(actual));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue