refactor: Herstructurering
This commit is contained in:
parent
1acd1cfb67
commit
e3c84e1761
33 changed files with 290 additions and 178 deletions
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
66
tests/prolog/builtins/ControlBuiltinsTest.kt
Normal file
66
tests/prolog/builtins/ControlBuiltinsTest.kt
Normal 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")
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
Reference in a new issue