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

fr.boreal.model.ruleCompilation.id.IDRuleCompilation Maven / Gradle / Ivy

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

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

import org.apache.commons.lang3.tuple.ImmutablePair;
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.Predicate;
import fr.boreal.model.logicalElements.api.Substitution;
import fr.boreal.model.logicalElements.api.Term;
import fr.boreal.model.logicalElements.factory.api.TermFactory;
import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory;
import fr.boreal.model.logicalElements.impl.AtomImpl;
import fr.boreal.model.logicalElements.impl.SubstitutionImpl;
import fr.boreal.model.partition.TermPartition;
import fr.boreal.model.rule.api.FORule;
import fr.boreal.model.ruleCompilation.api.RuleCompilationResult;
import fr.boreal.model.ruleCompilation.api.RuleCompilation;
import fr.boreal.model.ruleCompilation.api.RuleCompilationCondition;

/**
 * Version as implemented by Melanie in graal
 * Compilation for atomic rules (head and body) with no existential variables or constants
 */
public class IDRuleCompilation implements RuleCompilation {

	private final TermFactory tf = SameObjectTermFactory.instance();

	// a matrix for store conditions ( p -> q : [q][p] )
	private final Map>> conditions;

	/**
	 * Create a new empty compilation
	 */
	public IDRuleCompilation() {
		this.conditions = new HashMap<>();
	}

	@Override
	public void compile(RuleBase rb) {
		List compilable = this.extractCompilable(rb);
		this.createIDCondition(compilable.iterator());
		this.computeSaturation();
	}
	
	/**
	 * 
	 * 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.createIDCondition(compilable_rules.iterator());
		this.computeSaturation();
		
		return new RuleCompilationResult(this,compilable_rules, compilable_rules, non_compilable_rules);
	}

	@Override
	public boolean isMoreSpecificThan(Atom a, Atom b) {
		Predicate predB = a.getPredicate();
		Predicate predH = b.getPredicate();
		List conditions = this.getConditions(predB, predH);
		for (RuleCompilationCondition condition : conditions) {
			if (condition.check(a, b)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public Set> unfold(Atom a) {
		try {
			HashSet> res = new HashSet<>();
			res.add(new ImmutablePair<>(a, new SubstitutionImpl()));

			Predicate predH = a.getPredicate();
			Map> condH = this.conditions.get(predH);
			if (condH != null) {
				for (Map.Entry> entry : condH.entrySet()) {
					Predicate predB = entry.getKey();
					for (RuleCompilationCondition cond : entry.getValue()) {
						Pair, Substitution> ret = cond.instantiate(List.of(a.getTerms()));
						if (ret != null) {
							List generatedBody = ret.getKey();
							res.add(Pair.of(new AtomImpl(predB, generatedBody), ret.getValue()));
						}
					}
				}
			}
			return res;}
		catch(Exception e) {
			return null;
		}
	}


	@Override
	public boolean isCompatible(Predicate p, Predicate q) {
		if (p.equals(q))
			return true;
		else
			return !getConditions(p, q).isEmpty();
	}

	@Override
	public Set getCompatiblePredicates(Predicate p) {
		Set res = new HashSet<>();
		Map> condH = this.conditions.get(p);
		res.add(p);
		if (condH != null) {
			res.addAll(condH.keySet());
		}
		return res;
	}

	@Override
	public Set getHomomorphisms(Atom a, Atom b, Substitution s) {
		Set res = new HashSet<>();
		Predicate predB = b.getPredicate();
		Predicate predH = a.getPredicate();
		List conditions = this.getConditions(predB, predH);
		for (RuleCompilationCondition condition : conditions) {
			Substitution homo = condition.homomorphism(List.of(a.getTerms()), List.of(b.getTerms()), s);
			if (homo != null) {
				res.add(homo);
			}
		}
		return res;
	}

	@Override
	public Set getUnifications(Atom a, Atom b) {
		Set res = new HashSet<>();
		Predicate predB = a.getPredicate();
		Predicate predH = b.getPredicate();
		for (RuleCompilationCondition cond : this.getConditions(predB, predH)) {
			TermPartition unifier = cond.unifier(a, b);
			if (unifier != null) {
				res.add(unifier);
			}
		}
		return res;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for(Predicate q : this.conditions.keySet()) {
			for(Predicate p : this.conditions.get(q).keySet()) {
				for(RuleCompilationCondition c : this.conditions.get(q).get(p)) {
					sb.append(p).append(" <= ").append(q).append(" with ").append(c).append("\n");
				}
			}
		}
		return sb.toString();
	}


	private boolean addCompilation(Atom a, Atom b) {
		Predicate predBody = a.getPredicate();
		Predicate predHead = b.getPredicate();

		IDRuleCompilationCondition cond = new IDRuleCompilationCondition(a.getTerms(), b.getTerms());
        Map> condH = this.conditions.computeIfAbsent(predHead, k -> new HashMap<>());

        List conditions = condH.computeIfAbsent(predBody, k -> new ArrayList<>());
        if (!conditions.contains(cond)) {
			conditions.add(cond);
			return true;
		} else {
			return false;
		}
	}

	private List getConditions(Predicate predB, Predicate predH) {
		List res = new ArrayList<>();
		if (predB.equals(predH)) {
			ArrayList terms = new ArrayList<>(predB.arity());
			for (int i = 0; i < predH.arity(); i++) {
				terms.add(this.tf.createOrGetFreshVariable());
			}
			res.add(new IDRuleCompilationCondition(terms, terms));
		}
		Map> condH = this.conditions.get(predH);
		if (condH != null) {
			List condB = condH.get(predB);
			if(condB != null) {
				res.addAll(condB);
			}
		}
		return res;

	}

	/**
	 * Compute the saturation of this compilation
	 */
	private void computeSaturation() {
		// deep copy of conditions
		Map>> conditionsTmp = deepCopyMapMapList(this.conditions);
		// p -> q
		Predicate p, q;
		for (Map.Entry>> e : conditionsTmp.entrySet()) {
			q = e.getKey();
			for (Map.Entry> map : e.getValue().entrySet()) {
				p = map.getKey();
				for (RuleCompilationCondition conditionPQ : map.getValue()) {
					computeSaturation(conditionsTmp, p, q, conditionPQ);
				}
			}
		}
	}

