Checkpoint
This commit is contained in:
parent
e3c84e1761
commit
e73e5cbfc8
32 changed files with 1354 additions and 92 deletions
426
tests/prolog/builtins/ArithmeticOperatorsTests.kt
Normal file
426
tests/prolog/builtins/ArithmeticOperatorsTests.kt
Normal file
|
@ -0,0 +1,426 @@
|
|||
package prolog.builtins
|
||||
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import prolog.ast.terms.Integer
|
||||
import prolog.ast.terms.Variable
|
||||
import prolog.logic.between
|
||||
import prolog.logic.equivalent
|
||||
|
||||
class ArithmeticOperatorsTests {
|
||||
@Test
|
||||
fun `1 evaluates to 1`() {
|
||||
val op1 = EvaluatesTo(
|
||||
Integer(1),
|
||||
Integer(1)
|
||||
)
|
||||
|
||||
var result = op1.evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(True, result, "1 should be equal to 1")
|
||||
|
||||
val op2 = EvaluatesToDifferent(
|
||||
Integer(1),
|
||||
Integer(1)
|
||||
)
|
||||
|
||||
result = op2.evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(False, result, "1 should not be different from 1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `1 does not evaluate to 2`() {
|
||||
val op1 = EvaluatesTo(
|
||||
Integer(1),
|
||||
Integer(2)
|
||||
)
|
||||
|
||||
var result = op1.evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(False, result, "1 should not be equal to 2")
|
||||
|
||||
val op2 = EvaluatesToDifferent(
|
||||
Integer(1),
|
||||
Integer(2)
|
||||
)
|
||||
|
||||
result = op2.evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(True, result, "1 should be different from 2")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `2 + 3 evaluates to 5`() {
|
||||
val op = EvaluatesTo(
|
||||
Add(Integer(2), Integer(3)),
|
||||
Integer(5)
|
||||
)
|
||||
|
||||
var result = op.evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(True, result, "2 + 3 should be equal to 5")
|
||||
|
||||
val op2 = EvaluatesToDifferent(
|
||||
Add(Integer(2), Integer(3)),
|
||||
Integer(5)
|
||||
)
|
||||
|
||||
result = op2.evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(False, result, "2 + 3 should not be different from 5")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `2 + 3 evaluates to 4 + 1`() {
|
||||
val op = EvaluatesTo(
|
||||
Add(Integer(2), Integer(3)),
|
||||
Add(Integer(4), Integer(1))
|
||||
)
|
||||
|
||||
var result = op.evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(True, result, "2 + 3 should be equal to 4 + 1")
|
||||
|
||||
val op2 = EvaluatesToDifferent(
|
||||
Add(Integer(2), Integer(3)),
|
||||
Add(Integer(4), Integer(1))
|
||||
)
|
||||
|
||||
result = op2.evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(False, result, "2 + 3 should not be different from 4 + 1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `1 evaluates to variable not sufficiently instantiated`() {
|
||||
val op = EvaluatesTo(
|
||||
Integer(1),
|
||||
Variable("X")
|
||||
)
|
||||
|
||||
assertThrows<IllegalArgumentException> { op.evaluate(emptyMap()) }
|
||||
|
||||
val op2 = EvaluatesToDifferent(
|
||||
Integer(1),
|
||||
Variable("X")
|
||||
)
|
||||
|
||||
assertThrows<IllegalArgumentException> { op2.evaluate(emptyMap()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `(1 + var) evaluates to 1 not sufficiently instantiated`() {
|
||||
val op = EvaluatesTo(
|
||||
Add(Integer(1), Variable("X")),
|
||||
Integer(1)
|
||||
)
|
||||
|
||||
assertThrows<IllegalArgumentException> { op.evaluate(emptyMap()) }
|
||||
|
||||
val op2 = EvaluatesToDifferent(
|
||||
Add(Integer(1), Variable("X")),
|
||||
Integer(1)
|
||||
)
|
||||
|
||||
assertThrows<IllegalArgumentException> { op2.evaluate(emptyMap()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `1 is 1`() {
|
||||
val op = Is(
|
||||
Integer(1),
|
||||
Integer(1)
|
||||
)
|
||||
|
||||
val result = op.prove(emptyMap())
|
||||
|
||||
assertTrue(result.any(), "1 should be equal to 1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `1 is not 2`() {
|
||||
val op = Is(
|
||||
Integer(1),
|
||||
Integer(2)
|
||||
)
|
||||
|
||||
val result = op.prove(emptyMap()).toList()
|
||||
|
||||
assertTrue(result.isEmpty(), "1 should not be equal to 2")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `bound-to-1-var is 1`() {
|
||||
val t1 = Variable("X")
|
||||
val op = Is(
|
||||
t1,
|
||||
Integer(1)
|
||||
)
|
||||
|
||||
t1.bind(Integer(1))
|
||||
|
||||
val result = op.prove(emptyMap())
|
||||
|
||||
assertTrue(result.any(), "X should be equal to 1")
|
||||
assertTrue(result.first().isEmpty(), "X should not be rebound")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `bound-to-2-var is not 1`() {
|
||||
val t1 = Variable("X")
|
||||
val op = Is(
|
||||
t1,
|
||||
Integer(1)
|
||||
)
|
||||
|
||||
t1.bind(Integer(2))
|
||||
|
||||
val result = op.prove(emptyMap())
|
||||
|
||||
assertFalse(result.any(), "X should not be equal to 1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `variable is 1`() {
|
||||
val op = Is(
|
||||
Variable("X"),
|
||||
Integer(1)
|
||||
)
|
||||
|
||||
val result = op.prove(emptyMap()).toList()
|
||||
|
||||
assertFalse(result.isEmpty(), "X should be equal to 1")
|
||||
assertEquals(1, result[0].size, "X should be rebound")
|
||||
assertTrue(equivalent(Integer(1), result[0][Variable("X")]!!), "X should be equal to 1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `variable is 1 + 2`() {
|
||||
val op = Is(
|
||||
Variable("X"),
|
||||
Add(Integer(1), Integer(2))
|
||||
)
|
||||
|
||||
val result = op.prove(emptyMap()).toList()
|
||||
|
||||
assertFalse(result.isEmpty(), "X should be equal to 3")
|
||||
assertEquals(1, result[0].size, "X should be rebound")
|
||||
assertTrue(equivalent(Integer(3), result[0][Variable("X")]!!), "X should be equal to 3")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `var is var should throw`() {
|
||||
val op = Is(
|
||||
Variable("X"),
|
||||
Variable("Y")
|
||||
)
|
||||
|
||||
assertThrows<IllegalArgumentException> { op.prove(emptyMap()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `1 is var should throw`() {
|
||||
val op = Is(
|
||||
Integer(1),
|
||||
Variable("X")
|
||||
)
|
||||
|
||||
assertThrows<IllegalArgumentException> { op.prove(emptyMap()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `var is bound-to-sum-var`() {
|
||||
val t1 = Variable("X")
|
||||
val t2 = Variable("Y")
|
||||
|
||||
t2.bind(Add(Integer(1), Integer(2)))
|
||||
|
||||
val op = Is(t1, t2)
|
||||
|
||||
val result = op.prove(emptyMap()).toList()
|
||||
|
||||
assertTrue(result.isNotEmpty(), "X should be equal to 3")
|
||||
assertEquals(1, result[0].size, "X should be rebound, Y should not")
|
||||
assertTrue(equivalent(Integer(3), result[0][t1]!!), "X should be equal to 3")
|
||||
}
|
||||
|
||||
/**
|
||||
* ?- between(1, 2, X), Y is 1 + X.
|
||||
* X = 1, Y = 2 ;
|
||||
* X = 2, Y = 3 .
|
||||
*/
|
||||
@Test
|
||||
fun `between 1 and 2 plus 1 to get 2 and 3`() {
|
||||
val t1 = Integer(1)
|
||||
val t2 = Integer(2)
|
||||
val t3 = Variable("X")
|
||||
val t4 = Variable("Y")
|
||||
|
||||
val op = Conjunction(
|
||||
Between(t1, t2, t3),
|
||||
Is(t4, Add(Integer(1), t3))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `negate 1 to get -1`() {
|
||||
val t1 = Integer(1)
|
||||
|
||||
val result = Negate(t1).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(-1), result, "negate(1) should be equal to -1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `negate 0 to get 0`() {
|
||||
val t1 = Integer(0)
|
||||
|
||||
val result = Negate(t1).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(0), result, "negate(0) should be equal to 0")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `negate -1 to get 1`() {
|
||||
val t1 = Integer(-1)
|
||||
|
||||
val result = Negate(t1).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(1), result, "negate(-1) should be equal to 1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `negate bound-to-1-var to get -1`() {
|
||||
val t1 = Variable("X")
|
||||
|
||||
t1.bind(Integer(1))
|
||||
|
||||
val result = Negate(t1).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(-1), result, "negate(1) should be equal to -1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `negate bound-to-1-var to get -1 by map`() {
|
||||
val t1 = Variable("X")
|
||||
|
||||
val result = Negate(t1).evaluate(mapOf(t1 to Integer(1))).first
|
||||
|
||||
assertEquals(Integer(-1), result, "negate(1) should be equal to -1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `negate 1 + 3 to get -4`() {
|
||||
val t1 = Integer(1)
|
||||
val t2 = Integer(3)
|
||||
|
||||
val result = Negate(Add(t1, t2)).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(-4), result, "negate(1 + 3) should be equal to -4")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Add 1 and 2 to get 3`() {
|
||||
val t1 = Integer(1)
|
||||
val t2 = Integer(2)
|
||||
|
||||
val result = Add(t1, t2).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(3), result, "1 + 2 should be equal to 3")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Add 1 and bound-to-2-var to get 3`() {
|
||||
val t1 = Integer(1)
|
||||
val t2 = Variable("X")
|
||||
|
||||
t2.bind(Integer(2))
|
||||
|
||||
val result = Add(t1, t2).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(3), result, "1 + 2 should be equal to 3")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Add 1 and bound-to-2-var to get 3 by map`() {
|
||||
val t1 = Integer(1)
|
||||
val t2 = Variable("X")
|
||||
|
||||
val result = Add(t1, t2).evaluate(mapOf(t2 to Integer(2))).first
|
||||
|
||||
assertEquals(Integer(3), result, "1 + 2 should be equal to 3")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Subtract 1 and 2 to get -1`() {
|
||||
val t1 = Integer(1)
|
||||
val t2 = Integer(2)
|
||||
|
||||
val result = Subtract(t1, t2).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(-1), result, "1 - 2 should be equal to -1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Subtract 3 and 1 to get 2`() {
|
||||
val t1 = Integer(3)
|
||||
val t2 = Integer(1)
|
||||
|
||||
val result = Subtract(t1, t2).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(2), result, "3 - 1 should be equal to 2")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Multiply 0 and 0 to get 0`() {
|
||||
val t1 = Integer(0)
|
||||
val t2 = Integer(0)
|
||||
|
||||
val result = Multiply(t1, t2).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(0), result, "0 * 0 should be equal to 0")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Multiply 1 and 0 to get 0`() {
|
||||
val t1 = Integer(1)
|
||||
val t2 = Integer(0)
|
||||
|
||||
val result = Multiply(t1, t2).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(0), result, "1 * 0 should be equal to 0")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Multiply 0 and 1 to get 0`() {
|
||||
val t1 = Integer(0)
|
||||
val t2 = Integer(1)
|
||||
|
||||
val result = Multiply(t1, t2).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(0), result, "0 * 1 should be equal to 0")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Multiply 3 and 1 to get 3`() {
|
||||
val t1 = Integer(3)
|
||||
val t2 = Integer(1)
|
||||
|
||||
val result = Multiply(t1, t2).evaluate(emptyMap()).first
|
||||
|
||||
assertEquals(Integer(3), result, "3 * 1 should be equal to 3")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Multiply 2 and 3 to get 6`() {
|
||||
val t1 = Integer(2)
|
||||
val t2 = Integer(3)
|
||||
|
||||
val result = Multiply(t1, t2).evaluate(emptyMap()).toList()
|
||||
|
||||
assertEquals(1, result.size, "There should only be one solution")
|
||||
assertEquals(Integer(6), result, "2 * 3 should be equal to 6")
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ import prolog.Program
|
|||
import prolog.ast.logic.Fact
|
||||
import prolog.ast.terms.Atom
|
||||
|
||||
class ControlBuiltinsTest {
|
||||
class ControlTest {
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
Program.clear()
|
||||
|
@ -55,7 +55,7 @@ class ControlBuiltinsTest {
|
|||
Program.load(listOf(success, failure))
|
||||
|
||||
val goal = Atom("a")
|
||||
val failGoal = Fail()
|
||||
val failGoal = Fail
|
||||
|
||||
val result1 = Program.query(goal)
|
||||
val result2 = Program.query(failGoal)
|
|
@ -5,6 +5,8 @@ import org.junit.jupiter.api.Assertions.assertTrue
|
|||
import org.junit.jupiter.api.Test
|
||||
import prolog.ast.terms.Atom
|
||||
import prolog.ast.terms.Structure
|
||||
import prolog.logic.atomic
|
||||
import prolog.logic.compound
|
||||
|
||||
/**
|
||||
* Based on [Predicates for analyzing/constructing terms](https://github.com/dtonhofer/prolog_notes/blob/master/swipl_notes/about_term_analysis_and_construction/term_analysis_construction.png)
|
||||
|
|
52
tests/prolog/builtins/UnificationTest.kt
Normal file
52
tests/prolog/builtins/UnificationTest.kt
Normal file
|
@ -0,0 +1,52 @@
|
|||
package prolog.builtins
|
||||
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
import prolog.ast.terms.Atom
|
||||
import prolog.ast.terms.Integer
|
||||
import prolog.ast.terms.Variable
|
||||
|
||||
class UnificationTest {
|
||||
/**
|
||||
* ?- X == a.
|
||||
* false.
|
||||
*/
|
||||
@Test
|
||||
fun equivalent_variable_and_atom() {
|
||||
val variable = Variable("X")
|
||||
val atom = Atom("a")
|
||||
|
||||
val result = Equivalent(variable, atom).prove(emptyMap())
|
||||
|
||||
assertFalse(result.any(), "Variable and atom should not be equivalent")
|
||||
}
|
||||
|
||||
/**
|
||||
* ?- a == a.
|
||||
* true.
|
||||
*/
|
||||
@Test
|
||||
fun equivalent_atom_and_atom() {
|
||||
val atom1 = Atom("a")
|
||||
val atom2 = Atom("a")
|
||||
|
||||
val result = Equivalent(atom1, atom2).prove(emptyMap())
|
||||
|
||||
assertTrue(result.any(), "Identical atoms should be equivalent")
|
||||
assertEquals(0, result.first().size, "No substitutions should be made")
|
||||
}
|
||||
|
||||
/**
|
||||
* ?- 1 + 2 == 3.
|
||||
* false.
|
||||
*/
|
||||
@Test
|
||||
fun simple_addition_equivalence() {
|
||||
val addition = Add(Integer(1), Integer(2))
|
||||
val solution = Integer(3)
|
||||
|
||||
val result = Equivalent(addition, solution).prove(emptyMap())
|
||||
|
||||
assertFalse(result.any(), "Addition should be equivalent")
|
||||
}
|
||||
}
|
|
@ -6,9 +6,12 @@ import org.junit.jupiter.api.Test
|
|||
import prolog.ast.terms.Atom
|
||||
import prolog.ast.terms.Structure
|
||||
import prolog.ast.terms.Variable
|
||||
import prolog.logic.compound
|
||||
import prolog.logic.nonvariable
|
||||
import prolog.logic.variable
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class VerificationBuiltinsTest {
|
||||
class VerificationTest {
|
||||
@Test
|
||||
fun unbound_variable_is_var() {
|
||||
val variable = Variable("X")
|
Reference in a new issue