Coverage Summary for Class: CausalityModule (it.unibo.tuprolog.argumentation.causality.modules)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| CausalityModule |
100%
(1/1)
|
100%
(4/4)
|
|
100%
(7/7)
|
100%
(73/73)
|
package it.unibo.tuprolog.argumentation.causality.modules
import it.unibo.tuprolog.argumentation.causality.primitives.ButFor
import it.unibo.tuprolog.argumentation.causality.primitives.Ness
import it.unibo.tuprolog.argumentation.causality.primitives.NessIntervention
import it.unibo.tuprolog.argumentation.causality.primitives.NessOriginal
import it.unibo.tuprolog.argumentation.causality.primitives.NessOriginalIntervention
import it.unibo.tuprolog.argumentation.causality.runtime.CausalityAnalysis
import it.unibo.tuprolog.argumentation.core.modules.PrologModule
import it.unibo.tuprolog.argumentation.core.modules.graph.language.ParserModule
import it.unibo.tuprolog.core.operators.OperatorSet
import it.unibo.tuprolog.solve.Signature
import it.unibo.tuprolog.solve.primitive.Primitive
/**
* Whether a statement of a theory causes another (module `causality`): the NESS test, as published (Pisano, Prakken,
* Sartor, Liepina; ICAIL 2025) and revised, the revised one asking as well that an argument for the cause be IN in the
* grounded labelling of the theory, and the but-for test, on the grounded labelling of the theory and of its
* interventions. Unlike the modules of arg2p, each instance has a state of its own, the analysis computing the graphs
* (and caching them): a solver is given a new one. The solver of the analysis is built at the first test, and prints
* where the solver testing does.
*/
class CausalityModule : PrologModule("prolog.argumentation.causality.solver", "causality") {
private val analysis = CausalityAnalysis()
override val primitives: Map<Signature, Primitive>
get() =
listOf(Ness(analysis), NessIntervention(analysis), NessOriginal(analysis), NessOriginalIntervention(analysis), ButFor(analysis))
.associateBy { it.signature }
override val theoryOperators: OperatorSet
get() = super.theoryOperators.plus(ParserModule.operators())
override val prologRawTheory: String =
// language=Prolog
"""
%! subsets(?List, ?Subset)
% Subset is each subset of List, its elements in their order.
subsets([], []).
subsets([H|T], [H|NT]) :- subsets(T, NT).
subsets([_|T], NT) :- subsets(T, NT).
%! properSubsets(+List, -Subset)
% Subset is each subset of List other than the empty one and List itself.
properSubsets(L, S) :-
subsets(L, S),
S \= [],
S \= L.
%! generateInterventions(+Rules, +Cause, -Intervention)
% Intervention is each change of the theory removing Cause: its complement, the undercut of Cause (a rule,
% unless it is negated), or the complement with a set of the premises of the rules not among Rules (the top
% rules of the graph of the effect).
generateInterventions(_, S, [CS]) :-
compl(S, CS).
generateInterventions(_, S, [undercut(S)]) :-
S \= -_.
generateInterventions(R, S, SUP) :-
parser:::convertAllRules(_),
compl(S, CS),
unusedPremises(R, UP), !,
subsets(UP, SUP),
member(CS, SUP),
SUP \= [].
%! compl(?Statement, ?Complement)
% Complement is the complement of Statement (-X for X, X for -X).
compl(-X, X) :- !.
compl(X, -X).
%! unusedPremises(+Rules, -Premises)
% Premises are those of the rules of the theory not among Rules.
unusedPremises(R, UP) :-
findall(P, (parser::rule(Id, P, _), \+ member(Id, R), ground(Id)), RR),
utils::appendLists(RR, UP).
""".trimIndent()
}