All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.boreal.model.ruleCompilation.HierarchicalRuleCompilation Maven / Gradle / Ivy

The newest version!
package fr.boreal.model.ruleCompilation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang3.tuple.Pair;

import fr.boreal.model.kb.api.RuleBase;
import fr.boreal.model.logicalElements.api.Atom;
import fr.boreal.model.logicalElements.api.FunctionalTerm;
import fr.boreal.model.logicalElements.api.Predicate;
import fr.boreal.model.logicalElements.api.Substitution;
import fr.boreal.model.logicalElements.api.Term;
import fr.boreal.model.logicalElements.api.Variable;
import fr.boreal.model.logicalElements.impl.AtomImpl;
import fr.boreal.model.logicalElements.impl.SubstitutionImpl;
import fr.boreal.model.partition.TermPartition;
import fr.boreal.model.partition.TermPartitionFactory;
import fr.boreal.model.rule.api.FORule;
import fr.boreal.model.ruleCompilation.api.RuleCompilationResult;
import fr.boreal.model.ruleCompilation.api.RuleCompilation;

/**
 * Version as implemented by Melanie in graal
 * 
* Compilation for : p(X, Y, ...) -> q(X, Y, ...) * - atomic rules (head and body) * - no existential variables * - no constants * - body and head atom have the same arity * - body and head atom have exactly the same variables at the same position * * @author Florent Tornil */ public class HierarchicalRuleCompilation implements RuleCompilation { private final Map> order; /** * Create a new empty compilation */ public HierarchicalRuleCompilation() { this.order = new HashMap<>(); } @Override public void compile(RuleBase rb) { List compilable = this.extractCompilable(rb); this.computeOrder(compilable); } /** * * Creates a record with the partition of the compiled rules. * */ @Override public RuleCompilationResult compileAndGet(RuleBase rb) { List snapshot_original_rulebase = new ArrayList<>(rb.getRules()); List compilable_rules = this.extractCompilable(rb); List non_compilable_rules = new ArrayList<>(snapshot_original_rulebase); non_compilable_rules.removeAll(compilable_rules); this.computeOrder(compilable_rules); return new RuleCompilationResult(this,compilable_rules, compilable_rules, non_compilable_rules); } @Override public boolean isMoreSpecificThan(Atom a, Atom b) { if(this.isCompatible(a.getPredicate(), b.getPredicate())) { for (int i = 0; i < a.getTerms().length; i++) { if (!a.getTerm(i).equals(b.getTerm(i))) { return false; } } return true; } else { return false; } } @Override public Set> unfold(Atom a) { Set> res = new HashSet<>(); res.add(Pair.of(a, new SubstitutionImpl())); for (Predicate p : this.getCompatiblePredicates(a.getPredicate())) { Atom u = new AtomImpl(p, a.getTerms()); res.add(Pair.of(u, new SubstitutionImpl())); } return res; } @Override public boolean isCompatible(Predicate p, Predicate q) { return p.equals(q) || this.order.getOrDefault(p, new HashSet<>()).contains(q); } @Override public Set getCompatiblePredicates(Predicate p) { Set res = new HashSet<>(); res.add(p); res.addAll(this.order.getOrDefault(p, new HashSet<>())); return res; } @Override public Set getHomomorphisms(Atom a, Atom b, Substitution s) { Set res = new HashSet<>(); if(this.isCompatible(a.getPredicate(), b.getPredicate())) { Substitution homomorphism = new SubstitutionImpl(); Iterator fatherTermsIt = List.of(a.getTerms()).iterator(); Iterator sonTermsIt = List.of(b.getTerms()).iterator(); while(fatherTermsIt.hasNext() && sonTermsIt.hasNext()) { Term fatherTerm = fatherTermsIt.next(); Term sonTerm = sonTermsIt.next(); if(fatherTerm.isFrozen(s)) { if(!s.createImageOf(fatherTerm).equals(sonTerm)) { return res; } } else if (fatherTerm.isFunctionalTerm()) { if(sonTerm.isFunctionalTerm()) { Substitution innerRes = ((FunctionalTerm)fatherTerm).homomorphism((FunctionalTerm)sonTerm, s); if(innerRes == null) { return res; } else { homomorphism = homomorphism.merged(innerRes).orElse(null); if(homomorphism == null) { return res; } } } else { return res; } } else if (!homomorphism.keys().contains(fatherTerm)) { homomorphism.add((Variable) fatherTerm, sonTerm); } else if (!homomorphism.createImageOf(fatherTerm).equals(sonTerm)) { return res; } } res.add(homomorphism); } return res; } @Override public Set getUnifications(Atom a, Atom b) { Set res = new HashSet<>(); if (this.isCompatible(b.getPredicate(), a.getPredicate())) { res.add(TermPartitionFactory.instance().getByPositionPartition(List.of(a, b))); } return res; } private List extractCompilable(RuleBase rb) { Iterator ruleSet = rb.getRules().iterator(); List compilable = new ArrayList<>(); Set toRemove = new HashSet<>(); while (ruleSet.hasNext()) { FORule r = ruleSet.next(); if (this.isCompilable(r)) { compilable.add(r); toRemove.add(r); } } for(FORule r : toRemove) { rb.remove(r); } return compilable; } private boolean isCompilable(FORule r) { Collection bodyAtoms = r.getBody().asAtomSet(); if(bodyAtoms.size() != 1 ) { return false; } Collection headAtoms = r.getBody().asAtomSet(); if(headAtoms.size() != 1 ) { return false; } Term[] body = r.getBody().asAtomSet().iterator().next().getTerms(); Term[] head = r.getHead().asAtomSet().iterator().next().getTerms(); if(body.length != head.length) { return false; } // Check if each variable is different Set variables = new HashSet<>(); for(Term t : body) { if(!variables.add(t)) { return false; } } for(int i = 0; i < body.length; i++) { // Check for constants and same variables (include existential check) if(!body[i].isVariable() || !body[i].equals(head[i])) { return false; } } return true; } private void computeOrder(List compilable) { for(FORule rule : compilable) { Predicate body = rule.getBody().asAtomSet().iterator().next().getPredicate(); Predicate head = rule.getHead().asAtomSet().iterator().next().getPredicate(); Set hierarchie = this.order.getOrDefault(head, new HashSet<>()); hierarchie.add(body); this.order.put(head, hierarchie); this.updateTransitiveClosure(body, head); } } private void updateTransitiveClosure(Predicate body, Predicate head) { // Added rule body -> head // Add transitivity for X -> body -> head // As X -> head Set hierarchieBody = this.order.getOrDefault(body, new HashSet<>()); Set hierarchieHead = this.order.get(head); hierarchieHead.addAll(hierarchieBody); this.order.put(head, hierarchieHead); // Added rule body -> head // Add transitivity X -> head -> Y // As X -> Y for(Entry> entry : this.order.entrySet()) { if(entry.getValue().contains(head)) { Set newHierarchieX = entry.getValue(); newHierarchieX.addAll(hierarchieHead); this.order.put(entry.getKey(), newHierarchieX); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy