2016-11-21 17:51:14 +01:00
# include <catch.hpp>
2016-11-24 15:24:38 +01:00
# include <sstream>
# include <anthem/Context.h>
# include <anthem/Translation.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE ( " [translation] Rules are translated correctly " , " [translation] " )
{
std : : stringstream input ;
std : : stringstream output ;
std : : stringstream errors ;
anthem : : output : : Logger logger ( output , errors ) ;
2017-03-23 15:10:51 +01:00
anthem : : Context context = { logger , { } } ;
context . simplify = false ;
2017-04-08 18:47:06 +02:00
context . complete = false ;
2016-11-24 15:24:38 +01:00
SECTION ( " simple example 1 " )
{
input < < " p(1..5). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:24:38 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " (V1 in 1..5 -> p(V1)) \n " ) ;
2016-11-24 15:24:38 +01:00
}
SECTION ( " simple example 2 " )
{
input < < " p(N) :- N = 1..5. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:24:38 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in N and exists X1, X2 (X1 in N and X2 in 1..5 and X1 = X2)) -> p(V1)) \n " ) ;
2016-11-24 15:24:38 +01:00
}
SECTION ( " simple example 3 " )
{
input < < " p(N + 1) :- q(N). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:24:38 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in (N + 1) and exists X1 (X1 in N and q(X1))) -> p(V1)) \n " ) ;
2016-11-24 15:24:38 +01:00
}
2016-11-24 15:31:52 +01:00
SECTION ( " n-ary head " )
{
input < < " p(N, 1, 2) :- N = 1..5. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:31:52 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in N and V2 in 1 and V3 in 2 and exists X1, X2 (X1 in N and X2 in 1..5 and X1 = X2)) -> p(V1, V2, V3)) \n " ) ;
2016-11-24 15:31:52 +01:00
}
SECTION ( " disjunctive head " )
{
// TODO: check why order of disjunctive literals is inverted
input < < " q(3, N); p(N, 1, 2) :- N = 1..5. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:31:52 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in N and V2 in 1 and V3 in 2 and V4 in 3 and V5 in N and exists X1, X2 (X1 in N and X2 in 1..5 and X1 = X2)) -> (p(V1, V2, V3) or q(V4, V5))) \n " ) ;
2016-11-24 15:38:55 +01:00
}
2016-11-24 17:33:19 +01:00
SECTION ( " disjunctive head (alternative syntax) " )
{
// TODO: check why order of disjunctive literals is inverted
input < < " q(3, N), p(N, 1, 2) :- N = 1..5. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 17:33:19 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in N and V2 in 1 and V3 in 2 and V4 in 3 and V5 in N and exists X1, X2 (X1 in N and X2 in 1..5 and X1 = X2)) -> (p(V1, V2, V3) or q(V4, V5))) \n " ) ;
2016-11-24 17:33:19 +01:00
}
2016-11-24 15:38:55 +01:00
SECTION ( " escaping conflicting variable names " )
{
2017-03-29 21:28:46 +02:00
input < < " p(X1, V1, A1) :- q(X1), q(V1), q(A1). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:38:55 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in _X1 and V2 in _V1 and V3 in _A1 and exists X1 (X1 in _X1 and q(X1)) and exists X2 (X2 in _V1 and q(X2)) and exists X3 (X3 in _A1 and q(X3))) -> p(V1, V2, V3)) \n " ) ;
2016-11-24 15:31:52 +01:00
}
2016-11-24 15:44:46 +01:00
SECTION ( " fact " )
{
input < < " p(42). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:44:46 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " (V1 in 42 -> p(V1)) \n " ) ;
2016-11-24 15:44:46 +01:00
}
2016-11-24 15:51:11 +01:00
SECTION ( " 0-ary fact " )
{
input < < " p. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:51:11 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " (#true -> p) \n " ) ;
2016-11-24 15:51:11 +01:00
}
2017-03-15 17:01:09 +01:00
SECTION ( " function " )
{
input < < " :- not p(I), I = 1..n. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2017-03-15 17:01:09 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((exists X1 (X1 in I and not p(X1)) and exists X2, X3 (X2 in I and X3 in 1..n and X2 = X3)) -> #false) \n " ) ;
2017-03-15 17:01:09 +01:00
}
2016-11-24 17:45:22 +01:00
SECTION ( " disjunctive fact (no arguments) " )
{
input < < " q; p. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 17:45:22 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " (#true -> (p or q)) \n " ) ;
2016-11-24 17:45:22 +01:00
}
SECTION ( " disjunctive fact (arguments) " )
{
input < < " q; p(42). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 17:45:22 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " (V1 in 42 -> (p(V1) or q)) \n " ) ;
2016-11-24 17:45:22 +01:00
}
SECTION ( " integrity constraint (no arguments) " )
{
input < < " :- p, q. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 17:45:22 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((p and q) -> #false) \n " ) ;
2016-11-24 17:45:22 +01:00
}
SECTION ( " contradiction " )
{
input < < " :-. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 17:45:22 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " (#true -> #false) \n " ) ;
2016-11-24 17:45:22 +01:00
}
SECTION ( " integrity constraint (arguments) " )
2016-11-24 15:44:46 +01:00
{
2016-11-24 17:38:44 +01:00
input < < " :- p(42), q. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:44:46 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((exists X1 (X1 in 42 and p(X1)) and q) -> #false) \n " ) ;
2016-11-24 15:44:46 +01:00
}
2016-11-24 15:51:25 +01:00
SECTION ( " inf/sup " )
{
input < < " p(X, #inf) :- q(X, #sup). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:51:25 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in X and V2 in #inf and exists X1, X2 (X1 in X and X2 in #sup and q(X1, X2))) -> p(V1, V2)) \n " ) ;
2016-11-24 15:51:25 +01:00
}
2016-11-24 15:58:59 +01:00
SECTION ( " strings " )
{
input < < " p(X, \" foo \" ) :- q(X, \" bar \" ). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 15:58:59 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in X and V2 in \" foo \" and exists X1, X2 (X1 in X and X2 in \" bar \" and q(X1, X2))) -> p(V1, V2)) \n " ) ;
2016-11-24 15:58:59 +01:00
}
2016-11-24 16:00:44 +01:00
SECTION ( " tuples " )
{
input < < " p(X, (1, 2, 3)) :- q(X, (4, 5)). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 16:00:44 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in X and V2 in (1, 2, 3) and exists X1, X2 (X1 in X and X2 in (4, 5) and q(X1, X2))) -> p(V1, V2)) \n " ) ;
2016-11-24 16:00:44 +01:00
}
SECTION ( " 1-ary tuples " )
{
input < < " p(X, (1,)) :- q(X, (2,)). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 16:00:44 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in X and V2 in (1,) and exists X1, X2 (X1 in X and X2 in (2,) and q(X1, X2))) -> p(V1, V2)) \n " ) ;
2016-11-24 16:00:44 +01:00
}
2016-11-24 16:04:53 +01:00
2016-11-24 16:53:04 +01:00
SECTION ( " intervals " )
{
input < < " p(X, 1..10) :- q(X, 6..12). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 16:53:04 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in X and V2 in 1..10 and exists X1, X2 (X1 in X and X2 in 6..12 and q(X1, X2))) -> p(V1, V2)) \n " ) ;
2016-11-24 16:53:04 +01:00
}
2016-11-24 17:00:08 +01:00
SECTION ( " comparisons " )
{
input < < " p(M, N, O, P) :- M < N, P != O. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 17:00:08 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in M and V2 in N and V3 in O and V4 in P and exists X1, X2 (X1 in M and X2 in N and X1 < X2) and exists X3, X4 (X3 in P and X4 in O and X3 != X4)) -> p(V1, V2, V3, V4)) \n " ) ;
2016-11-24 17:00:08 +01:00
}
2017-05-04 15:44:37 +02:00
SECTION ( " single negation with 0-ary predicates " )
{
input < < " not p :- not q. " ;
anthem : : translate ( " input " , input , context ) ;
CHECK ( output . str ( ) = = " (not q -> not p) \n " ) ;
}
SECTION ( " single negation with n-ary predicates " )
2016-11-24 16:04:53 +01:00
{
input < < " not p(X, 1) :- not q(X, 2). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 16:04:53 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in X and V2 in 1 and exists X1, X2 (X1 in X and X2 in 2 and not q(X1, X2))) -> not p(V1, V2)) \n " ) ;
2016-11-24 16:04:53 +01:00
}
2016-11-24 16:50:35 +01:00
SECTION ( " variable numbering " )
{
// TODO: check why order of disjunctive literals is inverted
input < < " f; q(A1, A2); p(A3, r(A4)); g(g(A5)) :- g(A3), f, q(A4, A1), p(A2, A5). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 16:50:35 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in _A1 and V2 in _A2 and V3 in _A3 and V4 in r(_A4) and V5 in g(_A5) "
2017-03-29 21:28:46 +02:00
" and exists X1 (X1 in _A3 and g(X1)) and f and exists X2, X3 (X2 in _A4 and X3 in _A1 and q(X2, X3)) and exists X4, X5 (X4 in _A2 and X5 in _A5 and p(X4, X5))) "
2017-03-15 16:00:00 +01:00
" -> (q(V1, V2) or p(V3, V4) or g(V5) or f)) \n " ) ;
2016-11-24 16:50:35 +01:00
}
2016-11-24 16:51:17 +01:00
SECTION ( " nested functions " )
{
input < < " p(q(s(t(X1))), u(X2)) :- u(v(w(X2)), z(X1)). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2016-11-24 16:51:17 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in q(s(t(_X1))) and V2 in u(_X2) and exists X1, X2 (X1 in v(w(_X2)) and X2 in z(_X1) and u(X1, X2))) -> p(V1, V2)) \n " ) ;
2016-11-24 16:51:17 +01:00
}
2017-03-06 15:49:40 +01:00
SECTION ( " choice rule (simple) " )
{
input < < " {p}. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2017-03-06 15:49:40 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " (p -> p) \n " ) ;
2017-03-06 15:49:40 +01:00
}
SECTION ( " choice rule (two elements) " )
{
input < < " {p; q}. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2017-03-06 15:49:40 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " (p -> p) \n (q -> q) \n " ) ;
2017-03-06 15:49:40 +01:00
}
SECTION ( " choice rule (n-ary elements) " )
{
input < < " {p(1..3, N); q(2..4)}. " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2017-03-06 15:49:40 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in 1..3 and V2 in N and V3 in 2..4 and p(V1, V2)) -> p(V1, V2)) \n ((V1 in 1..3 and V2 in N and V3 in 2..4 and q(V3)) -> q(V3)) \n " ) ;
2017-03-06 15:49:40 +01:00
}
2017-03-06 15:55:00 +01:00
SECTION ( " choice rule with body " )
{
input < < " {p(M, N); q(P)} :- s(M, N, P). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2017-03-06 15:55:00 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in M and V2 in N and V3 in P and exists X1, X2, X3 (X1 in M and X2 in N and X3 in P and s(X1, X2, X3)) and p(V1, V2)) -> p(V1, V2)) \n ((V1 in M and V2 in N and V3 in P and exists X1, X2, X3 (X1 in M and X2 in N and X3 in P and s(X1, X2, X3)) and q(V3)) -> q(V3)) \n " ) ;
2017-03-15 16:00:00 +01:00
}
SECTION ( " choice rule with negation " )
{
input < < " {not p(X, 1)} :- not q(X, 2). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2017-03-15 16:00:00 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in X and V2 in 1 and exists X1, X2 (X1 in X and X2 in 2 and not q(X1, X2)) and not p(V1, V2)) -> not p(V1, V2)) \n " ) ;
2017-03-15 16:00:00 +01:00
}
SECTION ( " choice rule with negation (two elements) " )
{
input < < " {not p(X, 1); not s} :- not q(X, 2). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2017-03-15 16:00:00 +01:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in X and V2 in 1 and exists X1, X2 (X1 in X and X2 in 2 and not q(X1, X2)) and not p(V1, V2)) -> not p(V1, V2)) \n ((V1 in X and V2 in 1 and exists X1, X2 (X1 in X and X2 in 2 and not q(X1, X2)) and not s) -> not s) \n " ) ;
2017-03-06 15:55:00 +01:00
}
2017-03-29 21:28:46 +02:00
SECTION ( " anonymous variables " )
{
input < < " p(_, _) :- q(_, _). " ;
2017-04-10 16:32:12 +02:00
anthem : : translate ( " input " , input , context ) ;
2017-03-29 21:28:46 +02:00
2017-04-08 19:59:59 +02:00
CHECK ( output . str ( ) = = " ((V1 in A1 and V2 in A2 and exists X1, X2 (X1 in A3 and X2 in A4 and q(X1, X2))) -> p(V1, V2)) \n " ) ;
2017-03-29 21:28:46 +02:00
}
2016-11-24 15:24:38 +01:00
}