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

fr.boreal.model.partition.TermPartition Maven / Gradle / Ivy

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

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.SubstitutionImpl;
import fr.boreal.model.query.api.FOQuery;
import fr.boreal.model.rule.api.Rule;

/**
 * @author Guillaume Pérution-Kihli
 * @author Florent Tornil
 * 
* Partition of terms * Adds method specific for terms in addition to partition ones */ public class TermPartition extends Partition { /** * Cache for valid property */ Map valid = new HashMap<>(); /** * Cache for associated substitution property */ Map, Substitution> associatedSubstitution = new HashMap<>(); /** * Comparator used when choosing a representative of a class * Chooses constants first * @return the comparator */ private static Comparator getComparator() { return((t1, t2) -> { if((t1.isFrozen(null)) && (t2.isFrozen(null))) { return 0; } else if(t1.isFrozen(null)) { return -1; } else if(t2.isFrozen(null)) { return 1; } return 0; }); } /** * Creates a new empty TermPartition */ public TermPartition () { super(getComparator()); } /** * Creates a new TermPartition with the given elements, each in its own class * @param initialElements the initial elements of this partition */ public TermPartition (Set initialElements) { super(initialElements, getComparator()); } /** * Creates a new TermPartition with the given classes * @param partition the initial elements represented as multiple partitions */ public TermPartition (Collection> partition) { super(partition, getComparator()); } /** * Creates the TermPartition induced by a substitution * I.e., foreach variable v mapped to a term t through the substitution, * v and t are in the same class, and the partition is the finest for * this property * @param substitution the substitution to transform into a partition */ public TermPartition (Substitution substitution) { for (Map.Entry mapTo: substitution.toMap().entrySet()) { this.union(mapTo.getKey(), mapTo.getValue()); } } /** * Creates a new TermPartition, copying the given one * @param toCopy partition to copy */ public TermPartition (Partition toCopy) { super(toCopy, getComparator()); } //////////////////// // PUBLIC METHODS // //////////////////// /** * @param rule a rule * @return false iff a class of the receiving partition * contains two constants, * or contains two existential variable of R, * or contains a constant and an existential variable of R, * or contains an existential variable of R and a frontier variable of R */ public synchronized boolean isValid(Rule rule) { if (!valid.containsKey(rule)) { boolean result = this.isValid(rule, null); valid.put(rule, result); return result; } else { return valid.get(rule); } } /** * Takes into account answer variables of a context query, preventing them to be associated with an existential variable of the rule * @param rule a rule * @param context the query in which to test the validity * @return false iff a class of the receiving partition * contains two constants, * or contains two existential variable of R, * or contains a constant and an existential variable of R, * or contains an existential variable of R and a frontier variable of R, * or an existential and an answer variable of the context */ public boolean isValid(Rule rule, FOQuery context) { for (Collection cl : this.getClasses()) { boolean hasCst = false, hasExistFromRule= false, hasFr = false, hasAnsVar = false; for (Term term : cl) { if (term.isFrozen(null)) { if (hasCst || hasExistFromRule) { valid.put(rule, false); return false; } hasCst = true; } else if (rule.getExistentials().contains(term)) { if (hasExistFromRule || hasCst || hasFr || hasAnsVar) { return false; } hasExistFromRule = true; } else if (rule.getFrontier().contains(term)) { if (hasExistFromRule) { return false; } hasFr = true; } else if(context != null && context.getAnswerVariables().contains(term)) { if (hasExistFromRule) { return false; } hasAnsVar = true; } } } return true; } /** * @param sep a set of variables * @param rule a rule * @return the subset of sep containing variables that are in the same class as * an existential variable of rule. */ public Set getSeparatingStickyVariables(Set sep, Rule rule) { Set separatingStickyVariables = new HashSet<>(); for (Collection classs : this.getClasses()) { if (classs.stream().anyMatch(rule.getExistentials()::contains)) { classs.stream().filter(sep::contains).map(t -> (Variable)t).forEach(separatingStickyVariables::add); } } return separatingStickyVariables; } /** * Compute the substitution associated with this partition. * This method computes a substitution by choosing one representative term by * class. * The representative is chosen for each class as : * 1. The constant (if any) * 2. The answer variable of the context (if any) * 3. The variables of the context (if any) * 4. A random term of the class *
* Return an empty optional if the partition contain two constants in the same class * @param context a query for context (answer variables) * @return the substitution associated with this partition in the given context */ public synchronized Optional getAssociatedSubstitution(FOQuery context) { if (!associatedSubstitution.containsKey(context)) { Substitution subs = new SubstitutionImpl(); Collection contextAnswerVariables = new ArrayList<>(); Collection contextVariables = new ArrayList<>(); if(context != null) { contextAnswerVariables = context.getAnswerVariables(); contextVariables = context.getFormula().getVariables(); } for (Collection classs : getClasses()) { Term representative = null; for(Term term : classs) { // initialize the representative of the class with the context-free representative of the partition // constant if any then any variable if(representative == null) { representative = this.getRepresentative(term); } // Only one constant should exist in a given class if((term.isFrozen(null)) && !representative.equals(term)) { return Optional.empty(); } // If the representative is a variable // Prioritize answer variables of the context // and then other variables of the context if(representative.isVariable() && ! contextAnswerVariables.contains(representative) && contextVariables.contains(term)) { representative = term; } } for(Term term : classs) { if(term.isVariable()) { subs.add((Variable)term, representative); } } } associatedSubstitution.put(context, subs); return Optional.of(subs); } else { return Optional.ofNullable(associatedSubstitution.get(context)); } } /** * * @param s a substitution * @return a new partition that represents this partition on which the given substitution have been applied */ public TermPartition createImageWith(Substitution s) { TermPartition p = new TermPartition(); for(Set elements : this.getClasses()) { p.addClass(elements.stream().map(s::createImageOf).collect(Collectors.toSet())); } return p; } @Override protected void eraseMemoizedValues () { super.eraseMemoizedValues(); valid = new HashMap<>(); associatedSubstitution = new HashMap<>(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy