Checkpoint

This commit is contained in:
Tibo De Peuter 2025-05-04 21:50:58 +02:00
parent 5bfa1691dd
commit a85169dced
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
27 changed files with 377 additions and 250 deletions

View file

@ -1,7 +1,7 @@
package prolog.ast.logic
import prolog.Answers
import prolog.Program
import prolog.ast.Database.Program
import prolog.Substitutions
import prolog.ast.terms.*
import prolog.builtins.True
@ -16,10 +16,10 @@ import prolog.logic.unifyLazy
*
* A clause consists of a [Head] and body separated by the neck operator, or it is a [Fact].
*
* @see [prolog.ast.terms.Variable]
* @see [Variable]
* @see [Predicate]
*/
abstract class Clause(val head: Head, val body: Body) : Term, Resolvent {
abstract class Clause(var head: Head, var body: Body) : Term, Resolvent {
val functor: Functor = head.functor
override fun solve(goal: Goal, subs: Substitutions): Answers = sequence {
@ -35,7 +35,7 @@ abstract class Clause(val head: Head, val body: Body) : Term, Resolvent {
Program.variableRenamingStart = end
var newSubs: Substitutions = subs + renamed
unifyLazy(goal, head, newSubs).forEach { headAnswer ->
unifyLazy(applySubstitution(goal, subs), head, newSubs).forEach { headAnswer ->
headAnswer.map { headSubs ->
// If the body can be proven, yield the (combined) substitutions
newSubs = subs + renamed + headSubs
@ -43,8 +43,8 @@ abstract class Clause(val head: Head, val body: Body) : Term, Resolvent {
bodyAnswer.fold(
onSuccess = { bodySubs ->
var result = (headSubs + bodySubs)
.mapKeys { reverse[it.key] ?: it.key }
.mapValues { reverse[it.value] ?: it.value }
.mapKeys { applySubstitution(it.key, reverse)}
.mapValues { applySubstitution(it.value, reverse) }
result = result.map { it.key to applySubstitution(it.value, result) }
.toMap()
.filterNot { it.key in renamed.keys && !occurs(it.key as Variable, goal, emptyMap())}

View file

@ -15,37 +15,48 @@ import prolog.flags.AppliedCut
class Predicate : Resolvent {
val functor: Functor
val clauses: MutableList<Clause>
var dynamic = false
/**
* Creates a predicate with the given functor and an empty list of clauses.
*/
constructor(functor: Functor) {
constructor(functor: Functor, dynamic: Boolean = false) {
this.functor = functor
this.clauses = mutableListOf()
this.dynamic = dynamic
}
/**
* Creates a predicate with the given clauses.
*/
constructor(clauses: List<Clause>) {
constructor(clauses: List<Clause>, dynamic: Boolean = false) {
this.functor = clauses.first().functor
require(clauses.all { it.functor == functor }) { "All clauses must have the same functor" }
this.clauses = clauses.toMutableList()
this.dynamic = dynamic
}
/**
* Adds a clause to the predicate.
*
* @param clause The clause to add.
* @param index The index at which to insert the clause. If null, the clause is added to the end of the list.
* @param force If true, the clause is added even if the predicate is static.
*/
fun add(clause: Clause, index: Int? = null) {
fun add(clause: Clause, index: Int? = null, force: Boolean = false) {
require(clause.functor == functor) { "Clause functor does not match predicate functor" }
require(dynamic || force) { "No permission to modify static procedure '$functor'" }
if (index != null) clauses.add(index, clause) else clauses.add(clause)
}
/**
* Adds a list of clauses to the predicate.
*/
fun addAll(clauses: List<Clause>) {
fun addAll(clauses: List<Clause>, force: Boolean = false) {
require(clauses.all { it.functor == functor }) { "All clauses must have the same functor" }
require(dynamic || force) { "No permission to modify static procedure '$functor'" }
this.clauses.addAll(clauses)
}
@ -75,4 +86,4 @@ class Predicate : Resolvent {
}
}
}
}
}