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

org.semanticweb.rulewerk.graal.GraalToRulewerkModelConverter Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package org.semanticweb.rulewerk.graal;

/*-
 * #%L
 * Rulewerk Graal Import Components
 * %%
 * Copyright (C) 2018 - 2020 Rulewerk Developers
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.semanticweb.rulewerk.core.model.api.Conjunction;
import org.semanticweb.rulewerk.core.model.api.Fact;
import org.semanticweb.rulewerk.core.model.api.PositiveLiteral;
import org.semanticweb.rulewerk.core.model.api.Predicate;
import org.semanticweb.rulewerk.core.model.api.Rule;
import org.semanticweb.rulewerk.core.model.api.Term;
import org.semanticweb.rulewerk.core.model.implementation.Expressions;

import fr.lirmm.graphik.graal.api.core.AtomSet;
import fr.lirmm.graphik.graal.api.core.ConjunctiveQuery;
import fr.lirmm.graphik.util.stream.CloseableIterator;
import fr.lirmm.graphik.util.stream.IteratorException;

/**
 * Utility class to convert
 * Graal data structures into
 * Rulewerk data structures. Labels ({@link ConjunctiveQuery#getLabel()},
 * {@link fr.lirmm.graphik.graal.api.core.Rule#getLabel() Rule.getLabel()}, or
 * {@link fr.lirmm.graphik.graal.api.core.Term#getLabel() Term.getLabel()}) are
 * not converted since Rulewerk does not support them.
 *
 * @author Adrian Bielefeldt
 *
 */
public final class GraalToRulewerkModelConverter {

	private GraalToRulewerkModelConverter() {
	}

	/**
	 * Converts a {@link fr.lirmm.graphik.graal.api.core.Atom Graal Atom} into a
	 * {@link PositiveLiteral Rulewerk PositiveLiteral}.
	 *
	 * @param atom                 A {@link fr.lirmm.graphik.graal.api.core.Atom
	 *                             Graal Atom}
	 * @param existentialVariables set of variables that are existentially
	 *                             quantified
	 * @return A {@link PositiveLiteral Rulewerk PositiveLiteral}
	 */
	public static PositiveLiteral convertAtom(final fr.lirmm.graphik.graal.api.core.Atom atom,
			final Set existentialVariables) {
		final Predicate predicate = convertPredicate(atom.getPredicate());
		final List terms = convertTerms(atom.getTerms(), existentialVariables);
		return Expressions.makePositiveLiteral(predicate, terms);
	}

	/**
	 * Converts a {@link fr.lirmm.graphik.graal.api.core.Atom Graal Atom} into a
	 * {@link Fact Rulewerk fact}.
	 *
	 * @param atom A {@link fr.lirmm.graphik.graal.api.core.Atom Graal Atom}
	 * @return A {@link Fact Rulewerk fact}
	 * @throws IllegalArgumentException if the converted atom contains terms that
	 *                                  cannot occur in facts
	 */
	public static Fact convertAtomToFact(final fr.lirmm.graphik.graal.api.core.Atom atom) {
		final Predicate predicate = convertPredicate(atom.getPredicate());
		final List terms = convertTerms(atom.getTerms(), Collections.emptySet());
		return Expressions.makeFact(predicate, terms);
	}

	/**
	 * Converts a {@link List} of {@link fr.lirmm.graphik.graal.api.core.Atom Graal
	 * Atoms} into a {@link List} of {@link PositiveLiteral Rulewerk
	 * PositiveLiterals}.
	 *
	 * @param atoms list of {@link fr.lirmm.graphik.graal.api.core.Atom Graal
	 *              Atoms}.
	 * @return A {@link List} of {@link PositiveLiteral Rulewerk PositiveLiterals}.
	 */
	public static List convertAtoms(final List atoms) {
		final List result = new ArrayList<>();
		for (final fr.lirmm.graphik.graal.api.core.Atom atom : atoms) {
			result.add(convertAtom(atom, Collections.emptySet()));
		}
		return result;
	}

