commonMain.it.unibo.tuprolog.solve.concurrent.fsm.StateRuleSelection.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of solve-concurrent-jvm Show documentation
Show all versions of solve-concurrent-jvm Show documentation
Experimental, state-machine-based implementation of an OR-Concurrent, Prolog-like logic solver, based on Kotlin coroutines
package it.unibo.tuprolog.solve.concurrent.fsm
import it.unibo.tuprolog.core.Rule
import it.unibo.tuprolog.core.Struct
import it.unibo.tuprolog.solve.Signature
import it.unibo.tuprolog.solve.Solution
import it.unibo.tuprolog.solve.concurrent.ConcurrentExecutionContext
import it.unibo.tuprolog.solve.concurrent.stdlib.rule.Catch
import it.unibo.tuprolog.solve.exception.ResolutionException
import it.unibo.tuprolog.solve.exception.error.ExistenceError
import it.unibo.tuprolog.solve.exception.error.InstantiationError
import it.unibo.tuprolog.solve.exception.error.TypeError
import it.unibo.tuprolog.solve.exception.warning.MissingPredicate
import it.unibo.tuprolog.solve.extractSignature
import it.unibo.tuprolog.solve.flags.LastCallOptimization
import it.unibo.tuprolog.solve.flags.LastCallOptimization.ON
import it.unibo.tuprolog.solve.flags.Unknown
import it.unibo.tuprolog.theory.Theory
import it.unibo.tuprolog.utils.buffered
data class StateRuleSelection(override val context: ConcurrentExecutionContext) : State {
companion object {
private val catchSignature = Catch.signature
}
private fun exceptionalState(exception: ResolutionException): StateException =
StateException(exception, context.copy(step = nextStep()))
private fun missingProcedure(ruleSources: Sequence, missing: Signature): State =
when (val unknown = context.flags[Unknown]) {
Unknown.FAIL -> failureState
else -> {
if (ruleSources.none { missing.toIndicator() in it }) {
when (unknown) {
Unknown.ERROR -> exceptionalState(
ExistenceError.forProcedure(
context = context,
procedure = missing
)
)
Unknown.WARNING -> failureState.also {
context.warnings.write(
MissingPredicate(
context = context,
signature = missing
)
)
}
else -> failureState
}
} else {
failureState
}
}
}
private val ignoreState: StateGoalSelection
get() = StateGoalSelection(context.copy(goals = context.goals.next, step = nextStep()))
private val failureState: EndState
get() = StateEnd(
solution = Solution.no(context.query),
context = context.copy(step = nextStep())
)
override fun next(): Iterable {
val currentGoal = context.currentGoal!!
return when {
currentGoal.isVar ->
listOf(
exceptionalState(
InstantiationError.forGoal(
context = context,
procedure = context.procedure!!.extractSignature(),
variable = currentGoal.castToVar()
)
)
)
currentGoal.isStruct -> with(context) {
val currentGoalStruct = currentGoal.castToStruct()
val ruleSources = sequenceOf(libraries.theory, staticKb, dynamicKb)
when {
currentGoalStruct.isTruth -> {
listOf(
if (currentGoalStruct.isTrue) {
ignoreState
} else {
failureState
}
)
}
ruleSources.any { currentGoalStruct in it } -> {
val rules = ruleSources.flatMap { it.selectClauses(currentGoalStruct) }
rules.map {
if (context.isTailRecursive) {
StateRuleExecution(context.replaceWithChildAppendingRules(it))
} else {
StateRuleExecution(context.createChildAppendingRules(it))
}
}.asIterable()
}
else -> listOf(missingProcedure(ruleSources, currentGoalStruct.extractSignature()))
}
}
else -> listOf(
exceptionalState(
TypeError.forGoal(
context = context,
procedure = context.procedure!!.extractSignature(),
expectedType = TypeError.Expected.CALLABLE,
culprit = currentGoal
)
)
)
}
}
private val ConcurrentExecutionContext.isTailRecursive: Boolean
get() = goals.next.isOver && flags[LastCallOptimization] == ON && goals.current!!.let { currentGoal ->
currentGoal.asStruct()?.extractSignature()?.let {
it == procedure?.extractSignature() && it != catchSignature
} ?: false
}
private fun Theory.selectClauses(term: Struct): Sequence =
get(term).map { it.freshCopy() }.ensureRules().let {
if (isMutable) {
it.buffered()
} else {
it
}
}
override fun clone(context: ConcurrentExecutionContext): State = copy(context = context)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy