feat: Arithmetic

This commit is contained in:
Tibo De Peuter 2025-04-11 21:11:59 +02:00
parent e73e5cbfc8
commit ac55ed4c64
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
6 changed files with 147 additions and 107 deletions

View file

@ -418,9 +418,8 @@ class ArithmeticOperatorsTests {
val t1 = Integer(2)
val t2 = Integer(3)
val result = Multiply(t1, t2).evaluate(emptyMap()).toList()
val result = Multiply(t1, t2).evaluate(emptyMap())
assertEquals(1, result.size, "There should only be one solution")
assertEquals(Integer(6), result, "2 * 3 should be equal to 6")
assertEquals(Integer(6), result.first, "2 * 3 should be equal to 6")
}
}

View file

@ -2,6 +2,7 @@ package prolog.logic
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.RepeatedTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import prolog.ast.terms.Integer
@ -53,10 +54,11 @@ class ArithmeticTests {
val expected = Integer(1)
val result = succ(t1, expected, emptyMap())
val result = succ(t1, expected, emptyMap()).toList()
assertTrue(result.any(), "Expected 0 + 1 to be equal to 1")
assertTrue(result.first().isEmpty(), "Expected no substitutions")
assertEquals(1, result.size, "Expected 0 + 1 to be equal to 1")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "Expected no substitutions")
}
@Test
@ -65,10 +67,11 @@ class ArithmeticTests {
val expected = Integer(2)
val result = succ(t1, expected, emptyMap())
val result = succ(t1, expected, emptyMap()).toList()
assertTrue(result.any(), "Expected 1 + 1 to be equal to 2")
assertTrue(result.first().isEmpty(), "Expected no substitutions")
assertEquals(1, result.size, "Expected 1 + 1 to be equal to 2")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "Expected no substitutions")
}
@Test
@ -80,8 +83,9 @@ class ArithmeticTests {
val result = succ(t1, t2, emptyMap()).toList()
assertTrue(result.isNotEmpty(), "Expected 1 + 1 to be equal to X")
assertTrue(result[0][t2] == expected, "Expected X to be equal to 2")
assertEquals(1, result.size, "Expected 1 + 1 to be equal to X")
assertTrue(result[0].isSuccess, "Expected success")
assertEquals(expected, result[0].getOrNull()!![t2], "Expected X to be equal to 2")
}
@Test
@ -91,10 +95,11 @@ class ArithmeticTests {
t1.bind(Integer(1))
val result = succ(t1, t2, emptyMap())
val result = succ(t1, t2, emptyMap()).toList()
assertTrue(result.any(), "Expected X + 1 to be equal to 2")
assertTrue(result.first().isEmpty(), "Expected no substitutions")
assertEquals(1, result.size, "Expected X + 1 to be equal to 2")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "Expected no substitutions")
}
@Test
@ -102,10 +107,11 @@ class ArithmeticTests {
val t1 = Variable("X")
val t2 = Integer(2)
val result = succ(t1, t2, mapOf(t1 to Integer(1)))
val result = succ(t1, t2, mapOf(t1 to Integer(1))).toList()
assertTrue(result.any(), "Expected X + 1 to be equal to 2")
assertTrue(result.first().isEmpty(), "Expected no substitutions")
assertEquals(1, result.size, "Expected X + 1 to be equal to 2")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "Expected no substitutions")
}
@Test
@ -117,8 +123,9 @@ class ArithmeticTests {
val result = succ(t1, t2, emptyMap()).toList()
assertTrue(result.isNotEmpty(), "Expected X + 1 to be equal to Y")
assertTrue(result[0][t2] == Integer(2), "Expected Y to be equal to 2")
assertEquals(1, result.size, "Expected X + 1 to be equal to Y")
assertTrue(result[0].isSuccess, "Expected success")
assertEquals(Integer(2), result[0].getOrNull()!![t2], "Expected Y to be equal to 2")
}
@Test
@ -128,8 +135,9 @@ class ArithmeticTests {
val result = succ(t1, t2, mapOf(t1 to Integer(1))).toList()
assertTrue(result.isNotEmpty(), "Expected X + 1 to be equal to Y")
assertTrue(result[0][t2] == Integer(2), "Expected Y to be equal to 2")
assertEquals(1, result.size, "Expected X + 1 to be equal to Y")
assertTrue(result[0].isSuccess, "Expected success")
assertEquals(Integer(2), result[0].getOrNull()!![t2], "Expected Y to be equal to 2")
}
@Test
@ -148,10 +156,11 @@ class ArithmeticTests {
val t2 = Integer(2)
val t3 = Integer(3)
val result = plus(t1, t2, t3, emptyMap())
val result = plus(t1, t2, t3, emptyMap()).toList()
assertTrue(result.any(), "1 + 2 should be equal to 3")
assertTrue(result.first().isEmpty(), "1 + 2 should be equal to 3")
assertEquals(1, result.size, "1 + 2 should be equal to 3")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "1 + 2 should be equal to 3")
}
@Test
@ -173,8 +182,9 @@ class ArithmeticTests {
val result = plus(t1, t2, t3, emptyMap()).toList()
assertTrue(result.isNotEmpty(), "1 + 2 should be equal to X")
assertTrue(equivalent(result[0][t3]!!, Integer(3)), "X should be equal to 3")
assertEquals(1, result.size, "1 + 2 should be equal to X")
assertTrue(result[0].isSuccess, "Expected success")
assertEquals(Integer(3), result[0].getOrNull()!![t3], "X should be equal to 3")
}
@Test
@ -185,8 +195,9 @@ class ArithmeticTests {
val result = plus(t1, t2, t3, emptyMap()).toList()
assertTrue(result.isNotEmpty(), "1 + X should be equal to 3")
assertTrue(equivalent(result[0][t2]!!, Integer(2)), "X should be equal to 2")
assertEquals(1, result.size, "1 + X should be equal to 3")
assertTrue(result[0].isSuccess, "Expected success")
assertEquals(Integer(2), result[0].getOrNull()!![t2], "X should be equal to 2")
}
@Test
@ -197,8 +208,9 @@ class ArithmeticTests {
val result = plus(t1, t2, t3, emptyMap()).toList()
assertTrue(result.isNotEmpty(), "X + 2 should be equal to 3")
assertTrue(equivalent(result[0][t1]!!, Integer(1)), "X should be equal to 1")
assertEquals(1, result.size, "X + 2 should be equal to 3")
assertTrue(result[0].isSuccess, "Expected success")
assertEquals(Integer(1), result[0].getOrNull()!![t1], "X should be equal to 1")
}
@Test
@ -209,10 +221,11 @@ class ArithmeticTests {
t3.bind(Integer(3))
val result = plus(t1, t2, t3, emptyMap())
val result = plus(t1, t2, t3, emptyMap()).toList()
assertTrue(result.any(), "1 + 2 should be equal to X")
assertTrue(result.first().isEmpty(), "t3 should not be rebound")
assertEquals(1, result.size, "1 + 2 should be equal to X")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "t3 should not be rebound")
}
@Test
@ -221,10 +234,11 @@ class ArithmeticTests {
val t2 = Integer(2)
val t3 = Variable("X")
val result = plus(t1, t2, t3, mapOf(Variable("X") to Integer(3)))
val result = plus(t1, t2, t3, mapOf(Variable("X") to Integer(3))).toList()
assertTrue(result.any(), "1 + 2 should be equal to X")
assertTrue(result.first().isEmpty(), "t3 should not be rebound")
assertEquals(1, result.size, "1 + 2 should be equal to X")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "t3 should not be rebound")
}
@Test
@ -248,10 +262,11 @@ class ArithmeticTests {
t2.bind(Integer(2))
val result = plus(t1, t2, t3, emptyMap())
val result = plus(t1, t2, t3, emptyMap()).toList()
assertTrue(result.any(), "1 + X should be equal to 3")
assertTrue(result.first().isEmpty(), "t2 should not be rebound")
assertEquals(1, result.size, "1 + X should be equal to 3")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "t2 should not be rebound")
}
@Test
@ -275,10 +290,11 @@ class ArithmeticTests {
t1.bind(Integer(1))
val result = plus(t1, t2, t3, emptyMap())
val result = plus(t1, t2, t3, emptyMap()).toList()
assertTrue(result.any(), "X + 2 should be equal to 3")
assertTrue(result.first().none(), "t1 should not be rebound")
assertEquals(1, result.size, "X + 2 should be equal to 3")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.none(), "t1 should not be rebound")
}
@Test
@ -300,9 +316,11 @@ class ArithmeticTests {
val t2 = Variable("Y")
val t3 = Integer(3)
assertThrows<IllegalArgumentException> {
plus(t1, t2, t3, emptyMap())
}
val result = plus(t1, t2, t3, emptyMap()).toList()
assertEquals(1, result.size, "There should be one solution")
assertTrue(result[0].isFailure, "Expected failure")
assertTrue(result[0].exceptionOrNull() is IllegalArgumentException, "Expected IllegalArgumentException")
}
@Test
@ -317,7 +335,8 @@ class ArithmeticTests {
val result = plus(t1, t2, t3, emptyMap()).toList()
assertTrue(result.isNotEmpty(), "X + Y should be equal to Z")
assertTrue(equivalent(result[0][t3]!!, Integer(3)), "Z should be equal to 3")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(equivalent(result[0].getOrThrow()[t3]!!, Integer(3)), "Z should be equal to 3")
}
@Test
@ -329,7 +348,21 @@ class ArithmeticTests {
val result = mul(t1, t2, t3, emptyMap()).toList()
assertEquals(1, result.size, "There should be one solution")
assertTrue(result[0].isEmpty(), "1 * 1 should already be equal to 1")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "1 * 1 should already be equal to 1")
}
@Test
fun `1 times 2 is 2`() {
val t1 = Integer(1)
val t2 = Integer(2)
val t3 = Integer(2)
val result = mul(t1, t2, t3, emptyMap()).toList()
assertEquals(1, result.size, "There should be one solution")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "1 * 2 should already be equal to 2")
}
@Test
@ -341,7 +374,8 @@ class ArithmeticTests {
val result = mul(t1, t2, t3, emptyMap()).toList()
assertEquals(1, result.size, "There should be one solution")
assertTrue(result[0].isEmpty(), "2 * 3 should already be equal to 6")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "2 * 3 should already be equal to 6")
}
@Test
@ -354,4 +388,17 @@ class ArithmeticTests {
assertTrue(result.none(), "2 * 3 should not be equal to 4")
}
@RepeatedTest(100)
fun `random test for mul`() {
val t1 = Integer((0..1000).random())
val t2 = Integer((0..1000).random())
val t3 = Variable("X")
val result = mul(t1, t2, t3, emptyMap()).toList()
assertEquals(1, result.size, "There should be one solution")
assertTrue(result[0].isSuccess, "Expected success")
assertEquals(Integer(t1.value * t2.value), result[0].getOrNull()!![t3], "X should be equal to ${t1.value * t2.value}")
}
}