	private void computeSaturation(
			Map>> conditionsTmp,
			Predicate p, Predicate q,
			RuleCompilationCondition conditionPQ) {
		Map> map = conditionsTmp.get(p);
		if (map != null) {
			for (Map.Entry> e : map.entrySet()) {
				Predicate r = e.getKey();
				for (RuleCompilationCondition conditionRP : e.getValue()) {
					RuleCompilationCondition conditionRQ = conditionRP.composeWith(conditionPQ);
					if (conditionRQ != null) {
						// filter trivial implication - p(x,y,z) -> p(x,y,z)
						if (!(r.equals(q) && conditionRQ.isIdentity())) {
							if (addCondition(r, q, conditionRQ)) {
								this.computeSaturation(conditionsTmp, r, q,
										conditionRQ);
							}
						}
					}
				}
			}
		}
	}

	private static Map>> deepCopyMapMapList(
			Map>> map) {
		Map>> tmp = new HashMap<>();
		for (Map.Entry>> e : map.entrySet()) {
			tmp.put(e.getKey(), deepCopyMapList(e.getValue()));
		}
		return tmp;
	}

	private static Map> deepCopyMapList(
			Map> map) {
		Map> tmp = new HashMap<>();
		for (Map.Entry> e : map.entrySet()) {
			tmp.put(e.getKey(), new ArrayList<>(e.getValue()));
		}
		return tmp;
	}

	private boolean addCondition(
			Predicate predBody,
			Predicate predHead,
			RuleCompilationCondition cond) {

        Map> condH = this.conditions.computeIfAbsent(predHead, k -> new HashMap<>());

		List conditions = condH.computeIfAbsent(predBody, k -> new ArrayList<>());
        if (!conditions.contains(cond)) {
			conditions.add(cond);
			return true;
		} else {
			return false;
		}
	}

	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) {
		return r.getBody().asAtomSet().size() == 1 &&
				r.getHead().asAtomSet().size() == 1 &&
				r.getExistentials().isEmpty() &&
				r.getConstants().isEmpty();
	}

	private void createIDCondition(Iterator compilable) {
		while (compilable.hasNext()) {
			FORule ru = compilable.next();
			Atom b = ru.getBody().asAtomSet().iterator().next();
			Atom h = ru.getHead().asAtomSet().iterator().next();
			this.addCompilation(b, h);
		}
	}



}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy