Checkpoint
This commit is contained in:
parent
ef8b82457c
commit
d702b9b081
13 changed files with 114 additions and 63 deletions
|
@ -1,15 +1,18 @@
|
||||||
package prolog.builtins
|
package prolog.builtins
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.expressions.Operand
|
import prolog.components.expressions.Operand
|
||||||
import prolog.components.expressions.Operator
|
import prolog.components.expressions.Operator
|
||||||
import prolog.components.terms.Atom
|
import prolog.components.terms.Atom
|
||||||
import prolog.components.terms.Body
|
import prolog.components.terms.Body
|
||||||
|
import prolog.components.terms.Term
|
||||||
|
import prolog.components.terms.Variable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Always fail.
|
* Always fail.
|
||||||
*/
|
*/
|
||||||
class Fail: Atom("fail"), Body {
|
class Fail: Atom("fail"), Body {
|
||||||
override fun prove(): Boolean = false
|
override fun prove(): Sequence<Substitution> = emptySequence()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +24,7 @@ typealias False = Fail
|
||||||
* Always succeed.
|
* Always succeed.
|
||||||
*/
|
*/
|
||||||
class True: Atom("true"), Body {
|
class True: Atom("true"), Body {
|
||||||
override fun prove(): Boolean = true
|
override fun prove(): Sequence<Substitution> = sequenceOf(emptyMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Repeat/0
|
// TODO Repeat/0
|
||||||
|
@ -32,10 +35,16 @@ class True: Atom("true"), Body {
|
||||||
* Conjunction (and). True if both Goal1 and Goal2 are true.
|
* Conjunction (and). True if both Goal1 and Goal2 are true.
|
||||||
*/
|
*/
|
||||||
class Conjunction(leftOperand: Operand, rightOperand: Operand) : Operator(Atom(","), leftOperand, rightOperand) {
|
class Conjunction(leftOperand: Operand, rightOperand: Operand) : Operator(Atom(","), leftOperand, rightOperand) {
|
||||||
override fun prove(): Boolean {
|
override fun prove(): Sequence<Substitution> = sequence {
|
||||||
val left = leftOperand?.prove() ?: true
|
if (leftOperand != null) {
|
||||||
val right = rightOperand.prove()
|
leftOperand.prove().forEach { left ->
|
||||||
return left && right
|
rightOperand.prove().forEach { right ->
|
||||||
|
yield(left + right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
yieldAll(rightOperand.prove())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +52,10 @@ class Conjunction(leftOperand: Operand, rightOperand: Operand) : Operator(Atom("
|
||||||
* Disjunction (or). True if either Goal1 or Goal2 succeeds.
|
* Disjunction (or). True if either Goal1 or Goal2 succeeds.
|
||||||
*/
|
*/
|
||||||
class Disjunction(leftOperand: Operand, rightOperand: Operand) : Operator(Atom(";"), leftOperand, rightOperand) {
|
class Disjunction(leftOperand: Operand, rightOperand: Operand) : Operator(Atom(";"), leftOperand, rightOperand) {
|
||||||
override fun prove(): Boolean {
|
override fun prove(): Sequence<Substitution> = sequence {
|
||||||
val left = leftOperand?.prove() ?: false
|
if (leftOperand != null) {
|
||||||
val right = rightOperand.prove()
|
yieldAll(leftOperand.prove())
|
||||||
return left || right
|
}
|
||||||
|
yieldAll(rightOperand.prove())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package prolog.builtins
|
package prolog.builtins
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.expressions.Operand
|
import prolog.components.expressions.Operand
|
||||||
import prolog.components.expressions.Operator
|
import prolog.components.expressions.Operator
|
||||||
import prolog.components.terms.Atom
|
import prolog.components.terms.Atom
|
||||||
|
|
||||||
class Query(rightOperand: Operand) : Operator(Atom("?-"), null, rightOperand) {
|
class Query(rightOperand: Operand) : Operator(Atom("?-"), null, rightOperand) {
|
||||||
override fun prove(): Boolean = rightOperand.prove()
|
override fun prove(): Sequence<Substitution> = rightOperand.prove()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package prolog.components
|
package prolog.components
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.builtins.True
|
import prolog.builtins.True
|
||||||
import prolog.components.expressions.Clause
|
import prolog.components.expressions.Clause
|
||||||
import prolog.components.expressions.Fact
|
import prolog.components.expressions.Fact
|
||||||
|
@ -24,16 +25,20 @@ object Program: Resolvent {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun query(goal: Goal): Boolean {
|
/**
|
||||||
|
* Queries the program with a goal.
|
||||||
|
* @return true if the goal can be proven, false otherwise.
|
||||||
|
*/
|
||||||
|
fun query(goal: Goal): Boolean = solve(goal).any()
|
||||||
|
|
||||||
|
override fun solve(goal: Goal): Sequence<Substitution> {
|
||||||
val functor = goal.functor
|
val functor = goal.functor
|
||||||
// If the predicate does not exist, return false
|
// If the predicate does not exist, return false
|
||||||
val predicate = predicates[functor] ?: return false
|
val predicate = predicates[functor] ?: return emptySequence()
|
||||||
// If the predicate exists, evaluate the goal against it
|
// If the predicate exists, evaluate the goal against it
|
||||||
return predicate.solve(goal)
|
return predicate.solve(goal)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun solve(goal: Goal): Boolean = query(goal)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a list of clauses into the program.
|
* Loads a list of clauses into the program.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
package prolog.components
|
package prolog.components
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
|
|
||||||
interface Provable {
|
interface Provable {
|
||||||
fun prove(): Boolean
|
/**
|
||||||
|
* Proves the current [Provable] instance.
|
||||||
|
*
|
||||||
|
* @return a sequence of [Substitution] instances representing the results of the proof.
|
||||||
|
* If the proof fails, an empty sequence is returned.
|
||||||
|
*/
|
||||||
|
fun prove(): Sequence<Substitution>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
package prolog.components
|
package prolog.components
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.terms.Goal
|
import prolog.components.terms.Goal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can be instructed to solve a goal.
|
* Can be instructed to solve a goal.
|
||||||
*/
|
*/
|
||||||
interface Resolvent {
|
interface Resolvent {
|
||||||
fun solve(goal: Goal): Boolean
|
/**
|
||||||
|
* Attempts to solve the given goal.
|
||||||
|
*
|
||||||
|
* @return A sequence of substitutions that can be applied to the goal to unify it with this resolvent.
|
||||||
|
* If the goal cannot be unified with this resolvent, an empty sequence is returned.
|
||||||
|
*/
|
||||||
|
fun solve(goal: Goal): Sequence<Substitution>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package prolog.components.expressions
|
package prolog.components.expressions
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.Resolvent
|
import prolog.components.Resolvent
|
||||||
import prolog.components.terms.*
|
import prolog.components.terms.*
|
||||||
import prolog.unify
|
import prolog.unifyLazy
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ‘Sentence’ of a Prolog program.
|
* ‘Sentence’ of a Prolog program.
|
||||||
|
@ -15,20 +16,22 @@ import prolog.unify
|
||||||
abstract class Clause(private val head: Head, private val body: Body? = null) : Resolvent {
|
abstract class Clause(private val head: Head, private val body: Body? = null) : Resolvent {
|
||||||
val functor: Functor = head.functor
|
val functor: Functor = head.functor
|
||||||
|
|
||||||
override fun solve(goal: Goal): Boolean {
|
override fun solve(goal: Goal): Sequence<Substitution> = sequence {
|
||||||
val unification = unify(goal, head)
|
if (body == null) {
|
||||||
|
// If the clause is a fact, unify the goal with the head, and return the substitutions.
|
||||||
if (unification.isEmpty) {
|
// Do this in a lazy way.
|
||||||
return false
|
yieldAll(unifyLazy(goal, head))
|
||||||
|
} else {
|
||||||
|
// If the clause is a rule, unify the goal with the head and then try to prove the body.
|
||||||
|
// Only if the body can be proven, the substitutions should be returned.
|
||||||
|
// Do this in a lazy way.
|
||||||
|
unifyLazy(goal, head).forEach { subs ->
|
||||||
|
// If the body can be proven, yield the (combined) substitutions
|
||||||
|
body.prove().forEach { bodySubs ->
|
||||||
|
yield(subs + bodySubs)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val substitutions = unification.get()
|
|
||||||
|
|
||||||
val proven = body == null || body.prove()
|
|
||||||
|
|
||||||
substitutions.forEach { (variable, _) -> variable.unbind() }
|
|
||||||
|
|
||||||
return proven
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package prolog.components.expressions
|
package prolog.components.expressions
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.Provable
|
import prolog.components.Provable
|
||||||
import prolog.components.terms.Atom
|
import prolog.components.terms.Atom
|
||||||
import prolog.components.terms.CompoundTerm
|
import prolog.components.terms.CompoundTerm
|
||||||
|
@ -8,11 +9,11 @@ import prolog.components.terms.Goal
|
||||||
typealias Operand = Goal
|
typealias Operand = Goal
|
||||||
|
|
||||||
abstract class Operator(
|
abstract class Operator(
|
||||||
val symbol: Atom,
|
private val symbol: Atom,
|
||||||
val leftOperand: Operand? = null,
|
val leftOperand: Operand? = null,
|
||||||
val rightOperand: Operand
|
val rightOperand: Operand
|
||||||
) : CompoundTerm(symbol, listOfNotNull(leftOperand, rightOperand)), Provable {
|
) : CompoundTerm(symbol, listOfNotNull(leftOperand, rightOperand)), Provable {
|
||||||
abstract override fun prove(): Boolean
|
abstract override fun prove(): Sequence<Substitution>
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return when (leftOperand) {
|
return when (leftOperand) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package prolog.components.expressions
|
package prolog.components.expressions
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.Resolvent
|
import prolog.components.Resolvent
|
||||||
import prolog.components.terms.Functor
|
import prolog.components.terms.Functor
|
||||||
import prolog.components.terms.Goal
|
import prolog.components.terms.Goal
|
||||||
|
@ -48,8 +49,12 @@ class Predicate : Resolvent {
|
||||||
this.clauses.addAll(clauses)
|
this.clauses.addAll(clauses)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun solve(goal: Goal): Boolean {
|
override fun solve(goal: Goal): Sequence<Substitution> = sequence {
|
||||||
require(goal.functor == functor) { "Goal functor does not match predicate functor" }
|
require(goal.functor == functor) { "Goal functor does not match predicate functor" }
|
||||||
return clauses.any { it.solve(goal) }
|
for (clause in clauses) {
|
||||||
|
// Try to unify the goal with the clause
|
||||||
|
// If the unification is successful, yield the substitutions
|
||||||
|
yieldAll(clause.solve(goal))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package prolog.components.terms
|
package prolog.components.terms
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.Resolvent
|
import prolog.components.Resolvent
|
||||||
import prolog.unify
|
import prolog.unify
|
||||||
|
import prolog.unifyLazy
|
||||||
|
|
||||||
open class Atom(val name: String) : Goal(), Head, Body, Resolvent {
|
open class Atom(val name: String) : Goal(), Head, Body, Resolvent {
|
||||||
override val functor: Functor = "$name/_"
|
override val functor: Functor = "$name/_"
|
||||||
|
|
||||||
override fun solve(goal: Goal): Boolean = unify(goal, this).isEmpty
|
override fun solve(goal: Goal): Sequence<Substitution> = unifyLazy(goal, this)
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return name
|
return name
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package prolog.components.terms
|
package prolog.components.terms
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.Program
|
import prolog.components.Program
|
||||||
import prolog.components.Provable
|
import prolog.components.Provable
|
||||||
|
|
||||||
|
@ -13,5 +14,5 @@ import prolog.components.Provable
|
||||||
abstract class Goal : Term, Provable {
|
abstract class Goal : Term, Provable {
|
||||||
abstract val functor: Functor
|
abstract val functor: Functor
|
||||||
|
|
||||||
override fun prove(): Boolean = Program.query(this)
|
override fun prove(): Sequence<Substitution> = Program.solve(this)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package prolog.components.terms
|
package prolog.components.terms
|
||||||
|
|
||||||
|
import prolog.Substitution
|
||||||
import prolog.components.Resolvent
|
import prolog.components.Resolvent
|
||||||
import prolog.unify
|
import prolog.unifyLazy
|
||||||
|
|
||||||
typealias Argument = Term
|
typealias Argument = Term
|
||||||
|
|
||||||
open class Structure(val name: Atom, val arguments: List<Argument>): Goal(), Head, Body, Resolvent {
|
open class Structure(val name: Atom, val arguments: List<Argument>): Goal(), Head, Body, Resolvent {
|
||||||
override val functor: Functor = "${name.name}/${arguments.size}"
|
override val functor: Functor = "${name.name}/${arguments.size}"
|
||||||
|
|
||||||
override fun solve(goal: Goal): Boolean {
|
override fun solve(goal: Goal): Sequence<Substitution> {
|
||||||
return unify(goal, this).isEmpty
|
return unifyLazy(goal, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import java.util.*
|
||||||
typealias Substitution = Map<Variable, Term>
|
typealias Substitution = Map<Variable, Term>
|
||||||
|
|
||||||
// Apply substitutions to a term
|
// Apply substitutions to a term
|
||||||
fun applySubstitution(term: Term, substitution: Substitution): Term = when {
|
private fun applySubstitution(term: Term, substitution: Substitution): Term = when {
|
||||||
variable(term) -> (term as Variable).alias().map { applySubstitution(it, substitution) }.orElse(term)
|
variable(term) -> (term as Variable).alias().map { applySubstitution(it, substitution) }.orElse(term)
|
||||||
atomic(term) -> term
|
atomic(term) -> term
|
||||||
compound(term) -> {
|
compound(term) -> {
|
||||||
|
@ -22,7 +22,7 @@ fun applySubstitution(term: Term, substitution: Substitution): Term = when {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a variable occurs in a term
|
// Check if a variable occurs in a term
|
||||||
fun occurs(variable: Variable, term: Term): Boolean = when {
|
private fun occurs(variable: Variable, term: Term): Boolean = when {
|
||||||
variable(term) -> term == variable
|
variable(term) -> term == variable
|
||||||
atomic(term) -> false
|
atomic(term) -> false
|
||||||
compound(term) -> {
|
compound(term) -> {
|
||||||
|
@ -33,7 +33,7 @@ fun occurs(variable: Variable, term: Term): Boolean = when {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate possible substitutions
|
// Generate possible substitutions
|
||||||
fun generateSubstitutions(term1: Term, term2: Term, substitution: Substitution): Sequence<Substitution> = sequence {
|
private fun generateSubstitutions(term1: Term, term2: Term, substitution: Substitution): Sequence<Substitution> = sequence {
|
||||||
val t1 = applySubstitution(term1, substitution)
|
val t1 = applySubstitution(term1, substitution)
|
||||||
val t2 = applySubstitution(term2, substitution)
|
val t2 = applySubstitution(term2, substitution)
|
||||||
|
|
||||||
|
@ -42,15 +42,17 @@ fun generateSubstitutions(term1: Term, term2: Term, substitution: Substitution):
|
||||||
variable(t1) -> {
|
variable(t1) -> {
|
||||||
val variable = t1 as Variable
|
val variable = t1 as Variable
|
||||||
if (!occurs(variable, t2)) {
|
if (!occurs(variable, t2)) {
|
||||||
variable.bind(t2)
|
// variable.bind(t2)
|
||||||
yield(substitution + (variable to t2))
|
yield(substitution + (variable to t2))
|
||||||
|
// variable.unbind()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
variable(t2) -> {
|
variable(t2) -> {
|
||||||
val variable = t2 as Variable
|
val variable = t2 as Variable
|
||||||
if (!occurs(variable, t1)) {
|
if (!occurs(variable, t1)) {
|
||||||
variable.bind(t1)
|
// variable.bind(t1)
|
||||||
yield(substitution + (variable to t1))
|
yield(substitution + (variable to t1))
|
||||||
|
// variable.unbind()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compound(t1) && compound(t2) -> {
|
compound(t1) && compound(t2) -> {
|
||||||
|
@ -68,8 +70,11 @@ fun generateSubstitutions(term1: Term, term2: Term, substitution: Substitution):
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unify two terms with backtracking and lazy evaluation
|
// Unify two terms with backtracking and lazy evaluation
|
||||||
fun unifyLazy(term1: Term, term2: Term, substitution: Substitution = emptyMap()): Sequence<Substitution> {
|
fun unifyLazy(term1: Term, term2: Term, substitution: Substitution = emptyMap()): Sequence<Substitution> = sequence {
|
||||||
return generateSubstitutions(term1, term2, substitution)
|
generateSubstitutions(term1, term2, substitution).forEach { newSubstitution ->
|
||||||
|
// Return the new substitution
|
||||||
|
yield(newSubstitution)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unify(term1: Term, term2: Term): Optional<Substitution> {
|
fun unify(term1: Term, term2: Term): Optional<Substitution> {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package prolog
|
package prolog
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions.assertFalse
|
import org.junit.jupiter.api.Assertions.*
|
||||||
import org.junit.jupiter.api.Assertions.assertTrue
|
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import prolog.builtins.Conjunction
|
import prolog.builtins.Conjunction
|
||||||
|
@ -11,6 +10,7 @@ import prolog.components.expressions.Fact
|
||||||
import prolog.components.expressions.Rule
|
import prolog.components.expressions.Rule
|
||||||
import prolog.components.terms.Atom
|
import prolog.components.terms.Atom
|
||||||
import prolog.components.terms.Structure
|
import prolog.components.terms.Structure
|
||||||
|
import prolog.components.terms.Variable
|
||||||
|
|
||||||
class EvaluationTest {
|
class EvaluationTest {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
@ -23,7 +23,9 @@ class EvaluationTest {
|
||||||
val fact = Fact(Atom("a"))
|
val fact = Fact(Atom("a"))
|
||||||
Program.load(listOf(fact))
|
Program.load(listOf(fact))
|
||||||
|
|
||||||
assertTrue(Program.query(Atom("a")))
|
val result = Program.query(Atom("a"))
|
||||||
|
|
||||||
|
assertTrue(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -75,14 +77,14 @@ class EvaluationTest {
|
||||||
val mother = Fact(Structure(Atom("mother"), listOf(Atom("jane"), Atom("jimmy"))))
|
val mother = Fact(Structure(Atom("mother"), listOf(Atom("jane"), Atom("jimmy"))))
|
||||||
|
|
||||||
val parent1 = Rule(
|
val parent1 = Rule(
|
||||||
Structure(Atom("parent"), listOf(Atom("X"), Atom("Y"))),
|
Structure(Atom("parent"), listOf(Variable("X"), Variable("Y"))),
|
||||||
/* :- */
|
/* :- */
|
||||||
Structure(Atom("father"), listOf(Atom("X"), Atom("Y")))
|
Structure(Atom("father"), listOf(Variable("X"), Variable("Y")))
|
||||||
)
|
)
|
||||||
val parent2 = Rule(
|
val parent2 = Rule(
|
||||||
Structure(Atom("parent"), listOf(Atom("X"), Atom("Y"))),
|
Structure(Atom("parent"), listOf(Variable("X"), Variable("Y"))),
|
||||||
/* :- */
|
/* :- */
|
||||||
Structure(Atom("mother"), listOf(Atom("X"), Atom("Y")))
|
Structure(Atom("mother"), listOf(Variable("X"), Variable("Y")))
|
||||||
)
|
)
|
||||||
|
|
||||||
Program.load(listOf(father, mother, parent1, parent2))
|
Program.load(listOf(father, mother, parent1, parent2))
|
||||||
|
@ -100,11 +102,11 @@ class EvaluationTest {
|
||||||
val mother = Fact(Structure(Atom("mother"), listOf(Atom("jane"), Atom("jimmy"))))
|
val mother = Fact(Structure(Atom("mother"), listOf(Atom("jane"), Atom("jimmy"))))
|
||||||
|
|
||||||
val parent = Rule(
|
val parent = Rule(
|
||||||
Structure(Atom("parent"), listOf(Atom("X"), Atom("Y"))),
|
Structure(Atom("parent"), listOf(Variable("X"), Variable("Y"))),
|
||||||
/* :- */ Disjunction(
|
/* :- */ Disjunction(
|
||||||
Structure(Atom("father"), listOf(Atom("X"), Atom("Y"))),
|
Structure(Atom("father"), listOf(Variable("X"), Variable("Y"))),
|
||||||
/* ; */
|
/* ; */
|
||||||
Structure(Atom("mother"), listOf(Atom("X"), Atom("Y")))
|
Structure(Atom("mother"), listOf(Variable("X"), Variable("Y")))
|
||||||
))
|
))
|
||||||
|
|
||||||
Program.load(listOf(father, mother, parent))
|
Program.load(listOf(father, mother, parent))
|
||||||
|
@ -129,17 +131,17 @@ class EvaluationTest {
|
||||||
val parent2 = Fact(Structure(Atom("parent"), listOf(Atom("jane"), Atom("jimmy"))))
|
val parent2 = Fact(Structure(Atom("parent"), listOf(Atom("jane"), Atom("jimmy"))))
|
||||||
|
|
||||||
val isFather = Rule(
|
val isFather = Rule(
|
||||||
Structure(Atom("isFather"), listOf(Atom("X"), Atom("Y"))),
|
Structure(Atom("isFather"), listOf(Variable("X"), Variable("Y"))),
|
||||||
Conjunction(
|
Conjunction(
|
||||||
Structure(Atom("parent"), listOf(Atom("X"), Atom("Y"))),
|
Structure(Atom("parent"), listOf(Variable("X"), Variable("Y"))),
|
||||||
Structure(Atom("male"), listOf(Atom("X")))
|
Structure(Atom("male"), listOf(Variable("X")))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val isMother = Rule(
|
val isMother = Rule(
|
||||||
Structure(Atom("isMother"), listOf(Atom("X"), Atom("Y"))),
|
Structure(Atom("isMother"), listOf(Variable("X"), Variable("Y"))),
|
||||||
Conjunction(
|
Conjunction(
|
||||||
Structure(Atom("parent"), listOf(Atom("X"), Atom("Y"))),
|
Structure(Atom("parent"), listOf(Variable("X"), Variable("Y"))),
|
||||||
Structure(Atom("female"), listOf(Atom("X")))
|
Structure(Atom("female"), listOf(Variable("X")))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Reference in a new issue