Coverage Summary for Class: ExpandedAttackIn (it.unibo.tuprolog.argumentation.core.primitives.graph)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| ExpandedAttackIn |
100%
(1/1)
|
100%
(2/2)
|
50%
(2/4)
|
100%
(7/7)
|
97.4%
(37/38)
|
package it.unibo.tuprolog.argumentation.core.primitives.graph
import it.unibo.tuprolog.argumentation.core.primitives.PrimitiveWithSignature
import it.unibo.tuprolog.argumentation.core.runtime.Arg2pUnificator
import it.unibo.tuprolog.argumentation.core.runtime.context.contextLibrary
import it.unibo.tuprolog.core.Integer
import it.unibo.tuprolog.core.Struct
import it.unibo.tuprolog.core.Term
import it.unibo.tuprolog.core.Var
import it.unibo.tuprolog.solve.ExecutionContext
import it.unibo.tuprolog.solve.Signature
import it.unibo.tuprolog.solve.primitive.Solve
// The answers of a reader: each candidate unified with the arguments of the request, its variables renamed, as
// those of a clause read from the context are
private fun Solve.Request<ExecutionContext>.answers(
arguments: List<Term>,
candidates: Sequence<List<Term>>,
): Sequence<Solve.Response> {
val goal = Struct.of("t", arguments)
return candidates.mapNotNull { values ->
Arg2pUnificator.mgu(goal, Struct.of("t", values).freshCopy()).takeIf { it.isSuccess }?.let { replyWith(it) }
}
}
// The attacks to look at: those on the attacked argument or by the attacker if given, all of them otherwise
private fun ExpandedAttacks.candidates(
attacker: Term?,
attacked: Term?,
): List<AttackIds> =
when {
attacked != null -> byAttacked[attacked].orEmpty()
attacker != null -> byAttacker[attacker].orEmpty()
else -> attacks
}
/** graphStore::expandedAttackById(?Type, ?IdAttacker, ?IdAttacked, ?IdOn): the attacks, saved or extended (see [ExpandedAttacks]), by identifiers */
internal object ExpandedAttackById : PrimitiveWithSignature {
override val signature = Signature("expandedAttackById", 4)
override fun solve(request: Solve.Request<ExecutionContext>): Sequence<Solve.Response> {
val (_, attacker, attacked, _) = request.arguments
val attacks = request.expandedAttacks().candidates(attacker.takeUnless { it is Var }, attacked.takeUnless { it is Var })
return request.answers(request.arguments, attacks.asSequence().map { listOf(it.type, it.attacker, it.attacked, it.on) })
}
}
// The attacks, saved or extended, as arguments rather than identifiers (those of argument/1 terms, see context_id/2),
// in the given branch (the active one if null)
private fun Solve.Request<ExecutionContext>.attacksByTerms(
arguments: List<Term>,
branch: Int?,
): Sequence<Solve.Response> {
val (_, attacker, attacked, _) = arguments
val context = contextLibrary
// an argument saved has an identifier; any other is unified with each attack, as an instance of an argument saved
// with variables may be (the variables of a conclusion bound by an attack)
val (idAttacker, idAttacked) =
listOf(attacker, attacked).map { argument ->
argument.takeIf { it.isGround }?.let { context.knownIdentifier(Struct.of("argument", it)) }?.let { Integer.of(it) }
}
val argument = { id: Term ->
id
.asInteger()
?.let { context.term(it.intValue.toInt()) }
?.castToStruct()
?.get(0)
}
val attacks = expandedAttacks(branch).candidates(idAttacker, idAttacked)
return answers(
arguments,
attacks.asSequence().mapNotNull { attack ->
listOf(attack.attacker, attack.attacked, attack.on).map { argument(it) ?: return@mapNotNull null }.let {
listOf(attack.type) +
it
}
},
)
}
/** graphStore::expandedAttack(?Type, ?Attacker, ?Attacked, ?On): the attacks, saved or extended (see [ExpandedAttacks]) */
internal object ExpandedAttack : PrimitiveWithSignature {
override val signature = Signature("expandedAttack", 4)
override fun solve(request: Solve.Request<ExecutionContext>): Sequence<Solve.Response> = request.attacksByTerms(request.arguments, null)
}
/** graphStore::expandedAttackIn(+Branch, ?Type, ?Attacker, ?Attacked, ?On): as expandedAttack/4, in the given branch */
internal object ExpandedAttackIn : PrimitiveWithSignature {
override val signature = Signature("expandedAttackIn", 5)
override fun solve(request: Solve.Request<ExecutionContext>): Sequence<Solve.Response> {
val branch =
request.arguments[0]
.asInteger()
?.intValue
?.toInt() ?: return emptySequence()
return request.attacksByTerms(request.arguments.drop(1), branch)
}
}