diff --git a/src/renopro/asp/encodings/transform.lp b/src/renopro/asp/encodings/transform.lp index c583a1c..0852e3c 100644 --- a/src/renopro/asp/encodings/transform.lp +++ b/src/renopro/asp/encodings/transform.lp @@ -6,6 +6,7 @@ ast(constant(Id,Name)) :- constant(Id, Name). ast(function(Id,Name,Args)) :- function(Id,Name,Args). ast(term_tuple(Id,Pos,Element)) :- term_tuple(Id,Pos,Element). ast(binary_operation(Id,Operator,Left,Right)) :- binary_operation(Id,Operator,Left,Right). +ast(atom(Id,Symbol)) :- atom(Id,Symbol). ast(literal(Id,Sign,Function)) :- literal(Id,Sign,Function). ast(literal_tuple(Id,Pos,Element)) :- literal_tuple(Id,Pos,Element). ast(rule(Id,Head,Body)) :- rule(Id,Head,Body). diff --git a/src/renopro/asp/tests/reify/binary_operation.lp b/src/renopro/asp/tests/reify/binary_operation.lp index 4e6db72..b50714a 100644 --- a/src/renopro/asp/tests/reify/binary_operation.lp +++ b/src/renopro/asp/tests/reify/binary_operation.lp @@ -4,14 +4,15 @@ program("base",constant_tuple(0),statement_tuple(1)). statement_tuple(1,0,rule(2)). -rule(2,literal(3),literal_tuple(10)). +rule(2,literal(3),literal_tuple(11)). % facts representing head literal equal((1+1),2). -literal(3,"pos",function(4)). -function(4,equal,term_tuple(5)). +literal(3,"pos",atom(4)). +atom(4,function(5)). +function(5,equal,term_tuple(6)). % facts representing the binary operation (1+1). -term_tuple(5,0,binary_operation(6)). -binary_operation(6,"+",number(7),number(8)). -number(7,1). +term_tuple(6,0,binary_operation(7)). +binary_operation(7,"+",number(8),number(9)). number(8,1). -term_tuple(5,1,number(9)). -number(9,2). +number(9,1). +term_tuple(6,1,number(10)). +number(10,2). diff --git a/src/renopro/asp/tests/reify/constant.lp b/src/renopro/asp/tests/reify/constant_term.lp similarity index 54% rename from src/renopro/asp/tests/reify/constant.lp rename to src/renopro/asp/tests/reify/constant_term.lp index dd54148..c81ff20 100644 --- a/src/renopro/asp/tests/reify/constant.lp +++ b/src/renopro/asp/tests/reify/constant_term.lp @@ -4,9 +4,10 @@ program("base",constant_tuple(0),statement_tuple(1)). statement_tuple(1,0,rule(2)). -rule(2,literal(3),literal_tuple(7)). +rule(2,literal(3),literal_tuple(9)). % facts representing head literal yummy("carrot"). -literal(3,"pos",function(4)). -function(4,good,term_tuple(5)). -term_tuple(5,0,constant(6)). -constant(6,human). +literal(3,"pos",atom(4)). +atom(4,function(5)). +function(5,good,term_tuple(6)). +term_tuple(6,0,function(7)). +function(7,human,term_tuple(8)). diff --git a/src/renopro/asp/tests/reify/external.lp b/src/renopro/asp/tests/reify/external.lp new file mode 100644 index 0000000..2d154b5 --- /dev/null +++ b/src/renopro/asp/tests/reify/external.lp @@ -0,0 +1,25 @@ +% reified fact representation of program: +% #program base. +% #external a(X) : c(X); d(e(X)). + +program("base",constant_tuple(0),statement_tuple(1)). +statement_tuple(1,0,external(2)). +external(2,atom(3),literal_tuple(7),false). +atom(3,function(4)). +function(4,a,term_tuple(5)). +term_tuple(5,0,variable(6)). +variable(6,"X"). +literal_tuple(7,0,literal(8)). +literal(8,"pos",atom(9)). +atom(9,function(10)). +function(10,c,term_tuple(11)). +term_tuple(11,0,variable(12)). +variable(12,"X"). +literal_tuple(7,1,literal(13)). +literal(13,"pos",atom(14)). +atom(14,function(15)). +function(15,d,term_tuple(16)). +term_tuple(16,0,function(17)). +function(17,e,term_tuple(18)). +term_tuple(18,0,variable(19)). +variable(19,"X"). diff --git a/src/renopro/asp/tests/reify/function.lp b/src/renopro/asp/tests/reify/function.lp index 1b74fe4..5c2684d 100644 --- a/src/renopro/asp/tests/reify/function.lp +++ b/src/renopro/asp/tests/reify/function.lp @@ -4,19 +4,21 @@ program("base",constant_tuple(0),statement_tuple(1)). statement_tuple(1,0,rule(2)). -rule(2,literal(3),literal_tuple(8)). +rule(2,literal(3),literal_tuple(9)). % facts representing head literal rel(2,1). -literal(3,"pos",function(4)). -function(4,rel,term_tuple(5)). -term_tuple(5,0,number(6)). -number(6,2). -term_tuple(5,1,number(7)). -number(7,1). +literal(3,"pos",atom(4)). +atom(4,function(5)). +function(5,rel,term_tuple(6)). +term_tuple(6,0,number(7)). +number(7,2). +term_tuple(6,1,number(8)). +number(8,1). % facts representing body literal rel(1,2). -literal_tuple(8,0,literal(9)). -literal(9,"pos",function(10)). -function(10,rel,term_tuple(11)). -term_tuple(11,0,number(12)). -number(12,1). -term_tuple(11,1,number(13)). -number(13,2). +literal_tuple(9,0,literal(10)). +literal(10,"pos",atom(11)). +atom(11,function(12)). +function(12,rel,term_tuple(13)). +term_tuple(13,0,number(14)). +number(14,1). +term_tuple(13,1,number(15)). +number(15,2). diff --git a/src/renopro/asp/tests/reify/nested_function.lp b/src/renopro/asp/tests/reify/nested_function.lp index 7249b96..027dd85 100644 --- a/src/renopro/asp/tests/reify/nested_function.lp +++ b/src/renopro/asp/tests/reify/nested_function.lp @@ -4,11 +4,12 @@ program("base",constant_tuple(0),statement_tuple(1)). statement_tuple(1,0,rule(2)). -rule(2,literal(3),literal_tuple(9)). +rule(2,literal(3),literal_tuple(11)). % facts representing head literal rel(2,1). -literal(3,"pos",function(4)). -function(4,next,term_tuple(5)). -term_tuple(5,0,function(6)). -function(6,move,term_tuple(7)). -term_tuple(7,0,constant(8)). -constant(8,a). +literal(3,"pos",atom(4)). +atom(4,function(5)). +function(5,next,term_tuple(6)). +term_tuple(6,0,function(7)). +function(7,move,term_tuple(8)). +term_tuple(8,0,function(9)). +function(9,a,term_tuple(10)). diff --git a/src/renopro/asp/tests/reify/prop_fact.lp b/src/renopro/asp/tests/reify/prop_fact.lp index 41e6ee4..c0a88c0 100644 --- a/src/renopro/asp/tests/reify/prop_fact.lp +++ b/src/renopro/asp/tests/reify/prop_fact.lp @@ -4,7 +4,8 @@ program("base",constant_tuple(0),statement_tuple(1)). statement_tuple(1,0,rule(2)). -rule(2,literal(3),literal_tuple(5)). +rule(2,literal(3),literal_tuple(7)). % facts representing head literal a. -literal(3,"pos",constant(4)). -constant(4,a). +literal(3,"pos",atom(4)). +atom(4,function(5)). +function(5,a,term_tuple(6)). diff --git a/src/renopro/asp/tests/reify/prop_normal_rule.lp b/src/renopro/asp/tests/reify/prop_normal_rule.lp index 01bd65a..4990a79 100644 --- a/src/renopro/asp/tests/reify/prop_normal_rule.lp +++ b/src/renopro/asp/tests/reify/prop_normal_rule.lp @@ -4,15 +4,18 @@ program("base",constant_tuple(0),statement_tuple(1)). statement_tuple(1,0,rule(2)). -rule(2,literal(3),literal_tuple(5)). +rule(2,literal(3),literal_tuple(7)). % facts representing head literal a. -literal(3,"pos",constant(4)). -constant(4,a). +literal(3,"pos",atom(4)). +atom(4,function(5)). +function(5,a,term_tuple(6)). % facts representing body literal b. -literal_tuple(5,0,literal(6)). -literal(6,"pos",constant(7)). -constant(7,b). +literal_tuple(7,0,literal(8)). +literal(8,"pos",atom(9)). +atom(9,function(10)). +function(10,b,term_tuple(11)). % facts representing body literal not c. -literal_tuple(5,1,literal(8)). -literal(8,"not",constant(9)). -constant(9,c). +literal_tuple(7,1,literal(12)). +literal(12,"not",atom(13)). +atom(13,function(14)). +function(14,c,term_tuple(15)). diff --git a/src/renopro/asp/tests/reify/string.lp b/src/renopro/asp/tests/reify/string.lp index 98ae8d9..0c7830b 100644 --- a/src/renopro/asp/tests/reify/string.lp +++ b/src/renopro/asp/tests/reify/string.lp @@ -4,9 +4,10 @@ program("base",constant_tuple(0),statement_tuple(1)). statement_tuple(1,0,rule(2)). -rule(2,literal(3),literal_tuple(7)). +rule(2,literal(3),literal_tuple(8)). % facts representing head literal yummy("carrot"). -literal(3,"pos",function(4)). -function(4,yummy,term_tuple(5)). -term_tuple(5,0,string(6)). -string(6,"carrot"). +literal(3,"pos",atom(4)). +atom(4,function(5)). +function(5,yummy,term_tuple(6)). +term_tuple(6,0,string(7)). +string(7,"carrot"). diff --git a/src/renopro/asp/tests/reify/variable.lp b/src/renopro/asp/tests/reify/variable.lp index f36ffb8..e5b8564 100644 --- a/src/renopro/asp/tests/reify/variable.lp +++ b/src/renopro/asp/tests/reify/variable.lp @@ -4,19 +4,21 @@ program("base",constant_tuple(0),statement_tuple(1)). statement_tuple(1,0,rule(2)). -rule(2,literal(3),literal_tuple(8)). -% facts representing head literal rel(2,1). -literal(3,"pos",function(4)). -function(4,rel,term_tuple(5)). -term_tuple(5,0,variable(6)). -variable(6,"Y"). -term_tuple(5,1,variable(7)). -variable(7,"X"). -% facts representing body literal rel(1,2). -literal_tuple(8,0,literal(9)). -literal(9,"pos",function(10)). -function(10,rel,term_tuple(11)). -term_tuple(11,0,variable(12)). -variable(12,"X"). -term_tuple(11,1,variable(13)). -variable(13,"Y"). +rule(2,literal(3),literal_tuple(9)). +% facts representing head literal rel(Y,X). +literal(3,"pos",atom(4)). +atom(4,function(5)). +function(5,rel,term_tuple(6)). +term_tuple(6,0,variable(7)). +variable(7,"Y"). +term_tuple(6,1,variable(8)). +variable(8,"X"). +% facts representing body literal rel(X,Y). +literal_tuple(9,0,literal(10)). +literal(10,"pos",atom(11)). +atom(11,function(12)). +function(12,rel,term_tuple(13)). +term_tuple(13,0,variable(14)). +variable(14,"X"). +term_tuple(13,1,variable(15)). +variable(15,"Y"). diff --git a/src/renopro/asp/tests/transform/not_bad/transform.lp b/src/renopro/asp/tests/transform/not_bad/transform.lp index cd38e4a..9e6b8ba 100644 --- a/src/renopro/asp/tests/transform/not_bad/transform.lp +++ b/src/renopro/asp/tests/transform/not_bad/transform.lp @@ -13,15 +13,18 @@ % -> % good(dog(X,"spotty")) :- cute(dog(X,"spotty")), not bad(dog(X,"spotty")). -% auxiliary predicate to get maximal index within a tuple -max_index(I,N) :- N = #max{ P : literal_tuple(I,P,_); -1 }, literal_tuple(I,_,_). +% auxiliary predicate to get maximal index within a tuple of rule body literals +max_lit_index(LT,Idx) +:- Idx = #max{ P : literal_tuple(LT,P,_); -1 }, rule(_,_,literal_tuple(LT)). % the transformation itself -add((literal_tuple(LT,N+1,literal(new_id(LT,0)))); - literal(new_id(LT,0),"not",function(new_id(LT,1))); - function(new_id(LT,1),bad,Fargs)) +add((literal_tuple(LT,N+1,literal(new_id(LT,0))); + literal(new_id(LT,0),"not",atom(new_id(LT,1))); + atom(new_id(LT,1),function(new_id(LT,2))); + function(new_id(LT,2),bad,Fargs))) :- rule(_,literal(L),literal_tuple(LT)), - literal(L,"pos",function(F)), + literal(L,"pos",atom(A)), + atom(A,function(F)), function(F,good,Fargs), - max_index(LT,N). + max_lit_index(LT,N). diff --git a/src/renopro/asp/tests/transform/prev_to_timepoints/transform.lp b/src/renopro/asp/tests/transform/prev_to_timepoints/transform.lp index b546b13..c5766d4 100644 --- a/src/renopro/asp/tests/transform/prev_to_timepoints/transform.lp +++ b/src/renopro/asp/tests/transform/prev_to_timepoints/transform.lp @@ -1,61 +1,47 @@ % auxiliary atoms -max_index(T,Index) :- Index = #max{ Pos : term_tuple(T,Pos,_); -1 }, term_tuple(T,_,_). -arity(F,N+1) :- function(F,_,term_tuple(T)), max_index(T,N). +max_arg_index(TT,Idx) +:- Idx = #max{ Pos : term_tuple(TT,Pos,_); -1 }, function(_,_,term_tuple(TT)). +arity(F,N+1) :- function(F,_,term_tuple(T)), max_arg_index(T,N). -% when a literal is not prev +prev_chain(A,function(F),O) +:- atom(A,function(F)), function(F,prev,term_tuple(T)), arity(F,1), + term_tuple(T,0,O). -% when atom of a literal is a predicate -add((term_tuple(T,N+1,constant(new_id(T))); - constant(new_id(T),t))) -:- literal(L,_,function(F)), function(F,Name,term_tuple(T)), - Name!=prev, max_index(T,N). +prev_chain(A,function(F),O) +:- prev_chain(A,_,function(F)), function(F,prev,term_tuple(T)), arity(F,1), + term_tuple(T,0,O). -% when atom of a literal is a propositional constant -delete(literal(L,S,constant(F))) :- literal(L,S,constant(F)). -add((literal(L,S,function(F)); - function(F,Name,term_tuple(new_id(F))); - term_tuple(new_id(F),0,constant(new_id(F))); - constant(new_id(F),t))) -:- literal(L,S,constant(F)), constant(F,Name). +% final operand must be a constant or function, as e.g. prev(1) is not a prev operation +final_operand(A,O) +:- prev_chain(A,F,O), not prev_chain(A,O,_), + O=function(_). +num_prevs(A,N) :- N = #count{ F : prev_chain(A,F,_) }, prev_chain(A,_,_). -prev_chain(L,function(F),O) -:- literal(L,_,function(F)), function(F,prev,term_tuple(T)), arity(F,1), - term_tuple(T,0,O). +first_prev(A,F) :- prev_chain(A,F,O), not prev_chain(A,_,F). -prev_chain(L,function(F),O) -:- prev_chain(L,_,function(F)), function(F,prev,term_tuple(T)), arity(F,1), - term_tuple(T,0,O). -final_operand(L,O) -:- prev_chain(L,F,O), not prev_chain(L,O,_), O=(constant(_);function(_)). - -first_prev(L,F) -:- prev_chain(L,F,O), not prev_chain(L,_,F). - -num_prevs(L,N) -:- N = #count{ F : prev_chain(L,F,_) }, prev_chain(L,_,_). - -% when final operand is a function -replace(function(F,N,A),function(F,Name,term_tuple(T))) -:- first_prev(L,function(F)), function(F,N,A), final_operand(L,function(O)), - function(O,Name,term_tuple(T)). - -add(term_tuple(T,I+1,binary_operation(new_id(O))); - binary_operation(new_id(O),"-",constant(new_id(O)),number(new_id(O))); - constant(new_id(O),t); - number(new_id(O),N)) -:- final_operand(L,function(O)), function(O,_,term_tuple(T)), max_index(T,I), - num_prevs(L,N). - -% when final operand is a constant -replace(function(F,N,A),function(F,Name,term_tuple(new_id(O)))) -:- first_prev(L,function(F)), function(F,N,A), final_operand(L,constant(O)), - constant(O,Name). - -add(term_tuple(new_id(O),0,binary_operation(new_id(O))); - binary_operation(new_id(O),"-",constant(new_id(O)),number(new_id(O))); - constant(new_id(O),t); - number(new_id(O),N)) -:- final_operand(L,constant(O)), num_prevs(L,N). +% when an atom is not prev. + +% add time point constant as additional argument +add(term_tuple(T,N+1,function(new_id(T))); + function(new_id(T),t,term_tuple(new_id(T)))) +:- atom(A,function(F)), function(F,Name,term_tuple(T)), + Name!=prev, max_arg_index(T,N). + +% when an atom is a prev. + +% replace function symbol of atom with final operand, appending +% appropriate time point as additional argument. +replace(function(F,N,T1),function(F,Name,term_tuple(T2))) +:- first_prev(A,function(F)), function(F,N,T1), final_operand(A,function(O)), + function(O,Name,term_tuple(T2)). + +add((term_tuple(T,I+1,binary_operation(new_id(O))); + binary_operation(new_id(O),"-",function(new_id(O)),number(new_id(O))); + function(new_id(O),t,term_tuple(new_id(O))); + number(new_id(O),N))) +:- final_operand(A,function(O)), function(O,_,term_tuple(T)), max_arg_index(T,I), + num_prevs(A,N). + diff --git a/src/renopro/asp/tests/transform/prev_to_timepoints/very_sad_input.lp b/src/renopro/asp/tests/transform/prev_to_timepoints/very_sad_input.lp index 17c803f..5a58335 100644 --- a/src/renopro/asp/tests/transform/prev_to_timepoints/very_sad_input.lp +++ b/src/renopro/asp/tests/transform/prev_to_timepoints/very_sad_input.lp @@ -1 +1 @@ -very_sad(robot(X)) :- prev(sad(robot(X))), prev(prev(sad(robot(X)))). \ No newline at end of file +very_sad(robot(X)) :- prev(sad(robot(X))), prev(prev(sad(robot(X)))). diff --git a/src/renopro/clorm_predicates.py b/src/renopro/clorm_predicates.py index c025f42..f8836a2 100644 --- a/src/renopro/clorm_predicates.py +++ b/src/renopro/clorm_predicates.py @@ -6,7 +6,7 @@ from clorm import (IntegerField, Predicate, StringField, RawField, BaseField, combine_fields, define_enum_field, - ConstantField) + refine_field, ConstantField) from clingo import ast id_count = count() @@ -100,16 +100,8 @@ class Variable(Predicate): Variable1 = make_id_predicate(Variable) -class Constant(Predicate): - id = Identifier - name = ConstantField - - -Constant1 = make_id_predicate(Constant) - - Term = combine_fields_lazily([String1.Field, Number1.Field, - Variable1.Field, Constant1.Field], name="Term") + Variable1.Field], name="Term") class Term_Tuple(Predicate): @@ -122,6 +114,8 @@ class Term_Tuple(Predicate): class Function(Predicate): + """Note: we represent constants as a Function with an empty term + tuple (i.e. no term_tuple fact with a matching identifier""" id = Identifier name = ConstantField arguments = Term_Tuple1.Field @@ -164,8 +158,13 @@ class Binary_Operation(Predicate): Term.fields.append(Binary_Operation1.Field) -# an atom may be a predicate (Function) or propositional constant (Constant) -Atom = combine_fields([Function1.Field, Constant1.Field], name="Atom") + +class Atom(Predicate): + id = Identifier + symbol = Function1.Field + + +Atom1 = make_id_predicate(Atom) class Sign(str, enum.Enum): @@ -192,7 +191,7 @@ class Literal(Predicate): sig = define_enum_field(parent_field=StringField, enum_class=Sign, name="SignField") - atom = Atom + atom = Atom1.Field Literal1 = make_id_predicate(Literal) @@ -215,8 +214,25 @@ class Rule(Predicate): Rule1 = make_id_predicate(Rule) -# will be changed to combine_fileds once more statements are implemented -Statement = Rule1.Field + +# note that clingo's parser actually allows arbitrary constant as the external_type +# argument of External, but any other value than true or false results in the external +# statement having no effect +ExternalTypeField = refine_field(ConstantField, ["true", "false"], + name="ExternalTypeField") + + +class External(Predicate): + id = Identifier + atom = Atom1.Field + body = Literal_Tuple1.Field + external_type = ExternalTypeField + + +External1 = make_id_predicate(External) + + +Statement = combine_fields([Rule1.Field, External1.Field]) class Statement_Tuple(Predicate): @@ -231,7 +247,7 @@ class Statement_Tuple(Predicate): class Constant_Tuple(Predicate): id = Identifier position = IntegerField - element = Constant1.Field + element = Function1.Field Constant_Tuple1 = make_id_predicate(Constant_Tuple) @@ -251,20 +267,22 @@ class Program(Predicate): Number1, Variable, Variable1, - Constant, - Constant1, Term_Tuple, Term_Tuple1, Function, Function1, Binary_Operation, Binary_Operation1, + Atom, + Atom1, Literal, Literal1, Literal_Tuple, Literal_Tuple1, Rule, Rule1, + External, + External1, Statement_Tuple, Statement_Tuple1, Constant_Tuple, @@ -279,20 +297,22 @@ class Program(Predicate): Number1, Variable, Variable1, - Constant, - Constant1, Term_Tuple, Term_Tuple1, Function, Function1, Binary_Operation, Binary_Operation1, + Atom, + Atom1, Literal, Literal1, Literal_Tuple, Literal_Tuple1, Rule, Rule1, + External, + External1, Statement_Tuple, Statement_Tuple1, Constant_Tuple, @@ -304,13 +324,14 @@ class Program(Predicate): String, Number, Variable, - Constant, Function, Term_Tuple, Binary_Operation, + Atom, Literal, Literal_Tuple, Rule, + External, Statement_Tuple, Constant_Tuple, Program @@ -320,13 +341,14 @@ class Program(Predicate): String, Number, Variable, - Constant, Function, Term_Tuple, Binary_Operation, + Atom, Literal, Literal_Tuple, Rule, + External, Statement_Tuple, Constant_Tuple, Program diff --git a/src/renopro/reify.py b/src/renopro/reify.py index 4436e07..aad1d29 100644 --- a/src/renopro/reify.py +++ b/src/renopro/reify.py @@ -1,6 +1,6 @@ """Module implementing reification and de-reification of non-ground programs""" import sys -from functools import singledispatchmethod, partial +from functools import singledispatchmethod import logging from typing import Iterable, Sequence, Union, Optional from pathlib import Path @@ -10,11 +10,13 @@ from clingo.ast import (AST, ASTType, Location, Position, parse_string, parse_files, BinaryOperator) from clingo.symbol import Symbol, SymbolType -from clorm.clingo import Control, Model +from clorm.clingo import Control from clorm import (FactBase, control_add_facts, SymbolPredicateUnifier, parse_fact_string, UnifierNoMatchError, parse_fact_files) +import renopro.clorm_predicates as preds + class ChildQueryError(Exception): pass @@ -24,8 +26,6 @@ class ChildrenQueryError(Exception): pass -import renopro.clorm_predicates as preds - logger = logging.getLogger(__name__) DUMMY_LOC = Location(Position("", 1, 1), Position("", 1, 1)) @@ -162,6 +162,32 @@ def _reify_program(self, node): element=param.id)) return + @_reify_ast.register(ASTType.External) + def _reify_external(self, node): + self._program_statements.append(node) + ext_type = node.external_type.symbol.name + external1 = preds.External1() + external = preds.External( + id=external1.id, + atom=self._reify_ast(node.atom), + body=preds.Literal_Tuple1(), + external_type=ext_type + ) + self._reified.add(external) + statement_tup = preds.Statement_Tuple( + id=self._statement_tup_id, + position=self._statement_pos, + element=external1 + ) + self._reified.add(statement_tup) + self._statement_pos += 1 + for pos, element in enumerate(node.body, start=0): + self._reified.add(preds.Literal_Tuple( + id=external.body.id, + position=pos, + element=self._reify_ast(element))) + return + @_reify_ast.register(ASTType.Rule) def _reify_rule(self, node): self._program_statements.append(node) @@ -199,7 +225,10 @@ def _reify_literal(self, node): @_reify_ast.register(ASTType.SymbolicAtom) def _reify_symbolic_atom(self, node): - return self._reify_ast(node.symbol) + atom1 = preds.Atom1() + atom = preds.Atom(id=atom1.id, symbol=self._reify_ast(node.symbol)) + self._reified.add(atom) + return atom1 @_reify_ast.register(ASTType.Function) def _reify_function(self, node): @@ -211,14 +240,6 @@ def _reify_function(self, node): to create the correct clorm predicate. """ - if len(node.arguments) == 0: - constant1 = preds.Constant1() - constant = preds.Constant( - id=constant1.id, - name=node.name - ) - self._reified.add(constant) - return constant1 function1 = preds.Function1() function = preds.Function( id=function1.id, @@ -282,9 +303,10 @@ def _reify_symbol_function(self, symb): clingo.Symbol.Function with empty argument list. """ - const1 = preds.Constant1() - self._reified.add(preds.Constant(id=const1.id, name=symb.name)) - return const1 + func1 = preds.Function1() + self._reified.add(preds.Function(id=func1.id, name=symb.name, + arguments=preds.Term_Tuple1())) + return func1 @_reify_ast.register(SymbolType.String) def _reify_symbol_string(self, symb): @@ -362,6 +384,16 @@ def _reflect_program(self, program: preds.Program) -> Sequence[AST]: subprogram.extend(statement_nodes) return subprogram + @_reflect_predicate.register + def _reflect_external(self, external: preds.External) -> AST: + atom_node = self._reflect_child_pred(external, external.atom) + body_nodes = self._reflect_child_preds(external, external.body) + ext_type = ast.SymbolicTerm( + location=DUMMY_LOC, + symbol=symbol.Function(name=external.external_type, arguments=[])) + return ast.External(location=DUMMY_LOC, atom=atom_node, + body=body_nodes, external_type=ext_type) + @_reflect_predicate.register def _reflect_rule(self, rule: preds.Rule) -> AST: head_node = self._reflect_child_pred(rule, rule.head) @@ -375,10 +407,19 @@ def _reflect_literal(self, lit: preds.Literal) -> AST: return ast.Literal(location=DUMMY_LOC, sign=sign, atom=atom_node) @_reflect_predicate.register - def _reflect_function(self, func: preds.Function) -> AST: + def _reflect_atom(self, atom: preds.Atom) -> AST: + return ast.SymbolicAtom(symbol=self._reflect_child_pred(atom, + atom.symbol)) + + @_reflect_predicate.register + def _reflect_function( + self, func: preds.Function) -> Union[AST, Symbol]: + """Reflect function, which may represent a propositional + constant, predicate, function symbol, or constant term""" arg_nodes = self._reflect_child_preds(func, func.arguments) return ast.Function( - location=DUMMY_LOC, name=func.name, arguments=arg_nodes, external=0 + location=DUMMY_LOC, name=func.name, arguments=arg_nodes, + external=0 ) @_reflect_predicate.register @@ -397,13 +438,6 @@ def _reflect_string(self, string: preds.String) -> Symbol: location=DUMMY_LOC, symbol=symbol.String(string=string.value) ) - @_reflect_predicate.register - def _reflect_constant(self, constant: preds.Constant) -> Symbol: - return ast.SymbolicTerm( - location=DUMMY_LOC, - symbol=symbol.Function(name=constant.name, arguments=[]) - ) - @_reflect_predicate.register def _reflect_binary_operation( self, operation: preds.Binary_Operation) -> AST: @@ -423,6 +457,7 @@ def reflect(self): for prog in self._reified.query(preds.Program).all(): subprogram = self._reflect_predicate(prog) self._program_statements.extend(subprogram) + logger.info(f"Reflected program string:\n{self.program_string}") return def transform(self, meta_str: Optional[str] = None, diff --git a/tests/test_reify.py b/tests/test_reify.py index 63489bf..3f9931a 100644 --- a/tests/test_reify.py +++ b/tests/test_reify.py @@ -112,7 +112,7 @@ def test_reify_program_constant_term(self): Test reification of normal rule with constant term. """ prog_str = "good(human)." - facts = self.get_test_facts("constant.lp") + facts = self.get_test_facts("constant_term.lp") self.assertReifyReflectEqual(prog_str, facts) def test_reify_program_binary_operator(self): @@ -120,3 +120,7 @@ def test_reify_program_binary_operator(self): facts = self.get_test_facts("binary_operation.lp") self.assertReifyReflectEqual(prog_str, facts) + def test_reify_external_false(self): + prog_str = "#external a(X) : c(X); d(e(X)). [false]" + facts = self.get_test_facts("external.lp") + self.assertReifyReflectEqual(prog_str, facts)