diff --git a/integraal/integraal-explanation/src/main/java/fr/boreal/explanation/api/explainers/QueryExplainer.java b/integraal/integraal-explanation/src/main/java/fr/boreal/explanation/api/explainers/QueryExplainer.java index a2ebdedaf3044cef92949fbfe3e5626cd74ec932..2fee7e271022aa03e54520c65bd5ba575c0f3875 100644 --- a/integraal/integraal-explanation/src/main/java/fr/boreal/explanation/api/explainers/QueryExplainer.java +++ b/integraal/integraal-explanation/src/main/java/fr/boreal/explanation/api/explainers/QueryExplainer.java @@ -8,8 +8,9 @@ import java.util.Set; * * @param <ExplanationType> the type of the (set of) explanations which is returned by the enumerator * @param <QueryType> the type of the query + * @param <ExplanationContext> the context to use for finding explanations (eg. a knowledge base, a factbase, a rulebase) */ -public interface QueryExplainer<ExplanationType, QueryType, KnowledgeBaseType> { +public interface QueryExplainer<ExplanationType, QueryType, ExplanationContext> { /** * @param query @@ -20,20 +21,18 @@ public interface QueryExplainer<ExplanationType, QueryType, KnowledgeBaseType> { /** * @param query * @return an iterator for the set of explanations for the query on the current KB - * TODO : */ default Iterator<ExplanationType> getExplanations(QueryType query) { return getAllExplanations(query).iterator(); } - ; - /** * Checks if an atom can be explained * * @param query + * @param context to use for finding explanations (eg. a knowledge base, a factbase, a rulebase) * @return true iff the explainer surpports the query and the knowledget base */ - boolean canExplain(KnowledgeBaseType kb, QueryType query); + boolean canExplain(ExplanationContext context, QueryType query); } diff --git a/integraal/integraal-explanation/src/main/java/fr/boreal/explanation/solving_enumerating/whyprovenance/UnambiguousProofTreeWhyProvenanceSolver.java b/integraal/integraal-explanation/src/main/java/fr/boreal/explanation/solving_enumerating/whyprovenance/UnambiguousProofTreeWhyProvenanceSolver.java index 9873dcf2a449ce2847778879f673ca819601109c..aeb48bdce03437d437550b0ec1ddc28c5a4ec143 100644 --- a/integraal/integraal-explanation/src/main/java/fr/boreal/explanation/solving_enumerating/whyprovenance/UnambiguousProofTreeWhyProvenanceSolver.java +++ b/integraal/integraal-explanation/src/main/java/fr/boreal/explanation/solving_enumerating/whyprovenance/UnambiguousProofTreeWhyProvenanceSolver.java @@ -11,9 +11,9 @@ import java.util.*; public class UnambiguousProofTreeWhyProvenanceSolver implements Solver { - private List<Triple> loadLevel(Atom current, LineageTracker gri) { + private List<Trigger> loadLevel(Atom current, LineageTracker gri) { var triggers = gri.getRuleInstancesYielding(current); - List<Triple> stack = new Stack<>(); + List<Trigger> stack = new Stack<>(); for (Map.Entry<Rule, Map<Substitution, Set<Atom>>> ruleEntry : triggers.entrySet()) { Rule rule = ruleEntry.getKey(); @@ -23,7 +23,7 @@ public class UnambiguousProofTreeWhyProvenanceSolver implements Solver { Substitution substitution = subEntry.getKey(); Set<Atom> atoms = subEntry.getValue(); - stack.add(new Triple(rule, substitution, atoms)); + stack.add(new Trigger(rule, substitution, atoms, current)); } } return stack; @@ -31,76 +31,82 @@ public class UnambiguousProofTreeWhyProvenanceSolver implements Solver { public Object computeAllExplanations(LineageTracker gri, Atom query, HashSet<Atom> intialAtoms) { - List<Object> currentProof = new ArrayList<>(); - Set<Atom> proved = new LinkedHashSet<>(); - List<List<Triple>> levels = new ArrayList<>(); - List<Atom> levelAtom = new ArrayList<>(); - List<Integer> levelPosition = new ArrayList<>(); - levelAtom.add(query); - int level = 0; - - while (level!=-1) { - - Atom current = levelAtom.get(level); - - if (levelPosition.size() == 0 || levelPosition.size() - 1 < level) { - //load level - levelPosition.add(0); - var alternativeTriggersForCurrent = this.loadLevel(current, gri); - - if (alternativeTriggersForCurrent.isEmpty()) { - proved.add(current); - if (levelAtom.size()-1==level) { - // we reached the end : print the solution - for (int i = 0; i < levels.size(); i++) { - System.out.println(levels.get(i).get(levelPosition.get(i))); - System.out.println(current); + char backtracked = '0'; + char loaded = '1'; + char lastOperation = loaded; + + // atom level + int k = 0; + List<List<Trigger>> levels = new ArrayList<>(); + levels.add(loadLevel(query, gri)); + + // atom alternative + ArrayList<Integer> jk = new ArrayList<>(); + jk.add(0); + + // list of seen and to prove atoms + List<Atom> toProve = new ArrayList<>(); + toProve.add(query); + List<Atom> provedAtoms = new ArrayList<>(); + provedAtoms.add(query); + List<Trigger> solutionTriggers = new ArrayList<>(); + + while (k >= 0) { + if (lastOperation == loaded) { + + if (levels.get(k).isEmpty()) { + //nothing to load into toProve + } else { + Trigger current = levels.get(k).get(jk.get(k)); + solutionTriggers.add(current); + toProve.remove(current.head); + provedAtoms.add(current.head); + + //load next atoms into toProve + for (Atom a : current.atoms()) { + if (!provedAtoms.contains(a)) { + toProve.add(a); } - //backtrack - level--; } - continue; } - levels.add(alternativeTriggersForCurrent); - } else { - // try to advance into level - var pos = levelPosition.get(level); - if (levels.get(level).size() - 1 == pos) { - level--; - continue; + + if (toProve.isEmpty()) { + System.out.println("Solution " + provedAtoms+"\n"); + solutionTriggers.forEach(System.out::println); + lastOperation = backtracked; } else { - levelPosition.add(level, pos + 1); + Atom next = toProve.remove(0); + //provedAtoms.add(next); + levels.add(loadLevel(next, gri)); + jk.add(0); + k++; + lastOperation = loaded; } + continue; } - - // find atoms for the next levels - Triple trigger = levels.get(level).get(levelPosition.get(level)); - for (Atom ancestor : trigger.atoms()) { - if (!proved.contains(ancestor)) { - levelAtom.add(ancestor); + if (lastOperation == backtracked) { + + if (levels.get(k).size() - 1 >= jk.get(k) + 1) { + // move to the next level + jk.set(k, jk.get(k) + 1); + var current = levels.get(k).get(jk.get(k)); + solutionTriggers.add(current); + provedAtoms.set(k, current.head); + lastOperation = loaded; + } else { + levels.remove(k); + jk.remove(k); + k--; } - } - proved.add(current); - - if (levelAtom.size()==level) { - // we reached the end : print the solution - for (int i = 0; i < levels.size(); i++) { - System.out.println(levels.get(i).get(levelPosition.get(i))); - } - //backtrack - level--; - continue; - } - if (levels.isEmpty()) { - break; } - level++; + } + return null; } - record Triple(Rule rule, Substitution substitution, Set<Atom> atoms) { + record Trigger(Rule rule, Substitution substitution, Set<Atom> atoms, Atom head) { } }