	/**
	 * Converts a {@link List} of {@link fr.lirmm.graphik.graal.api.core.Atom Graal
	 * Atoms} into a {@link List} of {@link Fact Rulewerk facts}.
	 *
	 * @param atoms list of {@link fr.lirmm.graphik.graal.api.core.Atom Graal
	 *              Atoms}.
	 * @return A {@link List} of {@link Fact Rulewerk facts}.
	 */
	public static List convertAtomsToFacts(final List atoms) {
		final List result = new ArrayList<>();
		for (final fr.lirmm.graphik.graal.api.core.Atom atom : atoms) {
			result.add(convertAtomToFact(atom));
		}
		return result;
	}

	/**
	 * Converts a {@link AtomSet Graal AtomSet} into a {@link Conjunction Rulewerk
	 * Conjunction} of {@link PositiveLiteral}s.
	 *
	 * @param atomSet              A {@link AtomSet Graal AtomSet}
	 * @param existentialVariables set of variables that are existentially
	 *                             quantified
	 * @return A {@link Conjunction Rulewerk Conjunction}
	 */
	private static Conjunction convertAtomSet(final AtomSet atomSet,
			final Set existentialVariables) {
		final List result = new ArrayList<>();
		try (CloseableIterator iterator = atomSet.iterator()) {
			while (iterator.hasNext()) {
				result.add(convertAtom(iterator.next(), existentialVariables));
			}
		} catch (final IteratorException e) {
			throw new GraalConvertException(MessageFormat
					.format("Unexpected Iterator Exception when converting PositiveLiteralSet {0}}.", atomSet), e);
		}
		return Expressions.makeConjunction(result);
	}

	/**
	 * Converts a {@link fr.lirmm.graphik.graal.api.core.Predicate Graal Predicate}
	 * into a {@link Predicate Rulewerk Predicate}.
	 *
	 * @param predicate A {@link fr.lirmm.graphik.graal.api.core.Predicate Graal
	 *                  Predicate}
	 * @return A {@link Predicate Rulewerk Predicate}
	 */
	private static Predicate convertPredicate(final fr.lirmm.graphik.graal.api.core.Predicate predicate) {
		return Expressions.makePredicate(predicate.getIdentifier().toString(), predicate.getArity());
	}

