% This file is part of the Attempto Parsing Engine (APE). % Copyright 2008-2010, Kaarel Kaljurand . % % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it % under the terms of the GNU Lesser General Public License as published by the Free Software % Foundation, either version 3 of the License, or (at your option) any later version. % % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR % PURPOSE. See the GNU Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public License along with the Attempto % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. :- module(implication_to_swrl, [ implication_to_swrl/3 ]). :- use_module(drs_to_owlswrl_core, [ is_toplevel/3, get_entity/3, condlist_and/4, is_object_with_generalized_quantifier/1, has_dom_for_member/3, dataitem_datavalue_datatypeuri/3 ]). /** DRS implication to SWRL-rule translator Translate an Attempto DRS implication into Semantic Web Rule Language (SWRL) rule. We use the SWRL rule syntax specified in TODO: add a constraint that the variables in the head is a subset of the variables in the body. @author Kaarel Kaljurand @version 2010-12-14 */ %% implication_to_swrl(+Condition:term, +RefList:list, -Implies:term) is semidet. % % @param Condition is a DRS implication condition % @param RefList is a list of DRS toplevel referents % @param Implies is a SWRL 'DLSafeRule'-rule % implication_to_swrl( '=>'(CondList1, CondList2), RefList, 'DLSafeRule'('Body'(AtomList1), 'Head'(AtomList2)) ) :- condlist_atomlist(CondList1, RefList, AtomList1), condlist_atomlist(CondList2, RefList, AtomList2). %% condlist_atomlist(+ConditionList:list, +RefList:list, -AtomList:list) is det. % % Note that most conditions can produce several SWRL atoms because % an argument of the condition can be a complex expression which % will have to be unravelled into multiple SWRL builtins. % % @param ConditionList is a list of DRS conditions % @param RefList is a list of DRS toplevel referents % @param AtomList is list of SWRL atoms % condlist_atomlist([], _, []). % Attempt to roll up the whole condition list into a class expression % E.g.: If X loves Y and Y loves X then X is a man. % We need an additional contraint that it exposes all the variables % that are also present in the body. %condlist_atomlist(CondList, RefList, ['ClassAtom'(Class, OutX)]) :- % condlist_and(X, CondList, RefList, Class), % get_argument(X, RefList, object, OutX, _). % BUG: Experimental % Ignore 'something', 'thing', 'X', etc. % The idea is that otherwise they would be typed as owl:Thing, % i.e. as objects, but maybe the DRS uses them in data expressions. % So we don't want to make the object vs data distinction yet. % Test: If X = 1 + 2 then X = 3. % Test: If there is X and there is Y then X knows Y. % Test: For everything John likes Mary. % Since some conditions are ignored it might happen that the % head or the body becomes empty, but this is OK I guess. condlist_atomlist([Condition | ConditionList], RefList, AtomList) :- has_dom_for_member(_Ref, [Condition], []), !, condlist_atomlist(ConditionList, RefList, AtomList). condlist_atomlist([Condition | ConditionList], RefList, AtomList) :- condition_atomlist(Condition, RefList, AtomList1), condlist_atomlist(ConditionList, RefList, AtomList2), append(AtomList1, AtomList2, AtomList). /* % BUG: experimental % BUG: Add a restriction that all variables used in predicate-conditions % must be declared in object-conditions. condlist_atomlist([], _RefList, []). condlist_atomlist([Condition | CondList], RefList, [Atom | AtomList]) :- ( Condition = object(D, Value, countable, na, _, _)-_ -> get_entity(class, Value, NamedClass), select(Condition1, CondList, CondList1), condlist_class(D, Condition1, CondList1, RefList, AndClass, CondList2), Atom = 'description'(and(NamedClass, AndClass), 'I-variable'(D)) ; condition_atom(Condition, RefList, Atom), CondList2 = CondList ), condlist_atomlist(CondList2, RefList, AtomList). */ %% condition_atomlist(+Condition:term, -Atoms:list) is det. % % @param Condition is a DRS condition % @param RefList is a list of DRS toplevel referents % @param Atoms is a list of SWRL atoms % % We allow no generalized quantifiers condition_atomlist(Condition, _, _) :- is_object_with_generalized_quantifier(Condition), !, fail. condition_atomlist(formula(Expr1, Comp, Expr2)-_, RefList, Builtins) :- expr_to_builtins(Expr1, Var1, B1), expr_to_builtins(Expr2, Var2, B1, B2), add_relation(Comp, Var1, Var2, RefList, B2, Builtins). condition_atomlist(object(X, Value, _, na, _, _)-_, _, ['ClassAtom'(NamedClass, Variable)]) :- get_variable(X, Variable), get_entity(class, Value, NamedClass). condition_atomlist('-'([predicate(_, be, X1, X2)-_]), RefList, ['DifferentIndividualsAtom'(OutX1, OutX2)]) :- get_argument(X1, RefList, object, OutX1, _), get_argument(X2, RefList, object, OutX2, _). condition_atomlist(predicate(_, be, X1, X2)-_, RefList, ['SameIndividualAtom'(OutX1, OutX2)]) :- get_argument(X1, RefList, object, OutX1, _), get_argument(X2, RefList, object, OutX2, _). condition_atomlist(predicate(_, Value, X1, X2)-_, RefList, ['DataPropertyAtom'(DataProperty, OutX1, OutX2) | L]) :- Value \= be, get_entity(data_property, Value, DataProperty), get_argument(X1, RefList, object, OutX1, L1), get_argument(X2, RefList, data, OutX2, L2), append(L1, L2, L). condition_atomlist(predicate(_, Value, X1, X2)-_, RefList, ['ObjectPropertyAtom'(ObjectProperty, OutX1, OutX2)]) :- Value \= be, get_entity(object_property, Value, ObjectProperty), get_argument(X1, RefList, object, OutX1, _), get_argument(X2, RefList, object, OutX2, _). % Sublist % E.g. If a man owns a car then the man likes the car and likes exactly 3 cats. % E.g. If John owns a car then Mary likes a car and likes at most 3 cats. condition_atomlist([C | Cs], RefList, ['ClassAtom'(SubListClass, OutX)]) :- condlist_and(X, [C | Cs], RefList, SubListClass), get_argument(X, RefList, object, OutX, _). % Note that X can point to an Individual (i.e. not only a variable), % see e.g. "If John does not like Mary then a man does not like a woman." condition_atomlist('-'(Not), RefList, ['ClassAtom'('ObjectComplementOf'(NotClass), OutX)]) :- condlist_and(X, Not, RefList, NotClass), get_argument(X, RefList, object, OutX, _). % Note that X can point to an Individual. condition_atomlist('v'(Or1, Or2), RefList, ['ClassAtom'('ObjectUnionOf'([Or1Class, Or2Class]), OutX)]) :- condlist_and(X, Or1, RefList, Or1Class), condlist_and(X, Or2, RefList, Or2Class), get_argument(X, RefList, object, OutX, _). %% get_argument(+X:term, +RefList:list, -Type:atom, -Argument:term, -Atoms:list) is det. % % @param X is a discourse referent, expr-term, int/1, real/1, or string/1 % @param RefList is a list of DRS toplevel referents % @param Type is the type of the argument, i.e. one of {data, object, _} % @param Argument is a SWRL variable, OWL individual, or OWL data value % @param Atoms is a list of SWRL atoms (empty if X produces no builtins) % get_argument(expr(X, Y, Z), _RefList, data, Var, Builtins) :- !, expr_to_builtins(expr(X, Y, Z), Var, Builtins). % int/1, real/1, string/1 % BUG: use a predicate that already returns the ^^/2 term % to make sure that this term is used everywhere in DRS->OWL/SWRL % where numbers are represented. get_argument(DataItem, _RefList, data, '^^'(DataValue, DataTypeUri), []) :- dataitem_datavalue_datatypeuri(DataItem, DataValue, DataTypeUri), !. get_argument(X, RefList, object, Individual, []) :- is_toplevel(X, RefList, 'ObjectOneOf'([Individual])), !. get_argument('$VAR'(X), _RefList, object, Variable, []) :- get_variable(X, Variable). get_argument(X, _RefList, object, X, []). %% add_relation(+Relation:atom, +Var1, +Var2, +BIn:list, -BOut:list) is det. % % @param Relation is one of {'>', '<', '='} % ... % % @bug try to output less code, e.g. instead of 'equal' just unify: add_relation('=', Var, Var, B, B). % add_relation(Relation, Var1, Var2, RefList, B, ['BuiltInAtom'(swrlb:Builtin, [OutVar1, OutVar2]) | B]) :- relation_builtin(Relation, Builtin), get_argument(Var1, RefList, _, OutVar1, _), get_argument(Var2, RefList, _, OutVar2, _). % expr_to_builtins(+Expr:term, -EList:list) is det. % expr_to_builtins(+Expr:term, -Var:atom, -EList:list) is det. % % Flattens the expression (a tree) into a list simple expressions % that are connected by expression handles. E.g. % %== % ?- expr_to_builtins(expr(*, expr(+, 1, 2), 3), L). % L = [builtin(multiply, G295, G297, 3), builtin(add, G297, 1, 2)]. %== % % @param Expr is a term in the form expr(Op, Expr1, Expr2) % @param Var is a variable to be used as handle for the topmost expression % @param Builtins is a list of SWRL built-in predicates % expr_to_builtins(Expr, List) :- expr_to_builtins(Expr, _, List). expr_to_builtins(Expr, Var, List) :- expr_to_builtins(Expr, Var, [], List). expr_to_builtins(expr(Op, E1, E2), Var, LIn, ['BuiltInAtom'(swrlb:Builtin, [Var, Var1, Var2]) | LOut]) :- !, op_builtin(Op, Builtin), get_swrl_variable(Var), expr_to_builtins(E1, Var1, LIn, LTmp), expr_to_builtins(E2, Var2, LTmp, LOut). % @bug: why is RefList here empty? expr_to_builtins(Var, OutVar, List, List) :- get_argument(Var, [], _, OutVar, _). %% get_swrl_variable(-SwrlVariable:term) is det. % % Generate a new SWRL variable (prefixed by 'g' to avoid a possible nameclash) % % @bug It's not nice to use gensym/2 % get_swrl_variable(Variable) :- gensym(g, GenSym), get_variable(GenSym, Variable). %% get_variable(+Var, -Variable) % % get_variable('$VAR'(X), 'Variable'(Var)) :- !, with_output_to(atom(Var), format("urn:swrl#x~w", [X])). get_variable(X, 'Variable'(Var)) :- with_output_to(atom(Var), format("urn:swrl#x~w", [X])). %% relation_builtin(?Relation:atom, ?Builtin:atom) is det. % % SWRL built-ins for comparisons (complete coverage of the 6 built-ins) % % @param Relation is one of {'>', '<', '=', '\=', '=<', '>='} % @param Builtin is SWRL built-in % relation_builtin('=', equal). relation_builtin('\\=', notEqual). relation_builtin('<', lessThan). relation_builtin('=<', lessThanOrEqual). relation_builtin('>', greaterThan). relation_builtin('>=', greaterThanOrEqual). %% op_builtin(?Op:atom, ?Builtin:atom) is det. % % SWRL math built-ins and string built-ins. % % @param Op is DRS (binary) operator % @param Builtin is SWRL built-in % op_builtin('+', add). op_builtin('-', subtract). op_builtin('*', multiply). op_builtin('/', divide). op_builtin('^', pow). op_builtin('&', stringConcat).