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

fr.lirmm.boreal.util.Rules Maven / Gradle / Ivy

The newest version!
package fr.lirmm.boreal.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.collect.Sets;

import fr.boreal.model.formula.FOFormulas;
import fr.boreal.model.formula.api.FOFormula;
import fr.boreal.model.formula.api.FOFormulaConjunction;
import fr.boreal.model.formula.api.FOFormulaNegation;
import fr.boreal.model.formula.factory.FOFormulaFactory;
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.api.Variable;
import fr.boreal.model.logicalElements.factory.api.TermFactory;
import fr.boreal.model.logicalElements.factory.impl.SameObjectPredicateFactory;
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.rule.api.FORule;
import fr.boreal.model.rule.impl.FORuleImpl;

/**
 * Utility class for rules
 */
public final class Rules {

	/**
	 * Generate a set of mono-piece rules equivalent of the specified rule.
	 * 
	 * @param rule rule to split into single piece
	 * @return a Collection of Rule which is a decomposition of the specified rule to single piece rules.
	 */
	public static Collection computeSinglePiece(FORule rule) {
		Collection monoPiece = new LinkedList<>();
		PiecesSplitter splitter = new PiecesSplitter(true, rule.getExistentials());

		for (Collection piece : splitter.split(rule.getHead().asAtomSet())) {
			Collection piece_as_formula = new HashSet<>(piece);
			monoPiece.add(new FORuleImpl(
					rule.getBody(),
					FOFormulaFactory.instance().createOrGetConjunction(piece_as_formula)));
		}
		return monoPiece;
	}
	
	/**
	 * @param rule the rule to get the positive part of the body
	 * @return the conjunction representing the positive parts of the body of the given rule
	 */
	public static FOFormula getPositiveBodyPart(FORule rule) {
		Set bodyPositive = new HashSet<>();
		
		FOFormula body = rule.getBody();
		if(body.isAtomic()) {
			bodyPositive.add(body);
		} else if(body.isDisjunction()) {
			throw new UnsupportedOperationException("Cannot decompose a disjunctive rule into positive part.");
		} else if(body.isNegation()) {
			// Do nothing
		} else if(body.isConjunction()) {
			for(FOFormula f : ((FOFormulaConjunction)body).getSubElements()) {
				if(f.isAtomic()) {
					bodyPositive.add(f);
				} else if(f.isNegation()) {
					// Do nothing
				} else {
					throw new UnsupportedOperationException("Cannot decompose a rule with multiple layers of imbrication into positive parts.");
				}
			}
		} else {
			throw new UnsupportedOperationException("Unsupported rule type for rule : " + rule);
		}
		return FOFormulaFactory.instance().createOrGetConjunction(bodyPositive);
	}
	
	/**
	 * @param rule the rule to get the negative parts of the body
	 * @return the conjunction representing the negative parts of the body of the given rule
	 */
	public static FOFormula getNegativeBodyParts(FORule rule) {
		Set negativeParts = new HashSet<>();
	
		FOFormula body = rule.getBody();
		if(body.isAtomic()) {
			// Do nothing
		} else if(body.isDisjunction()) {
			throw new UnsupportedOperationException("Cannot decompose a disjunctive rule into negative parts.");
		} else if(body.isNegation()) {
			negativeParts.add(body);
		} else if(body.isConjunction()) {
			for(FOFormula f : ((FOFormulaConjunction)body).getSubElements()) {
				if(f.isAtomic()) {
					// Do nothing
				} else if(f.isNegation()) {
					negativeParts.add(((FOFormulaNegation)f).element());
				} else {
					throw new UnsupportedOperationException("Cannot decompose a rule with multiple layers of imbrication into negative parts.");
				}
			}
		} else {
			throw new UnsupportedOperationException("Unsupported rule type for rule : " + rule);
		}
		return FOFormulaFactory.instance().createOrGetConjunction(negativeParts);
	}

	/**
	 * Generate a set of safe-negative rules equivalent of the specified rule.
	 * A rule is safe-negative iff each negative part contains only variables that appear in the positive part.
	 * 

* Let R a rule, * B+ the positive part of R, * B- = A1, ..., Ak a negative part of R *

* This decomposition replaces each B- by a new atom and * adds a rule R' = B- -> p(x1, ..., xj) where x1, ..., xj are the variables that appear both in B+ and B-. * * @param rule rule to decompose into safe negation * @return a Collection of rule which is a decomposition of the specified rule to safe-negation rules. */ public static Collection computeSafeNegation(FORule rule) { Set safeNegative = new HashSet<>(); Set bodyPositive = new HashSet<>(); Set negativeParts = new HashSet<>(); FOFormula body = rule.getBody(); if(body.isAtomic()) { safeNegative.add(rule); } else if(body.isDisjunction()) { throw new UnsupportedOperationException("Cannot decompose a disjunctive rule into safe-negation."); } else if(body.isNegation()) { negativeParts.add(body); } else if(body.isConjunction()) { for(FOFormula f : ((FOFormulaConjunction)body).getSubElements()) { if(f.isAtomic()) { bodyPositive.add(f); } else if(f.isNegation()) { negativeParts.add(((FOFormulaNegation)f).element()); } else { throw new UnsupportedOperationException("Cannot decompose a rule with multiple layers of imbrication into safe-negation."); } } } else { throw new UnsupportedOperationException("Unsupported rule type for rule : " + rule); } for(FOFormula negativePart : negativeParts) { Set bodyPositiveVariables = bodyPositive.stream() .map(FOFormula::getVariables) .flatMap(Set::stream) .collect(Collectors.toSet()); List linkedVariables = new ArrayList<>(Sets.intersection(bodyPositiveVariables, negativePart.getVariables())); Predicate freshPredicate = SameObjectPredicateFactory.instance().createOrGetFreshPredicate(linkedVariables.size()); Atom helper = new AtomImpl(freshPredicate, linkedVariables); FORule helperPositiveRule = new FORuleImpl(negativePart, helper); safeNegative.add(helperPositiveRule); FOFormula notHelper = FOFormulaFactory.instance().createOrGetNegation(helper); FOFormula safeBody = FOFormulaFactory.instance().createOrGetConjunction(Sets.union(bodyPositive, Set.of(notHelper))); FORule safeInitialRule = new FORuleImpl(safeBody, rule.getHead()); safeNegative.add(safeInitialRule); } return safeNegative; } /** * Create a new rule corresponding to the given rule by renaming all the variables with fresh variables * * @param rule to rename * @return a new rule corresponding to the given rule by renaming all the variables with fresh variables */ public static FORule freshRenaming(FORule rule) { TermFactory tf = SameObjectTermFactory.instance(); Substitution s = new SubstitutionImpl(); for(Variable v : rule.getBody().getVariables()) { if(!s.keys().contains(v)) { s.add(v, tf.createOrGetFreshVariable()); } } for(Variable v : rule.getHead().getVariables()) { if(!s.keys().contains(v)) { s.add(v, tf.createOrGetFreshVariable()); } } return Rules.createImageWith(rule, s); } /** * @param r the rule to apply the substitution on * @param s the substitution to apply * @return a new FORule corresponding to the given FORule in which the * given substitution have been applied */ public static FORule createImageWith(FORule r, Substitution s) { FOFormula body = FOFormulas.createImageWith(r.getBody(), s); FOFormula head = FOFormulas.createImageWith(r.getHead(), s); return new FORuleImpl(body, head); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy