/* * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors * * SPDX-License-Identifier: EPL-2.0 */ package tools.refinery.store.query.dnf; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import tools.refinery.store.query.literal.BooleanLiteral; import tools.refinery.store.query.term.NodeVariable; import tools.refinery.store.query.term.ParameterDirection; import tools.refinery.store.query.term.Variable; import tools.refinery.store.query.term.bool.BoolTerms; import tools.refinery.store.query.view.KeyOnlyView; import tools.refinery.store.query.view.SymbolView; import tools.refinery.store.representation.Symbol; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static tools.refinery.store.query.literal.Literals.check; import static tools.refinery.store.query.literal.Literals.not; import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; class DnfBuilderLiteralEliminationTest { private final Symbol friend = Symbol.of("friend", 2); private final SymbolView friendView = new KeyOnlyView<>(friend); private final NodeVariable p = Variable.of("p"); private final NodeVariable q = Variable.of("q"); private final Dnf trueDnf = Dnf.builder().parameter(p, ParameterDirection.IN).clause().build(); private final Dnf falseDnf = Dnf.builder().parameter(p).build(); @Test void eliminateTrueTest() { var actual = Dnf.builder() .parameters(p, q) .clause(BooleanLiteral.TRUE, friendView.call(p, q)) .build(); var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void eliminateTrueAssumptionTest() { var actual = Dnf.builder() .parameters(p, q) .clause(check(BoolTerms.constant(true)), friendView.call(p, q)) .build(); var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void eliminateFalseTest() { var actual = Dnf.builder() .parameters(p, q) .clause(friendView.call(p, q)) .clause(friendView.call(q, p), BooleanLiteral.FALSE) .build(); var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); assertThat(actual, structurallyEqualTo(expected)); } @ParameterizedTest @CsvSource(value = { "false", "null" }, nullValues = "null") void eliminateFalseAssumptionTest(Boolean value) { var actual = Dnf.builder() .parameters(p, q) .clause(friendView.call(p, q)) .clause(friendView.call(q, p), check(BoolTerms.constant(value))) .build(); var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void alwaysTrueTest() { var actual = Dnf.builder() .parameters(List.of(p, q), ParameterDirection.IN) .clause(friendView.call(p, q)) .clause(BooleanLiteral.TRUE) .build(); var expected = Dnf.builder().parameters(List.of(p, q), ParameterDirection.IN).clause().build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void alwaysFalseTest() { var actual = Dnf.builder() .parameters(p, q) .clause(friendView.call(p, q), BooleanLiteral.FALSE) .build(); var expected = Dnf.builder().parameters(p, q).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void eliminateTrueDnfTest() { var actual = Dnf.builder() .parameters(p, q) .clause(trueDnf.call(q), friendView.call(p, q)) .build(); var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void eliminateFalseDnfTest() { var actual = Dnf.builder() .parameters(p, q) .clause(friendView.call(p, q)) .clause(friendView.call(q, p), falseDnf.call(q)) .build(); var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void alwaysTrueDnfTest() { var actual = Dnf.builder() .parameters(List.of(p, q), ParameterDirection.IN) .clause(friendView.call(p, q)) .clause(trueDnf.call(q)) .build(); var expected = Dnf.builder().parameters(List.of(p, q), ParameterDirection.IN).clause().build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void alwaysFalseDnfTest() { var actual = Dnf.builder() .parameters(p, q) .clause(friendView.call(p, q), falseDnf.call(q)) .build(); var expected = Dnf.builder().parameters(p, q).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void eliminateNotFalseDnfTest() { var actual = Dnf.builder() .parameters(p, q) .clause(not(falseDnf.call(q)), friendView.call(p, q)) .build(); var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void eliminateNotTrueDnfTest() { var actual = Dnf.builder() .parameters(p, q) .clause(friendView.call(p, q)) .clause(friendView.call(q, p), not(trueDnf.call(q))) .build(); var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void alwaysNotFalseDnfTest() { var actual = Dnf.builder() .parameters(List.of(p, q), ParameterDirection.IN) .clause(friendView.call(p, q)) .clause(not(falseDnf.call(q))) .build(); var expected = Dnf.builder().parameters(List.of(p, q), ParameterDirection.IN).clause().build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void alwaysNotTrueDnfTest() { var actual = Dnf.builder() .parameters(p, q) .clause(friendView.call(p, q), not(trueDnf.call(q))) .build(); var expected = Dnf.builder().parameters(p, q).build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void removeDuplicateTest() { var actual = Dnf.of(builder -> builder.clause((p, q) -> List.of( friendView.call(p, q), friendView.call(p, q) ))); var expected = Dnf.of(builder -> builder.clause((p, q) -> List.of(friendView.call(p, q)))); assertThat(actual, structurallyEqualTo(expected)); } @Test void removeContradictoryTest() { var actual = Dnf.of(builder -> builder.clause((p, q) -> List.of( friendView.call(p, q), not(friendView.call(p, q)) ))); var expected = Dnf.builder().build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void removeContradictoryUniversalTest() { var actual = Dnf.of(builder -> builder.clause((p, q) -> List.of( friendView.call(q, q), friendView.call(p, q), not(friendView.call(p, Variable.of())) ))); var expected = Dnf.builder().build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void removeContradictoryExistentialUniversalTest() { var actual = Dnf.of(builder -> builder.clause((p) -> List.of( friendView.call(p, Variable.of()), not(friendView.call(p, Variable.of())) ))); var expected = Dnf.builder().build(); assertThat(actual, structurallyEqualTo(expected)); } @Test void removeContradictoryUniversalParameterTest() { var actual = Dnf.of(builder -> { var p = builder.parameter("p"); builder.clause((q) -> List.of( friendView.call(q, q), friendView.call(p, q), not(friendView.call(p, Variable.of())) )); }); var expected = Dnf.builder().parameter(p).build(); assertThat(actual, structurallyEqualTo(expected)); } }