refactor: Herstructurering

This commit is contained in:
Tibo De Peuter 2025-04-06 19:16:50 +02:00
parent 1acd1cfb67
commit e3c84e1761
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
33 changed files with 290 additions and 178 deletions

View file

@ -3,14 +3,15 @@ package prolog
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import prolog.ast.logic.Fact
import prolog.ast.logic.Rule
import prolog.builtins.Conjunction
import prolog.builtins.Disjunction
import prolog.components.Program
import prolog.components.expressions.Fact
import prolog.components.expressions.Rule
import prolog.components.terms.Atom
import prolog.components.terms.Structure
import prolog.components.terms.Variable
import prolog.builtins.Query
import prolog.builtins.equivalent
import prolog.ast.terms.Atom
import prolog.ast.terms.Structure
import prolog.ast.terms.Variable
class EvaluationTest {
@BeforeEach
@ -25,7 +26,7 @@ class EvaluationTest {
val result = Program.query(Atom("a"))
assertTrue(result)
assertTrue(result.any())
}
@Test
@ -35,7 +36,7 @@ class EvaluationTest {
val result = Program.query(Atom("b"))
assertFalse(result)
assertFalse(result.any())
}
@Test
@ -44,9 +45,9 @@ class EvaluationTest {
val fact2 = Fact(Atom("b"))
Program.load(listOf(fact1, fact2))
assertTrue(Program.query(Atom("a")))
assertTrue(Program.query(Atom("b")))
assertFalse(Program.query(Atom("c")))
assertTrue(Program.query(Atom("a")).any())
assertTrue(Program.query(Atom("b")).any())
assertFalse(Program.query(Atom("c")).any())
}
@Test
@ -54,7 +55,7 @@ class EvaluationTest {
val structure = Structure(Atom("f"), listOf(Atom("a"), Atom("b")))
Program.load(listOf(Fact(structure)))
assertTrue(Program.query(Structure(Atom("f"), listOf(Atom("a"), Atom("b")))))
assertTrue(Program.query(Structure(Atom("f"), listOf(Atom("a"), Atom("b")))).any())
}
@Test
@ -63,9 +64,9 @@ class EvaluationTest {
val structure2 = Structure(Atom("g"), listOf(Atom("c"), Atom("d")))
Program.load(listOf(Fact(structure1), Fact(structure2)))
assertTrue(Program.query(Structure(Atom("f"), listOf(Atom("a"), Atom("b")))))
assertTrue(Program.query(Structure(Atom("g"), listOf(Atom("c"), Atom("d")))))
assertFalse(Program.query(Structure(Atom("h"), listOf(Atom("e")))))
assertTrue(Program.query(Structure(Atom("f"), listOf(Atom("a"), Atom("b")))).any())
assertTrue(Program.query(Structure(Atom("g"), listOf(Atom("c"), Atom("d")))).any())
assertFalse(Program.query(Structure(Atom("h"), listOf(Atom("e")))).any())
}
/**
@ -89,8 +90,8 @@ class EvaluationTest {
Program.load(listOf(father, mother, parent1, parent2))
assertTrue(Program.query(Structure(Atom("parent"), listOf(Atom("john"), Atom("jimmy")))))
assertTrue(Program.query(Structure(Atom("parent"), listOf(Atom("jane"), Atom("jimmy")))))
assertTrue(Program.query(Structure(Atom("parent"), listOf(Atom("john"), Atom("jimmy")))).any())
assertTrue(Program.query(Structure(Atom("parent"), listOf(Atom("jane"), Atom("jimmy")))).any())
}
/**
@ -110,19 +111,20 @@ class EvaluationTest {
Structure(Atom("father"), listOf(variable1, variable2)),
/* ; */
Structure(Atom("mother"), listOf(variable1, variable2))
))
)
)
Program.load(listOf(father, mother, parent))
val result1 = Program.query(Structure(Atom("parent"), listOf(Atom("john"), Atom("jimmy"))))
assertTrue(result1)
assertTrue(result1.toList().isNotEmpty())
val result2 = Program.query(Structure(Atom("parent"), listOf(Atom("jane"), Atom("jimmy"))))
assertTrue(result2)
assertTrue(result2.toList().isNotEmpty())
val result3 = Program.query(Structure(Atom("parent"), listOf(Atom("john"), Atom("jane"))))
assertFalse(result3)
assertFalse(result3.any())
val result4 = Program.query(Structure(Atom("father"), listOf(Atom("john"), Atom("jane"))))
assertFalse(result4)
assertFalse(result4.any())
}
/**
@ -162,18 +164,55 @@ class EvaluationTest {
Program.load(listOf(male, female, parent1, parent2, isFather, isMother))
val result1 = Program.query(Structure(Atom("isFather"), listOf(Atom("john"), Atom("jimmy"))))
assertTrue(result1)
assertTrue(result1.any())
val result2 = Program.query(Structure(Atom("isMother"), listOf(Atom("jane"), Atom("jimmy"))))
assertTrue(result2)
assertTrue(result2.any())
val result3 = Program.query(Structure(Atom("isFather"), listOf(Atom("jane"), Atom("jimmy"))))
assertFalse(result3)
assertFalse(result3.any())
val result4 = Program.query(Structure(Atom("isMother"), listOf(Atom("john"), Atom("jimmy"))))
assertFalse(result4)
assertFalse(result4.any())
val result5 = Program.query(Structure(Atom("parent"), listOf(Atom("trudy"), Atom("jimmy"))))
assertFalse(result5)
assertFalse(result5.any())
}
@Test
fun requires_backtracking() {
val fact1 = Fact(Structure(Atom("a"), listOf(Atom("b"))))
val fact2 = Fact(Structure(Atom("a"), listOf(Atom("c"))))
val fact3 = Fact(Structure(Atom("a"), listOf(Atom("d"))))
Program.load(listOf(fact1, fact2, fact3))
assertTrue(Program.query(Structure(Atom("a"), listOf(Atom("b")))).any())
assertTrue(Program.query(Structure(Atom("a"), listOf(Atom("c")))).any())
assertTrue(Program.query(Structure(Atom("a"), listOf(Atom("d")))).any())
}
@Test
fun multiple_choices() {
val fact1 = Fact(Structure(Atom("a"), listOf(Atom("b"))))
val fact2 = Fact(Structure(Atom("a"), listOf(Atom("c"))))
val fact3 = Fact(Structure(Atom("a"), listOf(Atom("d"))))
Program.load(listOf(fact1, fact2, fact3))
val results = Query(Structure(Atom("a"), listOf(Variable("X")))).prove(emptyMap())
val expectedResults = listOf(
mapOf(Variable("X") to Atom("b")),
mapOf(Variable("X") to Atom("c")),
mapOf(Variable("X") to Atom("d"))
)
val actualResults = results.toList()
assertEquals(expectedResults.size, actualResults.size, "Number of results should match")
for (i in expectedResults.indices) {
assertEquals(expectedResults[i].size, actualResults[i].size, "Substitution size should match")
assertTrue(expectedResults[i].all { actualResults[i][it.key]?.let { it1 -> equivalent(it.value, it1) } ?: false }, "Substitution values should match")
}
}
}

View file

@ -0,0 +1,66 @@
package prolog.builtins
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import prolog.Program
import prolog.ast.logic.Fact
import prolog.ast.terms.Atom
class ControlBuiltinsTest {
@BeforeEach
fun setUp() {
Program.clear()
}
@Test
fun not_atom() {
val success = Fact(Atom("a"))
Program.load(listOf(success))
val goal = Atom("a")
val notGoal = Not(goal)
val result1 = Program.query(goal)
val result2 = Program.query(notGoal)
assertTrue(result1.any(), "Expected query to succeed")
assertFalse(result2.any(), "Expected query to fail")
}
@Test
fun not_compound() {
val success = Fact(Atom("f"))
val failure = Fact(Atom("g"))
Program.load(listOf(success, failure))
val goal = Atom("f")
val notGoal = Not(Atom("g"))
val result1 = Program.query(goal)
val result2 = Program.query(notGoal)
assertTrue(result1.any(), "Expected query to succeed")
assertFalse(result2.any(), "Expected query to fail")
}
@Test
fun fail_should_cause_fails() {
val success = Fact(Atom("a"))
val failure = Fact(Atom("b"))
Program.load(listOf(success, failure))
val goal = Atom("a")
val failGoal = Fail()
val result1 = Program.query(goal)
val result2 = Program.query(failGoal)
assertTrue(result1.any(), "Expected query to succeed")
assertFalse(result2.any(), "Expected query to fail")
}
}

View file

@ -3,9 +3,8 @@ package prolog.builtins
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import prolog.components.terms.Atom
import prolog.components.terms.Structure
import prolog.ast.terms.Atom
import prolog.ast.terms.Structure
/**
* 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)

View file

@ -3,12 +3,12 @@ package prolog.builtins
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import prolog.components.terms.Atom
import prolog.components.terms.Structure
import prolog.components.terms.Variable
import prolog.ast.terms.Atom
import prolog.ast.terms.Structure
import prolog.ast.terms.Variable
import kotlin.test.assertEquals
class BuiltinsTest {
class VerificationBuiltinsTest {
@Test
fun unbound_variable_is_var() {
val variable = Variable("X")

View file

@ -1,12 +1,12 @@
package prolog
package prolog.logic
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import prolog.ast.terms.Atom
import prolog.ast.terms.Structure
import prolog.ast.terms.Variable
import prolog.builtins.equivalent
import prolog.components.terms.Atom
import prolog.components.terms.Structure
import prolog.components.terms.Variable
/*
* Based on: https://en.wikipedia.org/wiki/Unification_%28computer_science%29#Examples_of_syntactic_unification_of_first-order_terms