	/**
	 * Converts a {@link ConjunctiveQuery Graal ConjunctiveQuery} into a
	 * {@link GraalConjunctiveQueryToRule}. Answering a Graal ConjunctiveQuery over
	 * a certain knowledge base is equivalent to adding a {@link Rule} to the
	 * knowledge base,  prior to reasoning. The rule consists of the query
	 * literals as the body and a single {@link PositiveLiteral} with a new
	 * predicate containing all the query variables as the head. After the reasoning
	 * process, in which the rule is materialised, is completed, this rule head can
	 * then be used as a query PositiveLiteral to obtain the results of the Graal
	 * ConjunctiveQuery.
	 *
	 * 

* WARNING: The supplied {@code ruleHeadPredicateName} will be used to * create a {@link Predicate} containing all answer variables from the * {@code conjunctiveQuery}. If a Predicate with the same name and arity is used * elsewhere in the same program, the result will differ from the one expected * from the Graal ConjunctiveQuery. *

* * @param ruleHeadPredicateName A name to create a program-unique predicate for * the query PositiveLiteral. * @param conjunctiveQuery A {@link ConjunctiveQuery Graal Query}. * @return A {@link GraalConjunctiveQueryToRule} equivalent to the * {@code conjunctiveQuery} input. */ public static GraalConjunctiveQueryToRule convertQuery(final String ruleHeadPredicateName, final ConjunctiveQuery conjunctiveQuery) { if (StringUtils.isBlank(ruleHeadPredicateName)) { throw new GraalConvertException(MessageFormat.format( "Rule head predicate for Graal ConjunctiveQuery {0} cannot be a blank string.", conjunctiveQuery)); } if (conjunctiveQuery.getAtomSet().isEmpty()) { throw new GraalConvertException(MessageFormat.format( "Graal ConjunctiveQuery {0} with empty body is not supported in Rulewerk.", conjunctiveQuery)); } if (conjunctiveQuery.getAnswerVariables().isEmpty()) { throw new GraalConvertException(MessageFormat.format( "Graal ConjunctiveQuery {0} with no answer variables is not supported in Rulewerk.", conjunctiveQuery)); } final Conjunction conjunction = convertAtomSet(conjunctiveQuery.getAtomSet(), Collections.emptySet()); final List answerVariables = convertTerms(conjunctiveQuery.getAnswerVariables(), Collections.emptySet()); return new GraalConjunctiveQueryToRule(ruleHeadPredicateName, answerVariables, conjunction); } /** * Converts a {@link fr.lirmm.graphik.graal.api.core.Rule Graal Rule} into a * {@link Rule Rulewerk Rule}. * * @param rule A {@link fr.lirmm.graphik.graal.api.core.Rule Graal Rule}. * @return A {@link Rule Rulewerk Rule}. */ public static Rule convertRule(final fr.lirmm.graphik.graal.api.core.Rule rule) { final Conjunction head = convertAtomSet(rule.getHead(), rule.getExistentials()); final Conjunction body = convertAtomSet(rule.getBody(), Collections.emptySet()); return Expressions.makePositiveLiteralsRule(head, body); } /** * Converts a {@link List} of {@link fr.lirmm.graphik.graal.api.core.Rule Graal * Rules} into a {@link List} of {@link Rule Rulewerk Rules}. * * @param rules A {@link List} of {@link fr.lirmm.graphik.graal.api.core.Rule * Graal Rules}. * @return A {@link List} of {@link Rule Rulewerk Rules}. */ public static List convertRules(final List rules) { final List result = new ArrayList<>(); for (final fr.lirmm.graphik.graal.api.core.Rule rule : rules) { result.add(convertRule(rule)); } return result; } /** * Converts a {@link fr.lirmm.graphik.graal.api.core.Term Graal Term} into a * {@link Term Rulewerk Term}. If the {@code term} is neither * {@link fr.lirmm.graphik.graal.api.core.Term#isVariable() Variable} nor * {@link fr.lirmm.graphik.graal.api.core.Term#isConstant() Constant}, a * {@link GraalConvertException} is thrown. * * @param term A {@link fr.lirmm.graphik.graal.api.core.Term} * @param existentialVariables set of variables that are existentially * quantified * @return A {@link Term Rulewerk Term}, with {@link Term#getName()} equal to * {@link fr.lirmm.graphik.graal.api.core.Term#getIdentifier()}, if it * is a Variable, and {@link Term#getName()} equal to * <{@link fr.lirmm.graphik.graal.api.core.Term#getIdentifier()}>, if it * is a Constant.
* Graal Variable with identifier "a" will be transformed to * rulewerk Variable with name "a". Graal Constant with identifier * "c" will be transformed to rulewerk Constant with name * "<c>". * * @throws GraalConvertException If the term is neither variable nor constant. */ private static Term convertTerm(final fr.lirmm.graphik.graal.api.core.Term term, final Set existentialVariables) { final String id = term.getIdentifier().toString(); if (term.isConstant()) { return Expressions.makeAbstractConstant(id); } else if (term.isVariable()) { if (existentialVariables.contains(term)) { return Expressions.makeExistentialVariable(id); } else { return Expressions.makeUniversalVariable(id); } } else { throw new GraalConvertException(MessageFormat.format( "Term {0} with identifier {1} and label {2} could not be converted because it is neither constant nor variable.", term, id, term.getLabel())); } } /** * Converts a {@link List} of {@link fr.lirmm.graphik.graal.api.core.Term Graal * Terms} into a {@link List} of {@link Term Rulewerk Terms}. * * @param terms A {@link List} of {@link fr.lirmm.graphik.graal.api.core.Term * Graal Terms} * @return A {@link List} of {@link Term Rulewerk Terms} */ private static List convertTerms(final List terms, final Set existentialVariables) { final List result = new ArrayList<>(); for (final fr.lirmm.graphik.graal.api.core.Term term : terms) { result.add(convertTerm(term, existentialVariables)); } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy