Coverage Summary for Class: StateGoalSelection (it.unibo.tuprolog.argumentation.core.engine.fsm)

Class Method, % Branch, % Line, % Instruction, %
StateGoalSelection 100% (2/2) 100% (14/14) 100% (39/39) 100% (305/305)
StateGoalSelection$Companion
Total 100% (2/2) 100% (14/14) 100% (39/39) 100% (305/305)


 // Forked from 2p-kt's solve-prolog 3.0.2 (Apache License 2.0): see README.md in this package
 package it.unibo.tuprolog.argumentation.core.engine.fsm
 
 import it.unibo.tuprolog.argumentation.core.engine.PrologExecutionContext
 import it.unibo.tuprolog.argumentation.core.engine.RelevantGoals
 import it.unibo.tuprolog.solve.Solution
 import it.unibo.tuprolog.solve.flags.TrackVariables
 
 /**
  * "Goal Selection", the entry point of every resolution step: decides what to do with
  * [PrologExecutionContext.goals]. Three cases: no goals left and no parent context -> emit the current
  * substitution as a solution and move to `StateEnd`; no goals left but a parent exists -> pop the stack, carrying
  * the child's substitution (filtered down to variables the parent still cares about, via
  * [PrologExecutionContext.isVariableInteresting]) into the parent, and loop back into `StateGoalSelection` for
  * the parent's remaining goals; goals remain -> move to `StatePrimitiveSelection` (after recording the current
  * goal's variables as relevant, if `TrackVariables` is `ON`).
  */
 data class StateGoalSelection(
     override val context: PrologExecutionContext,
 ) : AbstractState(context) {
     @Suppress("ktlint:standard:discouraged-comment-location")
     override fun computeNext(): State =
         if (context.goals.isOver) {
             if (context.isRoot) {
                 StateEnd(
                     Solution.yes(context.query, context.substitution),
                     context.copy(step = nextStep()),
                 )
             } else {
                 // The bindings of the variables of no more interest are dropped once the substitution has doubled
                 // since it was last trimmed (arg2p: trimming it at every frame left made each step cost as much as
                 // all the variables in the frames above): keeping them a little longer does not change anything else
                 val trim = context.substitution.size > maxOf(MIN_TRIMMED_SIZE, 2 * context.trimmedSize)
                 val substitution =
                     if (trim) {
                         context.substitution.filter { (it, _) -> context.isVariableInteresting(it) }.castToUnifier()
                     } else {
                         context.substitution
                     }
                 StateGoalSelection(
                     context.parent!!.let {
                         it.copy(
                             choicePoints = context.choicePoints,
                             flags = context.flags,
                             dynamicKb = context.dynamicKb,
                             staticKb = context.staticKb,
                             substitution = substitution,
                             trimmedSize = if (trim) substitution.size else context.trimmedSize,
                             goals = it.goals.next, // go on with parent's goals
                             procedure = it.procedure,
                             step = nextStep(),
                             startTime = context.startTime,
                             operators = context.operators,
                             inputChannels = context.inputChannels,
                             outputChannels = context.outputChannels,
                             // The libraries of an inlined call only apply to its goal
                             libraries = if (context.inlined) it.libraries else context.libraries,
                             customData = context.customData,
                         )
                     },
                 )
             }
         } else if (context.flags[TrackVariables] == TrackVariables.ON) {
             StatePrimitiveSelection(
                 context.copy(
                     step = nextStep(),
                     relevantGoals = RelevantGoals(context.goals.current!!, context.relevantGoals),
                 ),
             )
         } else {
             StatePrimitiveSelection(
                 context.copy(step = nextStep()),
             )
         }
 
     private companion object {
         const val MIN_TRIMMED_SIZE = 32
     }
 }