// {{{ MIT License

// Copyright 2017 Roland Kaminski

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// }}}

#include "gringo/ground/dependency.hh"

#include "tests/tests.hh"
#include "tests/term_helper.hh"
#include "tests/output/solver_helper.hh"

#include "gringo/input/nongroundparser.hh"


namespace Gringo { namespace Output { namespace Test {

TEST_CASE("output-aspcomp2013", "[output][aspcomp]") {

// {{{1 N01 Permutation Pattern Matching

    SECTION("aspcomp2013_01") {
        // Author: Martin Lackner, Andreas Pfandler
        REQUIRE(
            "([[solution(1,3),solution(2,4),solution(3,2)]],[])" ==
            IO::to_string(solve(
                "% instance\n"
                "t(1,5).\n"
                "t(2,3).\n"
                "t(3,1).\n"
                "t(4,4).\n"
                "t(5,2).\n"
                "p(1,2).\n"
                "p(2,3).\n"
                "p(3,1).\n"
                "patternlength(3).\n"
                "\n"
                "% encoding\n"
                "kval(1).\n"
                "kval(N+1) :- kval(N), N < L, patternlength(L). \n"
                "1 <= { subt(K,I,E) : t(I,E) } <= 1 :- kval(K), patternlength(L).\n"
                ":- subt(K1,I1,_), subt(K2,I2,_), K1<K2, I1 >= I2.\n"
                "solution(K,E) :- subt(K,_,E).\n"
                ":- solution(K1,ET1), solution(K2,ET2), p(K1,EP1), p(K2,EP2), ET1 < ET2, EP1 >= EP2.\n", {"solution("})));
    }

// {{{1 N02 Valves Location Problem

    SECTION("aspcomp2013_02") {
        // Author: Andrea Peano
        REQUIRE(
            "([[valve(1,2),valve(1,4),valve(3,2),valve(4,2)]],"
            "[-:63:20-21: info: global variable in tuple of aggregate element:\n  X\n"
            ",-:91:31-32: info: global variable in tuple of aggregate element:\n  W\n"
            ",-:90:22-23: info: global variable in tuple of aggregate element:\n  X\n"
            ",-:90:24-25: info: global variable in tuple of aggregate element:\n  Y\n"
            ",-:91:33-34: info: global variable in tuple of aggregate element:\n  Z\n"
            ",-:107:44-45: info: global variable in tuple of aggregate element:\n  X\n"
            ",-:107:46-47: info: global variable in tuple of aggregate element:\n  Y\n"
            "])" == IO::to_string(solve(
                "%instance\n"
                "\n"
                "valves_number(4).\n"
                "valves_per_pipe(1).\n"
                "\n"
                "junction(1). junction(2). junction(3).\n"
                "junction(4). junction(5).\n"
                "tank(1).\n"
                "\n"
                "pipe(1, 2). pipe(1, 4). pipe(2, 3). \n"
                "pipe(2, 4). pipe(3, 4). pipe(3, 5).\n"
                "\n"
                "dem(1, 2, 57). dem(1, 4, 65). dem(2, 3, 155). \n"
                "dem(2, 4, 129). dem(3, 4, 78). dem(3, 5, 200).\n"
                "\n"
                "%encoding\n"
                "\n"
                "       %just some tools\n"
                "       %Symmetric pipe\n"
                "symm_pipe(A,B):- pipe(A,B).\n"
                "symm_pipe(B,A):- pipe(A,B).\n"
                "       %We need a lexicographic order (there may be more than one worst isolation cases)\n"
                "less_ico(pipe(A,B), pipe(C,D)):- pipe(A,B), pipe(C,D), A<C.\n"
                "less_ico(pipe(A,B), pipe(C,D)):- pipe(A,B), pipe(C,D), A = C, B<D.\n"
                "\n"
                "%Adjacency of pipes (common junction and unshared junctions)\n"
                "%adj(pipe(X,Y), pipe(W,Z), COM, U1, U2) :- symm_pipe(COM,U1), symm_pipe(COM,U2), U1!=U2, not tank(COM),\n"
                "%              pipe(X,Y), pipe(W,Z), \n"
                "%                                2 {COM=W, COM=Z, COM=X, COM=Y} 2,\n"
                "%              1 {U1=W, U1=Z, U1=X, U1=Y} 1,\n"
                "%              1 {U2=W, U2=Z, U2=X, U2=Y} 1.\n"
                "adj(pipe(X,Y), pipe(W,Z), COM, U1, U2) :- symm_pipe(COM,U1), symm_pipe(COM,U2), U1!=U2, not tank(COM),\n"
                "               pipe(X,Y), pipe(W,Z), \n"
                "                                2 = #count {a : COM=W; b : COM=Z; c : COM=X; d : COM=Y},\n"
                "               1 = #count {a : U1=W; b : U1=Z; c : U1=X; d : U1=Y},\n"
                "               1 = #count {a : U2=W; b : U2=Z; c : U2=X; d : U2=Y}.\n"
                "\n"
                "\n"
                "\n"
                "       %\n"
                "       %There are some valves that are closed to isolate the broken pipe\n"
                "1 <= { closed_valve(v(X,Y), broken(A,B)) : symm_pipe(X,Y) } <= Nv :- pipe(A,B), valves_number(Nv).\n"
                "\n"
                "       %\n"
                "       %If a valve is closed for some pipes, then it must be installed!!\n"
                "valve(A,B) :- closed_valve(v(A,B), _).\n"
                "\n"
                "       %\n"
                "       %There should always be installed valves near the tanks\n"
                "valve(A,B) :- symm_pipe(A,B), tank(A).\n"
                "\n"
                "       %\n"
                "       %Valves must be at most Nv\n"
                ":- valves_number(Nv), not Nv = #count{ X,Y : valve(X,Y) , pipe(X,Y); Y,X : valve(Y,X) , pipe(X,Y)}.\n"
                "\n"
                "       %\n"
                "       %At most X valves per pipe must be allowed (either 1 or 2)\n"
                ":- valves_per_pipe(1), pipe(A,B), valve(A,B), valve(B,A).\n"
                "\n"
                "       %\n"
                "       %some symmetry breaking on valves\n"
                ":- junction(X), not tank(X), symm_pipe(X,A), symm_pipe(X,B),\n"
                "       2 = #count{ X,Y : symm_pipe(X,Y) }, A>B, valve(X,A).\n"
                "\n"
                "       %\n"
                "       %A pipe adjacent to the tank is reached, when a generic pipe is broken iff there is no valve between them.\n"
                "reached(pipe(A,B), broken(X,Y)):- tank(A), pipe(X,Y), pipe(A,B), not closed_valve(v(A,B), broken(X,Y)).\n"
                "reached(pipe(A,B), broken(X,Y)):- tank(B), pipe(X,Y), pipe(A,B), not closed_valve(v(B,A), broken(X,Y)).\n"
                "\n"
                "       %\n"
                "       %Can we recursively reach any tank??\n"
                "reached(pipe(A,B), broken(X,Y)) :- adj(pipe(A,B), pipe(C,D), COM, U1, U2), %COM is not a tank! \n"
                "               not closed_valve(v(COM,U1), broken(X,Y)),\n"
                "               not closed_valve(v(COM,U2), broken(X,Y)),\n"
                "               reached(pipe(C,D), broken(X,Y)).\n"
                "\n"
                "       %\n"
                "       %The broken pipe must be unreachable!\n"
                ":- pipe(A,B), reached(pipe(A,B), broken(A,B)).\n"
                "\n"
                "       %\n"
                "       % Pair-wise comparisons between delivered demand pipe isolation cases\n"
                "%lower(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z),\n"
                "%      #sum [  reached(pipe(A,B), broken(X,Y))=Dn: dem(A,B,Dn),\n"
                "%          reached(pipe(C,D), broken(W,Z))=-Dm: dem(C,D,Dm) ] 0.\n"
                "%lower(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z),\n"
                "%      S1 = #sum { Dn,A,B,X,Y : reached(pipe(A,B), broken(X,Y)), dem(A,B,Dn) },\n"
                "%                S2 = #sum { Dm,C,D,W,Z : reached(pipe(C,D), broken(W,Z)), dem(C,D,Dm) }, S1 - S2 <= 0.\n"
                "lower(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z),\n"
                "       #sum { Dn,A,B,X,Y : reached(pipe(A,B), broken(X,Y)), dem(A,B,Dn);\n"
                "                       Dm,C,D,W,Z : reached(pipe(C,D), broken(W,Z)), dem(C,D,NegDm), Dm = -NegDm } <= 0.\n"
                "\n"
                "       %\n"
                "       %Then the lower are...\n"
                "lower_lexico(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z),\n"
                "               lower(pipe(X,Y), pipe(W,Z)), not lower(pipe(W,Z), pipe(X,Y)).\n"
                "lower_lexico(pipe(X,Y), pipe(X,Y)) :- pipe(X,Y),\n"
                "               lower(pipe(X,Y), pipe(X,Y)).\n"
                "lower_lexico(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z), % with the same delivered demand\n"
                "               lower(pipe(X,Y), pipe(W,Z)), lower(pipe(W,Z),pipe(X,Y)),\n"
                "               less_ico(pipe(X,Y), pipe(W,Z)).\n"
                "\n"
                "       %\n"
                "       %And the worst isolation case is the one for which all lower_lexico are true\n"
                "%worst(pipe(X,Y)) :- pipe(X,Y), lower_lexico(pipe(X,Y),pipe(W,Z)) : pipe(W,Z).\n"
                "worst(pipe(X,Y)) :- pipe(X,Y), C = #count{ W,Z : pipe(W,Z) }, \n"
                "                               D = #count{ X,Y,W,Z : lower_lexico(pipe(X,Y),pipe(W,Z)) , pipe(W,Z)}, C = D.\n"
                "\n"
                "\n"
                "worst_deliv_dem(pipe(A,B), D) :- dem(A,B,D), pipe(X,Y),\n"
                "       reached(pipe(A,B), broken(X,Y)), worst(pipe(X,Y)).\n"
                "\n"
                "       %\n"
                "       %Worst isolation case' delivered demand maximization\n"
                "\n"
                ":~ dem(A,B,D),  not worst_deliv_dem(pipe(A,B),D). [D,A,B]\n", {"valve("}, {343})));
    }

// {{{1 N04 Connected Maximum-density Still Life

    SECTION("aspcomp2013_04") {
        // Author: Christian Drescher
        REQUIRE(
            "([[lives(1,1),lives(1,2),lives(2,1),lives(2,3),lives(3,2),lives(3,4),lives(4,3),lives(4,4)],"
            "[lives(1,2),lives(1,3),lives(2,1),lives(2,4),lives(3,1),lives(3,4),lives(4,2),lives(4,3)],"
            "[lives(1,3),lives(1,4),lives(2,2),lives(2,4),lives(3,1),lives(3,3),lives(4,1),lives(4,2)]],[])" == IO::to_string(solve(
                "%instance\n"
                "\n"
                "size(4).\n"
                "\n"
                "%encoding\n"
                "\n"
                "% possible coordinates\n"
                "value(0).\n"
                "value(V) :- value(V1), V=V1+1, size(N), V1<=N.\n"
                "\n"
                "step(-1).\n"
                "step(1).\n"
                "diff(X,0) :- step(X).\n"
                "diff(0,Y) :- step(Y).\n"
                "diff(X,Y) :- step(X), step(Y).\n"
                "\n"
                "% a cell may live, except for the ones at the border\n"
                "{ lives(X,Y) } <= 1 :- value(X), value(Y), X>0, Y>0, size(N), X<=N, Y<=N.\n"
                "\n"
                "% cells with exactly 3 neighbours must live\n"
                ":- #sum { 1,DX,DY : lives(X+DX,Y+DY), diff(DX,DY) } = 3, not lives(X,Y), value(X), value(Y).\n"
                "\n"
                "% living cells must have 2-3 living neighbours\n"
                ":- lives(X,Y), not 2 <= #sum { 1,DX,DY : lives(X+DX,Y+DY), diff(DX,DY) } <= 3, value(X), value(Y).\n"
                "\n"
                "% connectedness\n"
                "reached(XX,YY) :- XX = #min { X : lives(X,Y), value(X), value(Y) }, YY = #min { Y : lives(XX,Y), value(Y) }.\n"
                "reached(XX,YY) :- reached(X,Y), value(X), value(Y), diff(DX,DY), XX=X+DX, YY=Y+DY, lives(XX,YY).\n"
                ":- lives(X,Y), not reached(X,Y), value(X), value(Y).\n"
                "\n"
                "% maximise living cells\n"
                "%#maximise { 1 : lives(X,Y), value(X), value(Y) }.\n"
                ":~ value(X),value(Y), not lives(X,Y). [1,X,Y]\n", {"lives("}, {28})));
    }

// {{{1 N05 Graceful Graphs

    SECTION("aspcomp2013_05") {
        // Author: Christian Drescher
        REQUIRE(
            "([[value(a,0),value(b,1),value(c,3)],"
            "[value(a,0),value(b,2),value(c,3)],"
            "[value(a,0),value(b,3),value(c,1)],"
            "[value(a,0),value(b,3),value(c,2)],"
            "[value(a,1),value(b,0),value(c,3)],"
            "[value(a,1),value(b,3),value(c,0)],"
            "[value(a,2),value(b,0),value(c,3)],"
            "[value(a,2),value(b,3),value(c,0)],"
            "[value(a,3),value(b,0),value(c,1)],"
            "[value(a,3),value(b,0),value(c,2)],"
            "[value(a,3),value(b,1),value(c,0)],"
            "[value(a,3),value(b,2),value(c,0)]],[])" == IO::to_string(solve(
                "%instance\n"
                "\n"
                "edge(a,b). edge(b,c). edge(c,a).\n"
                "\n"
                "%encoding\n"
                "\n"
                "% nodes and values\n"
                "node(X) :- edge(X,Y).\n"
                "node(Y) :- edge(X,Y).\n"
                "num_edges(N) :- N = #sum { 1,X,Y : edge(X,Y) }.\n"
                "num(0).\n"
                "num(N) :- num(N1), N=N1+1, num_edges(E), N<=E.\n"
                "\n"
                "% assignment to nodes\n"
                "{ value(X,N) : num(N) } = 1 :- node(X).\n"
                "\n"
                "% assignment to edges\n"
                "{ edge_value(edge(X,Y),N) : num(N), N>0 } = 1 :- edge(X,Y).\n"
                "\n"
                "% relates node values with edge values\n"
                ":- not edge_value(edge(X,Y),M-N), edge(X,Y), value(X,M), value(Y,N), N < M.\n"
                ":- not edge_value(edge(X,Y),N-M), edge(X,Y), value(X,M), value(Y,N), N > M.\n"
                "\n"
                "% alldifferent values\n"
                ":- value(X,N), value(Y,N), num(N), X<Y.\n"
                ":- edge_value(X,N), edge_value(Y,N), num(N), X<Y.\n", {"value("})));
    }

// {{{1 N06 Bottle Filling Problem

    SECTION("aspcomp2013_06") {
        // Author: Wolfgang Faber
        REQUIRE(
            "([[filled(1,1),filled(1,2)]],[])" ==
            IO::to_string(solve(
                "% instance\n"
                "\n"
                "xsucc(1,2). ysucc(1,2).\n"
                "bottle(1,1,1). bottle(1,1,2).\n"
                "xvalue(1,1). xvalue(2,1).\n"
                "yvalue(1,2). yvalue(2,0).\n"
                "\n"
                "% encoding\n"
                "\n"
                "filled(X,Y) :- bottle(B,X,Y), not unfilled(X,Y).\n"
                "unfilled(X,Y) :- bottle(B,X,Y), not filled(X,Y).\n"
                "\n"
                ":- xvalue(Y,V), not #count{ X : filled(X,Y) } = V.\n"
                ":- yvalue(X,V), not #count{ Y : filled(X,Y) } = V.\n"
                "\n"
                ":- bottle(B,X1,Y1), bottle(B,X2,Y2), ysucc(Y1,Y2), filled(X1,Y1), unfilled(X2,Y2).\n"
                ":- bottle(B,X1,Y), bottle(B,X2,Y), filled(X1,Y), unfilled(X2,Y), X1 != X2.\n", {"filled("})));
    }

// {{{1 N07 Nomystery

    SECTION("aspcomp2013_07") {
        // Author: Giovambattista Ianni, Carlos Linares López*, Hootan Nakhost*
        REQUIRE(
            "([[drive(t0,a,b,10),drive(t0,a,b,2),drive(t0,a,b,6),drive(t0,b,a,5),drive(t0,b,a,9),load(p0,t0,a,1),load(p0,t0,b,7),unload(p0,t0,b,4)],"
            "[drive(t0,a,b,10),drive(t0,a,b,2),drive(t0,a,b,6),drive(t0,b,a,5),drive(t0,b,a,9),load(p0,t0,a,1),load(p0,t0,b,7),unload(p0,t0,b,4),unload(p0,t0,b,8)],"
            "[drive(t0,a,b,2),drive(t0,a,b,6),drive(t0,b,a,5),drive(t0,b,a,9),load(p0,t0,a,1),load(p0,t0,b,7),unload(p0,t0,a,10),unload(p0,t0,b,4)],"
            "[drive(t0,a,b,2),drive(t0,a,b,6),drive(t0,b,a,5),drive(t0,b,a,9),load(p0,t0,a,1),load(p0,t0,b,7),unload(p0,t0,b,4)],"
            "[drive(t0,a,b,2),drive(t0,a,b,6),drive(t0,b,a,5),drive(t0,b,a,9),load(p0,t0,a,1),load(p0,t0,b,7),unload(p0,t0,b,4),unload(p0,t0,b,8)]],"
            "[-:91:42-43: info: global variable in tuple of aggregate element:\n  S\n])" == IO::to_string(solve(
                "%instance\n"
                "\n"
                "fuelcost(10,a,b). fuelcost(10,b,a).\n"
                "\n"
                "at(t0,a).\n"
                "fuel(t0,56).\n"
                "at(p0,a).\n"
                "goal(p0,b).\n"
                "\n"
                "step(1). step(2). step(3). step(4).\n"
                "step(5). step(6). step(7). step(8).\n"
                "step(9). step(10).\n"
                "\n"
                ":- drive(t0,a,b,4).\n"
                ":- drive(t0,a,b,5).\n"
                ":- drive(t0,a,b,1).\n"
                ":- drive(t0,b,a,6).\n"
                ":- unload(p0,t0,b,3).\n"
                ":- not unload(p0,t0,b,4).\n"
                ":- not drive(t0,a,b,6).\n"
                ":- not load(p0,t0,b,7).\n"
                ":- not load(p0,t0,a,1).\n"
                ":- not drive(t0,a,b,2).\n"
                ":- not drive(t0,b,a,9).\n"
                "\n"
                "%encoding\n"
                "\n"
                "truck(T) :- fuel(T,_).\n"
                "package(P) :- at(P,L), not truck(P).\n"
                "location(L) :- fuelcost(_,L,_).\n"
                "location(L) :- fuelcost(_,_,L).\n"
                "locatable(O) :- at(O,L).\n"
                "%\n"
                "at(O,L,0) :- at(O,L).\n"
                "fuel(T,F,0) :- fuel(T,F).\n"
                "\n"
                "% GENERATE  >>>>>\n"
                "1 <= { unload( P,T,L,S ) : \n"
                "        package( P ) , \n"
                "   truck( T ) , \n"
                "   location( L ); \n"
                "    load( P,T,L,S ) : \n"
                "   package( P ) , \n"
                "   truck( T ) , \n"
                "   location( L ); \n"
                "    drive( T,L1,L2,S ) : \n"
                "   fuelcost( Fueldelta,L1,L2 ) , \n"
                "   truck( T );\n"
                "    noop(S)\n"
                "  } <= 1 :- step(S), S > 0.\n"
                "% <<<<<  GENERATE\n"
                "\n"
                "% unload/4, effects\n"
                "at( P,L,S ) :- unload( P,T,L,S ).\n"
                "del( in( P,T ),S ) :- unload( P,T,L,S ).\n"
                "\n"
                "% load/4, effects\n"
                "del( at( P,L ),S ) :- load( P,T,L,S ).\n"
                "in( P,T,S ) :- load( P,T,L,S ).\n"
                "\n"
                "% drive/4, effects\n"
                "del( at( T,L1 ), S ) :- drive( T,L1,L2,S ).\n"
                "at( T,L2,S ) :- drive( T,L1,L2,S). \n"
                "del( fuel( T,Fuelpre ),S ) :- drive( T,L1,L2,S ), fuel(T, Fuelpre,S-1).\n"
                "fuel( T,Fuelpost,S ) :- drive( T,L1,L2,S ), fuelcost(Fueldelta,L1,L2), fuel(T,Fuelpre,S-1), Fuelpost = Fuelpre - Fueldelta.\n"
                "% <<<<<  EFFECTS APPLY\n"
                "% \n"
                "% INERTIA  >>>>>\n"
                "at( O,L,S ) :- at( O,L,S-1 ), not del( at( O,L ),S  ), step(S).\n"
                "in( P,T,S ) :- in( P,T,S-1 ), not del( in( P,T ),S  ), step(S).\n"
                "fuel( T,Level,S ) :- fuel( T,Level,S-1 ), not del( fuel( T,Level) ,S ), truck( T ), step(S).\n"
                "% <<<<<  INERTIA\n"
                "\n"
                "% PRECONDITIONS CHECK  >>>>>\n"
                "\n"
                "% unload/4, preconditions\n"
                " :- unload( P,T,L,S ), not preconditions_u( P,T,L,S ).\n"
                "preconditions_u( P,T,L,S ) :- step(S), at( T,L,S-1 ), in( P,T,S-1 ), package( P ), truck( T ).\n"
                "\n"
                "% load/4, preconditions\n"
                " :- load( P,T,L,S ), not preconditions_l( P,T,L,S ).\n"
                "preconditions_l( P,T,L,S ) :- step(S), at( T,L,S-1 ), at( P,L,S-1 ).\n"
                "\n"
                "% drive/5, preconditions\n"
                " :- drive( T,L1,L2,S ), not preconditions_d( T,L1,L2,S ).\n"
                "preconditions_d( T,L1,L2,S ) :- step(S), at( T,L1,S-1 ), fuel( T, Fuelpre, S-1), fuelcost(Fueldelta,L1,L2), Fuelpre - Fueldelta >= 0.\n"
                "% <<<<<  PRECONDITIONS HOLD\n"
                "\n"
                "% GOAL CHECK\n"
                "\n"
                "goalreached :- step(S),  N = #count{ P,L,S : at(P,L,S) , goal(P,L) }, N = #count{ P,L : goal(P,L) }.\n"
                ":- not goalreached.\n", {"unload(", "drive(", "load("})));
    }

// {{{1 N08 Sokoban

    SECTION("aspcomp2013_08") {
        // Author: Giovambattista Ianni, Carlos Linares López*, Hootan Nakhost*
        REQUIRE(
            "([[move(player_01,pos_2_2,pos_3_2,dir_right,3),move(player_01,pos_3_2,pos_2_2,dir_left,2),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,1)],"
            "[move(player_01,pos_3_2,pos_2_2,dir_left,2),noop(3),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,1)],"
            "[move(player_01,pos_3_2,pos_2_2,dir_left,3),noop(1),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,2)],"
            "[move(player_01,pos_3_2,pos_2_2,dir_left,3),noop(2),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,1)],"
            "[noop(1),noop(2),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,3)],"
            "[noop(1),noop(3),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,2)],"
            "[noop(2),noop(3),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,1)]],"
            "[-:135:39-40: info: global variable in tuple of aggregate element:\n  T\n])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "player(player_01).\n"
                "stone(stone_01).\n"
                "isgoal(pos_4_2).\n"
                "isnongoal(pos_1_1).\n"
                "isnongoal(pos_1_2).\n"
                "isnongoal(pos_1_3).\n"
                "isnongoal(pos_2_1).\n"
                "isnongoal(pos_2_2).\n"
                "isnongoal(pos_2_3).\n"
                "isnongoal(pos_3_1).\n"
                "isnongoal(pos_3_2).\n"
                "isnongoal(pos_3_3).\n"
                "isnongoal(pos_4_1).\n"
                "isnongoal(pos_4_3).\n"
                "isnongoal(pos_5_1).\n"
                "isnongoal(pos_5_2).\n"
                "isnongoal(pos_5_3).\n"
                "movedir(pos_2_2,pos_3_2,dir_right).\n"
                "movedir(pos_3_2,pos_2_2,dir_left).\n"
                "movedir(pos_3_2,pos_4_2,dir_right).\n"
                "movedir(pos_4_2,pos_3_2,dir_left).\n"
                "at(player_01,pos_2_2).\n"
                "at(stone_01,pos_3_2).\n"
                "clear(pos_4_2).\n"
                "goal(stone_01).\n"
                "step(1).\n"
                "step(2).\n"
                "step(3).\n"
                "\n"
                "% encoding\n"
                "\n"
                "%\n"
                "% Sokoban domain IPC 2008\n"
                "%\n"
                "% Adaptment from IPC 2008 domain description by GB Ianni, using the PDDL2ASP PLASP converter\n"
                "% http://www.cs.uni-potsdam.de/wv/pdfformat/gekaknsc11a.pdf \n"
                "%\n"
                "% \n"
                "\n"
                "\n"
                "% GENERATE  >>>>>\n"
                "1 <= { pushtonongoal( P,S,Ppos,From,To,Dir,T ) : \n"
                "   movedir( Ppos,From,Dir ) ,\n"
                "   movedir( From,To,Dir ) , \n"
                "   isnongoal( To ) , \n"
                "   player( P ) , \n"
                "   stone( S ) , Ppos != To , Ppos != From , From != To; \n"
                "    move( P,From,To,Dir,T ) : \n"
                "   movedir( From,To,Dir ) , \n"
                "   player( P ) , From != To;\n"
                "    pushtogoal( P,S,Ppos,From,To,Dir,T ) : \n"
                "   movedir( Ppos,From,Dir ) , \n"
                "   movedir( From,To,Dir ) , \n"
                "   isgoal( To ) , player( P ) , stone( S ) , Ppos != To , Ppos != From , From != To;\n"
                "    noop(T) } <= 1 :- step(T).\n"
                "\n"
                "% <<<<<  GENERATE\n"
                "% \n"
                "\n"
                "% \n"
                "%\n"
                "% Initial state\n"
                "at(P,To,0) :- at(P,To).\n"
                "clear(P,0) :- clear(P).\n"
                "atgoal(S,0) :- isgoal(L), stone(S), at(S,L).\n"
                " \n"
                "% EFFECTS APPLY  >>>>>\n"
                "\n"
                "% push-to-nongoal/7, effects\n"
                "del( at( P,Ppos ),Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), \n"
                "                          movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "del( at( S,From ),Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "del( clear( To ),Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "at( P,From,Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "at( S,To,Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "clear( Ppos,Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "del( atgoal( S ),Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "\n"
                "% move/5, effects\n"
                "del( at( P,From ),Ti ) :- move( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n"
                "del( clear( To ),Ti ) :- move( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n"
                "at( P,To,Ti ) :- move( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n"
                "clear( From,Ti ) :- move( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n"
                "\n"
                "% push-to-goal/7, effects\n"
                "del( at( P,Ppos ),Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n"
                "                          movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "del( at( S,From ),Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n"
                "                          movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "del( clear( To ),Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n"
                "                         movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "at( P,From,Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n"
                "                   movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "at( S,To,Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n"
                "                 movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "clear( Ppos,Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n"
                "                    movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "atgoal( S,Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n"
                "                  stone( S ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "% <<<<<  EFFECTS APPLY\n"
                "% \n"
                "\n"
                "% \n"
                "% \n"
                "% INERTIA  >>>>>\n"
                "clear( L,Ti ) :- clear( L,Ti-1 ), not del( clear( L ),Ti  ), step(Ti).\n"
                "atgoal( S,Ti ) :- atgoal( S,Ti-1 ), not del( atgoal( S ),Ti ), stone( S ), step(Ti).\n"
                "at( T,L,Ti ) :- at( T,L,Ti-1 ), not del( at( T,L ) ,Ti  ), step(Ti).\n"
                "% <<<<<  INERTIA\n"
                "% \n"
                "\n"
                "% \n"
                "% \n"
                "% PRECONDITIONS HOLD  >>>>>\n"
                "\n"
                "% push-to-nongoal/6, preconditions\n"
                " :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), not preconditions_png( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n"
                "preconditions_png( P,S,Ppos,From,To,Dir,Ti ) :- at( P,Ppos,Ti-1 ), at( S,From,Ti-1 ), clear( To,Ti-1 ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To, step(Ti).\n"
                "\n"
                "% move/4, preconditions\n"
                " :- move( P,From,To,Dir,Ti ), not preconditions_m( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n"
                "preconditions_m( P,From,To,Dir,Ti ) :- at( P,From,Ti-1 ), clear( To,Ti-1 ), movedir( From,To,Dir ), movedir( From,To,Dir ), player( P ), From != To, step(Ti).\n"
                "\n"
                "% push-to-goal/6, preconditions\n"
                " :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), not preconditions_pg( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To, step(Ti).\n"
                "preconditions_pg( P,S,Ppos,From,To,Dir,Ti ) :- at( P,Ppos,Ti-1 ), at( S,From,Ti-1 ), clear( To,Ti-1 ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To, step(Ti).\n"
                "\n"
                "% <<<<<  PRECONDITIONS HOLD\n"
                "% \n"
                "%\n"
                "% Goal Reached check \n"
                "%\n"
                "goalreached :- step(T), N = #count{ X,T : atgoal(X,T) , goal(X) }, N = #count{ X : goal(X) }.\n"
                ":- not goalreached.\n"
                "\n"
                "% Gringo directives to show / hide particular literals\n"
                "%#hide.\n"
                "%#show pushtonongoal/7.\n"
                "%#show move/5.\n"
                "%#show pushtogoal/7.\n"
                , {"pushtonongoal(", "pushtogoal(", "move(", "noop("})));
    }

// {{{1 N09 Ricochet Robots

    SECTION("aspcomp2013_09") {
        // Author: Julius Höfler, Martin Gebser, Philipp Obermeier, Roland Kaminski, Torsten Schaub
        REQUIRE(
            "([[go(blue,east,1,2),go(blue,east,2),go(blue,north,-1,1),go(blue,north,1),go(blue,south,-1,3),go(blue,south,3),go(red,east,1,4),go(red,east,4),go(red,south,-1,5),go(red,south,5)],"
                "[go(blue,east,1,2),go(blue,east,2),go(blue,north,-1,1),go(blue,north,1),go(blue,south,-1,4),go(blue,south,4),go(red,east,1,3),go(red,east,3),go(red,south,-1,5),go(red,south,5)],"
                "[go(blue,east,1,3),go(blue,east,3),go(blue,north,-1,1),go(blue,north,1),go(blue,south,-1,4),go(blue,south,4),go(red,east,1,2),go(red,east,2),go(red,south,-1,5),go(red,south,5)],"
                "[go(blue,east,1,3),go(blue,east,3),go(blue,north,-1,2),go(blue,north,2),go(blue,south,-1,4),go(blue,south,4),go(red,east,1),go(red,east,1,1),go(red,south,-1,5),go(red,south,5)],"
                "[go(blue,east,1,4),go(blue,east,4),go(blue,north,-1,1),go(blue,north,1),go(red,east,1,2),go(red,east,2),go(red,north,-1,5),go(red,north,5),go(red,south,-1,3),go(red,south,3)],"
                "[go(blue,east,1,4),go(blue,east,4),go(blue,north,-1,2),go(blue,north,2),go(red,east,1),go(red,east,1,1),go(red,north,-1,5),go(red,north,5),go(red,south,-1,3),go(red,south,3)],"
                "[go(blue,east,1,4),go(blue,east,4),go(blue,north,-1,3),go(blue,north,3),go(red,east,1),go(red,east,1,1),go(red,north,-1,5),go(red,north,5),go(red,south,-1,2),go(red,south,2)],"
                "[go(green,south,-1,3),go(green,south,3),go(green,west,1,4),go(green,west,4),go(red,east,1),go(red,east,1,1),go(red,south,-1,5),go(red,south,5),go(yellow,west,1,2),go(yellow,west,2)],"
                "[go(green,south,-1,3),go(green,south,3),go(green,west,1,4),go(green,west,4),go(red,east,1,2),go(red,east,2),go(red,south,-1,5),go(red,south,5),go(yellow,west,1),go(yellow,west,1,1)],"
                "[go(green,south,-1,3),go(green,south,3),go(red,east,1),go(red,east,1,1),go(red,south,-1,5),go(red,south,5),go(yellow,east,1,4),go(yellow,east,4),go(yellow,west,1,2),go(yellow,west,2)],"
                "[go(green,south,-1,3),go(green,south,3),go(red,east,1,2),go(red,east,2),go(red,south,-1,5),go(red,south,5),go(yellow,east,1,4),go(yellow,east,4),go(yellow,west,1),go(yellow,west,1,1)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "dim(1). dim(2). dim(3).\n"
                "dim(4). dim(5).\n"
                "\n"
                "pos(red,   1,1). pos(blue,  1,5).\n"
                "pos(green, 5,1). pos(yellow,5,5).\n"
                "\n"
                "barrier(1,2,south). barrier(4,3,east).\n"
                "barrier(2,5,east).\n"
                "\n"
                "target(red,4,4).\n"
                "\n"
                "length(5).\n"
                "\n"
                "% encoding\n"
                "\n"
                "dir(west, -1, 0).\n"
                "dir(east,  1, 0).\n"
                "dir(north, 0,-1).\n"
                "dir(south, 0, 1).\n"
                "\n"
                "dl(west, -1).\n"
                "dl(north,-1).\n"
                "dl(east,  1).\n"
                "dl(south, 1).\n"
                "\n"
                "dir(west, 1).   %dir(west, row).\n"
                "dir(east, 1).   %dir(east, row).\n"
                "dir(north, -1). %dir(north,col).\n"
                "dir(south, -1). %dir(south,col).\n"
                "\n"
                "dir(D) :- dir(D,_).\n"
                "\n"
                "robot(R) :- pos(R,_,_).\n"
                "\n"
                "pos(R,1,I,0) :- pos(R,I,_).  %pos(R,row,I,0) :- pos(R,I,_).\n"
                "pos(R,-1,J,0) :- pos(R,_,J). %pos(R,col,J,0) :- pos(R,_,J).\n"
                "\n"
                "barrier(I+1,J,west ) :- barrier(I,J,east ), dim(I), dim(J), dim(I+1).\n"
                "barrier(I,J+1,north) :- barrier(I,J,south), dim(I), dim(J), dim(J+1).\n"
                "barrier(I-1,J,east ) :- barrier(I,J,west ), dim(I), dim(J), dim(I-1).\n"
                "barrier(I,J-1,south) :- barrier(I,J,north), dim(I), dim(J), dim(I-1).\n"
                "\n"
                "conn(D,I,J) :- dir(D,-1), dir(D,_,DJ), not barrier(I,J,D), dim(I), dim(J), dim(J+DJ). %conn(D,I,J) :- dir(D,col), dir(D,_,DJ), not barrier(I,J,D), dim(I), dim(J), dim(J+DJ).\n"
                "conn(D,J,I) :- dir(D,1), dir(D,DI,_), not barrier(I,J,D), dim(I), dim(J), dim(I+DI).  %conn(D,J,I) :- dir(D,row), dir(D,DI,_), not barrier(I,J,D), dim(I), dim(J), dim(I+DI).\n"
                "\n"
                "%step(1..X) :- length(X).\n"
                "step(1).\n"
                "step(X+1) :- step(X), length(L), X < L. \n"
                "\n"
                "1 <= { selectRobot(R,T) : robot(R) } <= 1 :- step(T).\n"
                "1 <= { selectDir(D,O,T) : dir(D,O) } <= 1 :- step(T).\n"
                "\n"
                "go(R,D,O,T) :- selectRobot(R,T), selectDir(D,O,T).\n"
                "go_(R,O,T)   :- go(R,_,O,T).\n"
                "go(R,D,T) :- go(R,D,_,T).\n"
                "\n"
                "sameLine(R,D,O,RR,T)  :- go(R,D,O,T), pos(R,-O,L,T-1), pos(RR,-O,L,T-1), R != RR.\n"
                "blocked(R,D,O,I+DI,T) :- go(R,D,O,T), pos(R,-O,L,T-1), not conn(D,L,I), dl(D,DI), dim(I), dim(I+DI).\n"
                "blocked(R,D,O,L,T)    :- sameLine(R,D,O,RR,T), pos(RR,O,L,T-1).\n"
                "\n"
                "reachable(R,D,O,I,   T) :- go(R,D,O,T), pos(R,O,I,T-1).\n"
                "reachable(R,D,O,I+DI,T) :- reachable(R,D,O,I,T), not blocked(R,D,O,I+DI,T), dl(D,DI), dim(I+DI).\n"
                "\n"
                ":- go(R,D,O,T), pos(R,O,I,T-1), blocked(R,D,O,I+DI,T), dl(D,DI).\n"
                ":- go(R,D,O,T), go(R,DD,O,T-1).\n"
                "\n"
                "pos(R,O,I,T) :- reachable(R,D,O,I,T), not reachable(R,D,O,I+DI,T), dl(D,DI).\n"
                "pos(R,O,I,T) :- pos(R,O,I,T-1), not go_(R,O,T), step(T).\n"
                "\n"
                "selectDir(O,T) :- selectDir(D,O,T).\n"
                "\n"
                ":- target(R,I,_), not pos(R,1,I,X), length(X).  %:- target(R,I,_), not pos(R,row,I,X), length(X).\n"
                ":- target(R,_,J), not pos(R,-1,J,X), length(X). %:- target(R,_,J), not pos(R,col,J,X), length(X).\n", {"go("})));
    }

// {{{1 O10 Crossing Minimization

    SECTION("aspcomp2013_10") {
        // Author: Carmine Dodaro, Graeme Gange*, Peter Stuckey*
        REQUIRE(
            "([[position(n1,1),position(n10,4),position(n11,1),position(n12,3),position(n13,8),position(n14,9),position(n15,5),position(n16,6),position(n17,2),position(n18,7),position(n19,1),position(n2,3),position(n20,7),position(n21,2),position(n22,3),position(n23,8),position(n24,9),position(n25,5),position(n26,4),position(n27,6),position(n3,7),position(n4,2),position(n5,8),position(n6,9),position(n7,6),position(n8,4),position(n9,5)],"
            "[position(n1,1),position(n10,4),position(n11,1),position(n12,3),position(n13,8),position(n14,9),position(n15,5),position(n16,6),position(n17,2),position(n18,7),position(n19,2),position(n2,3),position(n20,7),position(n21,1),position(n22,3),position(n23,8),position(n24,9),position(n25,5),position(n26,4),position(n27,6),position(n3,7),position(n4,2),position(n5,8),position(n6,9),position(n7,6),position(n8,4),position(n9,5)],"
            "[position(n1,1),position(n10,4),position(n11,1),position(n12,3),position(n13,8),position(n14,9),position(n15,5),position(n16,6),position(n17,2),position(n18,7),position(n19,3),position(n2,3),position(n20,7),position(n21,1),position(n22,2),position(n23,8),position(n24,9),position(n25,5),position(n26,4),position(n27,6),position(n3,7),position(n4,2),position(n5,8),position(n6,9),position(n7,6),position(n8,4),position(n9,5)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "layers(3).\n"
                "width(0,9).\n"
                "in_layer(0,n1).  in_layer(0,n2).  in_layer(0,n3).  in_layer(0,n4).  in_layer(0,n5).  \n"
                "in_layer(0,n6).  in_layer(0,n7).  in_layer(0,n8).  in_layer(0,n9).\n"
                "width(1,9).\n"
                "in_layer(1,n10).  in_layer(1,n11).  in_layer(1,n12).  in_layer(1,n13).  in_layer(1,n14).\n"
                "in_layer(1,n15).  in_layer(1,n16).  in_layer(1,n17).  in_layer(1,n18).\n"
                "width(2,9).\n"
                "in_layer(2,n19).  in_layer(2,n20).  in_layer(2,n21).  in_layer(2,n22).  in_layer(2,n23).\n"
                "in_layer(2,n24).  in_layer(2,n25).  in_layer(2,n26).  in_layer(2,n27).\n"
                "edge(n16,n20).  edge(n10,n26).  edge(n17,n26).  edge(n10,n25).  edge(n6,n14).\n"
                "edge(n7,n15).  edge(n6,n13).  edge(n7,n10).  edge(n18,n27).  edge(n18,n20).\n"
                "edge(n16,n27).  edge(n12,n22).  edge(n8,n12).  edge(n18,n25).  edge(n18,n23).\n"
                "edge(n9,n18).  edge(n3,n13).  edge(n4,n12).  edge(n11,n21).  edge(n13,n24).\n"
                "edge(n1,n11).  edge(n15,n25).  edge(n11,n22).  edge(n17,n25).  edge(n17,n21).\n"
                "edge(n12,n27).  edge(n7,n13).  edge(n9,n10).  edge(n14,n24).  edge(n16,n25).\n"
                "edge(n5,n13).  edge(n12,n25).  \n"
                "\n"
                ":- not position(n1,1).\n"
                ":- not position(n2,3).\n"
                ":- not position(n23,8).\n"
                ":- not position(n24,9).\n"
                ":- not position(n26,4).\n"
                ":- not position(n27,6).\n"
                ":- not position(n3,7).\n"
                ":- not position(n4,2).\n"
                ":- position(n10,1).\n"
                ":- position(n10,2).\n"
                ":- position(n10,3).\n"
                ":- position(n10,5).\n"
                ":- position(n10,6).\n"
                ":- position(n10,7).\n"
                ":- position(n10,8).\n"
                ":- position(n10,9).\n"
                ":- position(n11,2).\n"
                ":- position(n15,2).\n"
                ":- position(n15,3).\n"
                ":- position(n15,4).\n"
                ":- position(n15,6).\n"
                ":- position(n16,3).\n"
                ":- position(n16,4).\n"
                ":- position(n16,5).\n"
                ":- position(n16,7).\n"
                ":- position(n17,9).\n"
                ":- position(n18,1).\n"
                ":- position(n18,2).\n"
                ":- position(n18,3).\n"
                ":- position(n18,4).\n"
                ":- position(n18,5).\n"
                ":- position(n18,6).\n"
                ":- position(n18,8).\n"
                ":- position(n18,9).\n"
                ":- position(n19,5).\n"
                ":- position(n19,6).\n"
                ":- position(n19,7).\n"
                ":- position(n19,8).\n"
                ":- position(n23,1).\n"
                ":- position(n23,2).\n"
                ":- position(n23,3).\n"
                ":- position(n23,5).\n"
                ":- position(n23,6).\n"
                ":- position(n23,7).\n"
                ":- position(n23,9).\n"
                ":- position(n24,1).\n"
                ":- position(n24,2).\n"
                ":- position(n24,3).\n"
                ":- position(n24,4).\n"
                ":- position(n24,5).\n"
                "\n"
                "% encoding\n"
                "\n"
                "%%guess\n"
                "pvalue(L,0) :- width(L,_).\n"
                "pvalue(L,X+1) :- pvalue(L,X), width(L,T), X < T.\n"
                "position( Node, Pos ) | not_position( Node, Pos ) :- in_layer( Layer, Node ), width( Layer, T ), Pos = P + 1, \n"
                "                                                     pvalue(Layer,P), P < T.\n"
                "\n"
                "%%check\n"
                "%a node must be assigned at most at one position.\n"
                ":- position( Node1, Pos1 ), position( Node1, Pos2 ), Pos1 < Pos2.\n"
                "\n"
                "%two nodes of the same layer cannot be assigned at the same position.\n"
                ":- in_layer( Layer1, Node1 ), in_layer( Layer1, Node2 ), position( Node1, Pos1 ), position( Node2, Pos1 ), Node1 != Node2.\n"
                "\n"
                "%a node must be assigned at least at one position.  \n"
                "node_assigned_at_position( Node ) :- position( Node, Pos ).\n"
                ":- in_layer( Layer1, Node1 ), not node_assigned_at_position( Node1 ).\n"
                "\n"
                "\n"
                "%%optimization\n"
                "%Computing the edges from same layers.\n"
                "edge_from_same_layers(Node1,Node2,Node3,Node4):- edge(Node1,Node2), edge(Node3,Node4), Node1 < Node3, Node2 != Node4, in_layer(Layer,Node1), in_layer(Layer,Node3).\n"
                "\n"
                "%Computing all the crossings.\n"
                "crossing(Node1,Node2,Node3,Node4) :- edge_from_same_layers(Node1,Node2,Node3,Node4), antecedent(Node1,Node3), antecedent(Node4,Node2). \n"
                "crossing(Node1,Node2,Node3,Node4) :- edge_from_same_layers(Node1,Node2,Node3,Node4), antecedent(Node3,Node1), antecedent(Node2,Node4).\n"
                "\n"
                "% A node Node1 is an antecedent of a node Node2 if they are in the same layer and the Node1 position is antecedent of the Node2 position.\n"
                "antecedent(Node1,Node2):- in_layer(Layer,Node1), in_layer(Layer,Node2), Node1 != Node2, position(Node1,Pos1), position(Node2,Pos2), Pos1 < Pos2.\n"
                "\n"
                "% Assign a penalty to each violation of the crossing.\n"
                ":~ crossing(Node1, Node2, Node3, Node4 ). [1,Node1,Node2,Node3,Node4]\n", {"position("}, {15})));
    }

// N11: needs queries
// N12: needs queries
// {{{1 O13 Solitaire

    SECTION("aspcomp2013_13") {
        // Author: Marcello Balduccini, Yuliya Lierler*
        REQUIRE(
            "([[move(1,left,6,3),move(2,right,3,3),move(3,up,3,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,right,2,3),move(2,up,2,5),move(3,up,3,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,right,2,3),move(2,up,3,5),move(3,left,4,3),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,right,2,3),move(2,up,3,5),move(3,left,5,4),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,right,2,3),move(2,up,3,5),move(3,right,1,4),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,right,2,3),move(2,up,3,5),move(3,up,2,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,up,4,5),move(2,left,6,4),move(3,right,2,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,up,4,5),move(2,right,2,4),move(3,right,2,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,up,4,5),move(2,right,2,5),move(3,down,2,3),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,up,4,5),move(2,right,2,5),move(3,left,6,4),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)],"
            "[move(1,up,4,5),move(2,right,2,5),move(3,right,2,4),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]],"
            "[-:56:22-23: info: global variable in tuple of aggregate element:\n  T\n"
            ",-:51:76-93: info: atom does not occur in any rule head:\n  checking_solution\n"
            ",-:56:94-111: info: atom does not occur in any rule head:\n  checking_solution\n])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "time(1).  time(2).  time(3).  time(4).  time(5).  time(6).\n"
                "full(3,1).  full(4,1).  full(5,1).  full(3,2).  full(4,2).  full(5,2).\n"
                "full(1,3).  full(2,3).  full(3,3).  empty(4,3).  full(5,3).  full(6,3).\n"
                "full(7,3).  full(1,4).  full(2,4).  full(3,4).  full(4,4).  full(5,4).\n"
                "full(6,4).  full(7,4).  full(1,5).  full(2,5).  full(3,5).  full(4,5).\n"
                "full(5,5).  full(6,5).  full(7,5).  full(3,6).  full(4,6).  full(5,6).\n"
                "full(3,7).  full(4,7).  full(5,7).\n"
                "\n"
                ":- not move(6,down,7,3).\n"
                ":- not move(4,left,5,5).\n"
                "\n"
                "% encoding\n"
                "\n"
                "% 2x2 squares in the corner aren't used\n"
                "range(1).\n"
                "range(X+1) :- range(X), X < 7.\n"
                "\n"
                "location(1,X) :- range(X), 3 <= X, X <= 5.\n"
                "location(2,X) :- range(X), 3 <= X, X <= 5.\n"
                "location(Y,X) :- range(Y), 3 <= X, X <= 5, range(X).\n"
                "location(6,X) :- range(X), 3 <= X, X <= 5.\n"
                "location(7,X) :- range(X), 3 <= X, X <= 5.\n"
                "\n"
                "% Moves can be made in one of four directions\n"
                "direction(up).\n"
                "direction(down).\n"
                "direction(left).\n"
                "direction(right).\n"
                "\n"
                "% Each location is either full or empty\n"
                "status(full).\n"
                "status(empty).\n"
                "\n"
                "% Can move a full location over a full location to an empty one.\n"
                "possibleMove(T,up,X,Y) :-  state(T,full,X,Y), state(T,full,X,Y-1), state(T,empty,X,Y-2),\n"
                "                      time(T), location(X,Y),     location(X,Y-1),      location(X,Y-2).\n"
                "\n"
                "possibleMove(T,down,X,Y) :-  state(T,full,X,Y), state(T,full,X,Y+1), state(T,empty,X,Y+2),\n"
                "                        time(T), location(X,Y),     location(X,Y+1),      location(X,Y+2).\n"
                "\n"
                "possibleMove(T,left,X,Y) :-  state(T,full,X,Y), state(T,full,X-1,Y), state(T,empty,X-2,Y),\n"
                "                        time(T), location(X,Y),     location(X-1,Y),      location(X-2,Y).\n"
                "\n"
                "possibleMove(T,right,X,Y) :-  state(T,full,X,Y), state(T,full,X+1,Y), state(T,empty,X+2,Y),\n"
                "                         time(T), location(X,Y),     location(X+1,Y),      location(X+2,Y).\n"
                "\n"
                "\n"
                "%% At each time step choose a move\n"
                "1 <= { move(T,D,X,Y) : direction(D) , location(X,Y) } <= 1 :- time(T), not checking_solution.\n"
                "\n"
                "%% CHECKER [marcy 011111]\n"
                "%% Exactly one move must be present at each step.\n"
                "%% Only needed if the choice rule is not enabled.\n"
                ":- not 1 <= #count { T,D,X,Y : move(T,D,X,Y) , direction(D) , location(X,Y) } <= 1, time(T), checking_solution.\n"
                "\n"
                "% A move must be possible\n"
                " :- move(T,D,X,Y), not possibleMove(T,D,X,Y), time(T), direction(D), location(X,Y).\n"
                "\n"
                "% Now need to look at the effect of moves\n"
                "% (section location parameter to cut grounding size)\n"
                "state(T+1,empty,X,Y) :- move(T,up,X,Y), location(X,Y), time(T).\n"
                "state(T+1,empty,X,Y-1) :- move(T,up,X,Y), location(X,Y), location(X,Y-1), time(T).\n"
                "state(T+1,full,X,Y-2) :- move(T,up,X,Y), location(X,Y), location(X,Y-2), time(T).\n"
                "\n"
                "state(T+1,empty,X,Y) :- move(T,down,X,Y), location(X,Y), time(T).\n"
                "state(T+1,empty,X,Y+1) :- move(T,down,X,Y), location(X,Y), location(X,Y+1), time(T).\n"
                "state(T+1,full,X,Y+2) :- move(T,down,X,Y), location(X,Y), location(X,Y+2), time(T).\n"
                "\n"
                "state(T+1,empty,X,Y) :- move(T,left,X,Y), location(X,Y), time(T).\n"
                "state(T+1,empty,X-1,Y) :- move(T,left,X,Y), location(X,Y), location(X-1,Y), time(T).\n"
                "state(T+1,full,X-2,Y) :- move(T,left,X,Y), location(X,Y), location(X-2,Y), time(T).\n"
                "\n"
                "state(T+1,empty,X,Y) :- move(T,right,X,Y), location(X,Y), time(T).\n"
                "state(T+1,empty,X+1,Y) :- move(T,right,X,Y), location(X,Y), location(X+1,Y), time(T).\n"
                "state(T+1,full,X+2,Y) :- move(T,right,X,Y), location(X,Y), location(X+2,Y), time(T).\n"
                "\n"
                "\n"
                "changed(T+1,X,Y) :- move(T,up,X,Y), location(X,Y), time(T).\n"
                "changed(T+1,X,Y-1) :- move(T,up,X,Y), location(X,Y), location(X,Y-1), time(T).\n"
                "changed(T+1,X,Y-2) :- move(T,up,X,Y), location(X,Y), location(X,Y-2), time(T).\n"
                "\n"
                "changed(T+1,X,Y) :- move(T,down,X,Y), location(X,Y), time(T).\n"
                "changed(T+1,X,Y+1) :- move(T,down,X,Y), location(X,Y), location(X,Y+1), time(T).\n"
                "changed(T+1,X,Y+2) :- move(T,down,X,Y), location(X,Y), location(X,Y+2), time(T).\n"
                "\n"
                "changed(T+1,X,Y) :- move(T,left,X,Y), location(X,Y), time(T).\n"
                "changed(T+1,X-1,Y) :- move(T,left,X,Y), location(X,Y), location(X-1,Y), time(T).\n"
                "changed(T+1,X-2,Y) :- move(T,left,X,Y), location(X,Y), location(X-2,Y), time(T).\n"
                "\n"
                "changed(T+1,X,Y) :- move(T,right,X,Y), location(X,Y), time(T).\n"
                "changed(T+1,X+1,Y) :- move(T,right,X,Y), location(X,Y), location(X+1,Y), time(T).\n"
                "changed(T+1,X+2,Y) :- move(T,right,X,Y), location(X,Y), location(X+2,Y), time(T).\n"
                "\n"
                "state(T+1,S,X,Y) :- not changed(T+1,X,Y), state(T,S,X,Y), status(S), location(X,Y), time(T).\n"
                "\n"
                "state(1,full,X,Y) :- full(X,Y).\n"
                "state(1,empty,X,Y) :- empty(X,Y).\n", {"move("})));
    }


// {{{1 O14 Weighted-Sequence Problem

    SECTION("aspcomp2013_14") {
        // Author: Marcello Balduccini, Yuliya Lierlier, Shaden Smith
        REQUIRE(
           "([[leafPos(1,0),leafPos(2,1),leafPos(3,2),posColor(1,blue),posColor(2,red)],"
           "[leafPos(1,0),leafPos(2,1),leafPos(3,2),posColor(1,green),posColor(2,red)],"
           "[leafPos(1,0),leafPos(2,1),leafPos(3,2),posColor(1,red),posColor(2,red)],"
           "[leafPos(1,2),leafPos(2,1),leafPos(3,0),posColor(1,blue),posColor(2,red)],"
           "[leafPos(1,2),leafPos(2,1),leafPos(3,0),posColor(1,green),posColor(2,red)],"
           "[leafPos(1,2),leafPos(2,1),leafPos(3,0),posColor(1,red),posColor(2,red)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "leafWeightCardinality(1,45,44). leafWeightCardinality(2,21,3). leafWeightCardinality(3,64,74).\n"
                "\n"
                "innerNode(1). innerNode(2).\n"
                "\n"
                "num(3). max_total_weight(495).\n"
                "\n"
                ":- not leafPos(2,1).\n"
                ":- not posColor(2,red).\n"
                "\n"
                "% encoding\n"
                "\n"
                "color(red).\n"
                "color(blue).\n"
                "color(green).\n"
                "\n"
                "leafWeight(X,W)  :-leafWeightCardinality(X,W,C).\n"
                "\n"
                "leafCard(X,C)  :-leafWeightCardinality(X,W,C).\n"
                "\n"
                "leaf(X):-leafWeightCardinality(X,W,C).\n"
                "\n"
                "%%\n"
                "%% Sequence Definition\n"
                "%%\n"
                "\n"
                "coloredPos(1).\n"
                "coloredPos(X+1):- coloredPos(X),  X < N-1, num(N).\n"
                "%coloredPos(X):-  X=1..N-1, num(N).\n"
                "location(0).\n"
                "location(X+1) :- location(X), X < N-1, num(N).\n"
                "%location(X):-X=0..N-1, num(N).\n"
                "\n"
                "1 <= {leafPos(L,N) : location(N) } <= 1 :- leaf(L).\n"
                "% No sharing locations\n"
                "%:- leafPos(L1, N), leafPos(L2, N), location(N), L1 != L2.\n"
                "1 <= { leafPos(L,N) : leaf(L) } <= 1 :- location(N).\n"
                "\n"
                "%%\n"
                "%% each node at colordPos has a unique color\n"
                "%%\n"
                "1 <= {posColor(P,C):color(C)} <= 1:-coloredPos(P).\n"
                "\n"
                "% BEGIN Weight T  definition\n"
                "\n"
                "%  if color of X is green\n"
                "%    weight(X) = weight(right child of X) + cardinality(right child of X) \n"
                "%\n"
                "nWeight(0,W):- leafWeightCardinality(L,W,C), leafPos(L,0).\n"
                "\n"
                "nWeight(P,W):- W= W1+C, posColor(P,green),\n"
                "           leafWeight(R,W1), leafCard(R,C),\n"
                "            coloredPos(P), leafPos(R,P), leaf(R),  W<=M, max_total_weight(M).\n"
                "\n"
                "\n"
                "\n"
                "\n"
                "%  if color of X is red\n"
                "%     weight(X) = weight(right child of X) + weight(left child of X) \n"
                "nWeight(P,W):- W= W1+W2, posColor(P,red),\n"
                "           leafWeight(R,W1),nWeight(P-1,W2),\n"
                "           coloredPos(P), leafPos(R,P),\n"
                "            leaf(R),  W<=M, max_total_weight(M).\n"
                "\n"
                "\n"
                "\n"
                "%  if color(X) is blue\n"
                "%     weight(X) = cardinality(right child of X) + weight(left child of X) \n"
                "nWeight(P,W):- W= W1+C,   posColor(P,blue),\n"
                "           leafCard(R,C), nWeight(P-1,W1),\n"
                "           coloredPos(P),leafPos(R,P),   \n"
                "            leaf(R),  W<=M, max_total_weight(M).\n"
                "\n"
                "%%\n"
                "%% Weights related Tests\n"
                "%%\n"
                "\n"
                "%% \n"
                "%% definition of a total weight of a prime tree T'\n"
                "tWeight(1,W):-nWeight(1,W), coloredPos(1),  W<=M, max_total_weight(M).\n"
                "tWeight(N,W):-W=W1+W2, tWeight(N-1,W1), nWeight(N,W2),coloredPos(N),N>1,  W<=M, max_total_weight(M).\n"
                "\n"
                "% END Weight T definition\n"
                "% --------------------------------------------------------------\n"
                "% --------------------------------------------------------------\n"
                "% --------------------------------------------------------------\n"
                "% exists Definition\n"
                "\n"
                "exists:-tWeight(N-1,W), W<=M, max_total_weight(M),num(N).\n"
                ":-not exists.\n", {"leafPos(", "posColor("})));
    }

// {{{1 O15 Stable Marriage

    SECTION("aspcomp2013_15") {
        // Author: Mario Alviano, Carmine Dodaro, Francesco Ricca
        REQUIRE(
            "([[match(m_1,w_1),match(m_2,w_3),match(m_3,w_2),match(m_4,w_4)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "manAssignsScore(m_1,w_1,4). manAssignsScore(m_1,w_2,2). manAssignsScore(m_1,w_3,2). manAssignsScore(m_1,w_4,1).\n"
                "manAssignsScore(m_2,w_1,2). manAssignsScore(m_2,w_2,1). manAssignsScore(m_2,w_3,4). manAssignsScore(m_2,w_4,3).\n"
                "manAssignsScore(m_3,w_1,1). manAssignsScore(m_3,w_2,3). manAssignsScore(m_3,w_3,2). manAssignsScore(m_3,w_4,2).\n"
                "manAssignsScore(m_4,w_1,2). manAssignsScore(m_4,w_2,3). manAssignsScore(m_4,w_3,4). manAssignsScore(m_4,w_4,1).\n"
                "\n"
                "womanAssignsScore(w_1,m_1,3). womanAssignsScore(w_1,m_2,4). womanAssignsScore(w_1,m_3,2). womanAssignsScore(w_1,m_4,1).\n"
                "womanAssignsScore(w_2,m_1,1). womanAssignsScore(w_2,m_2,4). womanAssignsScore(w_2,m_3,3). womanAssignsScore(w_2,m_4,2).\n"
                "womanAssignsScore(w_3,m_1,4). womanAssignsScore(w_3,m_2,2). womanAssignsScore(w_3,m_3,3). womanAssignsScore(w_3,m_4,1).\n"
                "womanAssignsScore(w_4,m_1,3). womanAssignsScore(w_4,m_2,2). womanAssignsScore(w_4,m_3,4). womanAssignsScore(w_4,m_4,1).\n"
                "\n"
                "% encoding\n"
                "\n"
                "% guess matching\n"
                "match(M,W) :- manAssignsScore(M,_,_), womanAssignsScore(W,_,_), not nonMatch(M,W).\n"
                "nonMatch(M,W) :- manAssignsScore(M,_,_), womanAssignsScore(W,_,_), not match(M,W).\n"
                "\n"
                "% no polygamy\n"
                ":- match(M1,W), match(M,W), M <> M1.\n"
                ":- match(M,W), match(M,W1), W <> W1.\n"
                "\n"
                "% no singles\n"
                "jailed(M) :- match(M,_).\n"
                ":- manAssignsScore(M,_,_), not jailed(M).\n"
                "\n"
                "% strong stability condition\n"
                ":- match(M,W1), manAssignsScore(M,W,Smw), W1 <> W, manAssignsScore(M,W1,Smw1),   Smw >  Smw1,\n"
                "   match(M1,W), womanAssignsScore(W,M,Swm),        womanAssignsScore(W,M1,Swm1), Swm >= Swm1.\n"
                , {"match("})));
    }

// {{{1 O16 Incremental Scheduling

    SECTION("aspcomp2013_16") {
        // Author: Marcello Balduccini, Yuliya Lierler*
        REQUIRE(
            "([[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,0),penalty(j3,2),start(j1,0),start(j2,4),start(j3,9),tot_penalty(2)],"
            "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,1),penalty(j3,0),start(j1,0),start(j2,6),start(j3,2),tot_penalty(1)],"
            "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,2),penalty(j3,0),start(j1,0),start(j2,7),start(j3,2),tot_penalty(2)],"
            "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,2),penalty(j3,0),start(j1,0),start(j2,7),start(j3,3),tot_penalty(2)],"
            "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,3),penalty(j3,0),start(j1,0),start(j2,8),start(j3,2),tot_penalty(3)],"
            "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,3),penalty(j3,0),start(j1,0),start(j2,8),start(j3,3),tot_penalty(3)],"
            "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,3),penalty(j3,0),start(j1,0),start(j2,8),start(j3,4),tot_penalty(3)]],"
            "[-:33:51-68: info: atom does not occur in any rule head:\n  checking_solution\n"
            ",-:34:83-100: info: atom does not occur in any rule head:\n  checking_solution\n])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "max_value(20).\n"
                "device(d1). instances(d1,1).\n"
                "device(d2). instances(d2,2).\n"
                "offline_instance(d2,1).\n"
                "%\n"
                "job(j1). job_device(j1,d1). job_len(j1,4).\n"
                "job(j2). job_device(j2,d2). job_len(j2,5). deadline(j2,10). importance(j2,1).\n"
                "precedes(j1,j2).\n"
                "job(j3). job_device(j3,d2). job_len(j3,4). deadline(j3,12). importance(j3,2).\n"
                "%\n"
                "max_total_penalty(3).\n"
                "%\n"
                "curr_job_start(j1,0). curr_on_instance(j1,1).\n"
                "curr_job_start(j2,4). curr_on_instance(j2,1).\n"
                "%\n"
                "curr_time(2).\n"
                "\n"
                "% encoding\n"
                "\n"
                "time(0).\n"
                "time(T+1) :- time(T), T < MT, max_value(MT).\n"
                "%time(0..MT) :- max_value(MT).\n"
                "\n"
                "pen_value(T) :- time(T).\n"
                "td_value(T) :- time(T).\n"
                "\n"
                "instance_of(D,1) :- device(D).\n"
                "instance_of(D,I+1) :- device(D), instance_of(D,I), instances(D,N), I < N.\n"
                "\n"
                "% Pick a unique start time and instance for each job\n"
                "1 <= { start(J,S) : time(S) } <= 1 :- job(J), not checking_solution.\n"
                "1 <= { on_instance(J,I) : instance_of(D,I) } <= 1 :- job(J), job_device(J,D), not checking_solution.\n"
                "\n"
                "%----------------------\n"
                "% - overlap\n"
                "%----------------------\n"
                ":- on_instance(J1,I), on_instance(J2,I), J1 != J2,\n"
                "   job_device(J1,D), job_device(J2,D),\n"
                "   start(J1,S1), job_len(J1,L1),\n"
                "   start(J2,S2),\n"
                "   S1 <= S2, S2 < S1 + L1.\n"
                "\n"
                "\n"
                "%----------------------\n"
                "%     - order\n"
                "%----------------------\n"
                ":- precedes(J1,J2),\n"
                "   start(J1,S1), job_len(J1,L1),\n"
                "   start(J2,S2),\n"
                "   S2 < S1 + L1.\n"
                "\n"
                "\n"
                "%-------------------------------------\n"
                "%     - completion -- total-tardiness\n"
                "%-------------------------------------\n"
                "td(J,S + L - D) :-\n"
                "   job(J),\n"
                "   start(J,S), job_len(J,L),\n"
                "   deadline(J,D),\n"
                "   S + L > D.\n"
                "\n"
                "td(J,0) :-\n"
                "   job(J),\n"
                "   start(J,S), job_len(J,L),\n"
                "   deadline(J,D),\n"
                "   S + L <= D.\n"
                "\n"
                "%-------------------------------------\n"
                "%     - completion -- penalty\n"
                "%-------------------------------------\n"
                "\n"
                "penalty(J,TD * I) :-\n"
                "   job(J),\n"
                "   td(J,TD),\n"
                "   importance(J,I).\n"
                "\n"
                ":- penalty(J,P),\n"
                "   max_value(MV),\n"
                "   P > MV.\n"
                "\n"
                "tot_penalty(TP) :-\n"
                "   pen_value(TP),\n"
                "   TP = #sum{ P,J : penalty(J,P) }.\n"
                "\n"
                "%\n"
                "% If the value of the total penalty would be greater than the\n"
                "% maximum allowed value of pen_value(_), the above rule\n"
                "% does not define tot_penalty(_).\n"
                "% In that case, the solution is not acceptable.\n"
                "%\n"
                "has_tot_penalty :-\n"
                "   tot_penalty(TP).\n"
                "-has_tot_penalty :-\n"
                "   not has_tot_penalty.\n"
                ":- -has_tot_penalty.\n"
                "\n"
                ":- pen_value(TP), tot_penalty(TP), max_total_penalty(K),\n"
                "   TP > K.\n"
                "\n"
                "%----------------------\n"
                "%     - instance assignment\n"
                "%----------------------\n"
                "\n"
                ":- on_instance(J1,I), on_instance(J2,I),\n"
                "   job_device(J1,D), job_device(J2,D),\n"
                "   instances(D,N), N > 1,\n"
                "   J1 != J2,\n"
                "   start(J1,S1), start(J2,S2),\n"
                "   job_len(J1,L1),\n"
                "   S1 <= S2, S2 < S1 + L1.\n"
                "\n"
                ":- on_instance(J,I),\n"
                "   device(D),\n"
                "   job(J), job_device(J,D),\n"
                "   offline_instance(D,I),\n"
                "   must_schedule(J).\n"
                "\n"
                "%----------------------\n"
                "% - current schedule\n"
                "%----------------------\n"
                "\n"
                "already_started(J) :-\n"
                "   curr_job_start(J,S),\n"
                "   curr_time(CT),\n"
                "   CT > S.\n"
                "\n"
                "already_finished(J) :-\n"
                "   curr_job_start(J,S),\n"
                "   job_len(J,L),\n"
                "   curr_time(CT),\n"
                "   CT >= S + L.\n"
                "\n"
                "must_schedule(J) :-\n"
                "   job(J),\n"
                "   not must_not_schedule(J).\n"
                "\n"
                "must_not_schedule(J) :-\n"
                "   already_started(J),\n"
                "   not rescheduled(J).\n"
                "\n"
                "rescheduled(J) :-\n"
                "   already_started(J),\n"
                "   not already_finished(J),\n"
                "   job_device(J,D),\n"
                "   curr_on_instance(J,I),\n"
                "   offline_instance(D,I).\n"
                "\n"
                ":- start(J,S),\n"
                "   curr_time(CT),\n"
                "   S < CT,\n"
                "   device(D),\n"
                "   job_device(J,D),\n"
                "   time(S),\n"
                "   must_schedule(J).\n"
                "\n"
                ":- start(J,S),\n"
                "   curr_job_start(J,CS),\n"
                "   S != CS,\n"
                "   job_device(J,D),\n"
                "   must_not_schedule(J).\n"
                "\n"
                ":- on_instance(J,I),\n"
                "   curr_on_instance(J,CI),\n"
                "   I != CI,\n"
                "   must_not_schedule(J).\n"
                , {"start(","on_instance(","penalty(","tot_penalty(","rescheduled("})));
    }

// {{{1 N17 Qualitative Spatial Reasoning

    SECTION("aspcomp2013_17") {
        // Author: Jason Jingshi Li
#ifndef _MSC_VER
        REQUIRE(
            "([[label(0,1,rpi),label(0,2,rd),label(1,2,rd)],"
            "[label(0,1,rpi),label(0,2,rf),label(1,2,rd)],"
            "[label(0,1,rpi),label(0,2,rmi),label(1,2,rd)],"
            "[label(0,1,rpi),label(0,2,roi),label(1,2,rd)],"
            "[label(0,1,rpi),label(0,2,rpi),label(1,2,rd)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "% Csp\n"
                "node1(0..2). node2(0..2).\n"
                "%  0  1 ( DC )\n"
                "lc(0,1,rEQ). lc(0,1,rEC). lc(0,1,rPO).\n"
                "lc(0,1,rTPP). lc(0,1,rNTPP). lc(0,1,rTPPI).\n"
                "lc(0,1,rNTPPI).\n"
                "%  1  2 ( PO )\n"
                "lc(1,2,rEQ). lc(1,2,rDC). lc(1,2,rEC).\n"
                "lc(1,2,rTPP). lc(1,2,rNTPP). lc(1,2,rTPPI).\n"
                "lc(1,2,rNTPPI).\n"
                "\n"
                ":- not label(1,2,rd).\n"
                ":- not label(0,1,rpi).\n"
                "\n"
                "% encoding\n"
                "\n"
                "% A Disjunctive Logic Program for IA Constraint Networks \n"
                "\n"
                "% relations \n"
                "rel(req).\n"
                "rel(rp).\n"
                "rel(rpi).\n"
                "rel(rd).\n"
                "rel(rdi).\n"
                "rel(ro).\n"
                "rel(roi).\n"
                "rel(rm).\n"
                "rel(rmi).\n"
                "rel(rs).\n"
                "rel(rsi).\n"
                "rel(rf).\n"
                "rel(rfi).\n"
                "% Choice rule for clasp\n"
                "1 <= {label(X,Y,L) : rel(L)} <= 1 :- node1(X), node2(Y), X<Y.\n"
                ":- label(X,Y,L), lc(X,Y,L), node1(X), node2(Y), rel(L).\n"
                "\n"
                "% Composition table\n"
                "% req o req = r= \n"
                "label(X,Z,req) :- label(X,Y,req), label(Y,Z,req).\n"
                "% req o rp = r< \n"
                "label(X,Z,rp) :- label(X,Y,req), label(Y,Z,rp).\n"
                "% req o rpi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,req), label(Y,Z,rpi).\n"
                "% req o rd = rd \n"
                "label(X,Z,rd) :- label(X,Y,req), label(Y,Z,rd).\n"
                "% req o rdi = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,req), label(Y,Z,rdi).\n"
                "% req o rs = rs \n"
                "label(X,Z,rs) :- label(X,Y,req), label(Y,Z,rs).\n"
                "% req o rsi = rsi \n"
                "label(X,Z,rsi) :- label(X,Y,req), label(Y,Z,rsi).\n"
                "% req o rf = rf \n"
                "label(X,Z,rf) :- label(X,Y,req), label(Y,Z,rf).\n"
                "% req o rfi = rfi \n"
                "label(X,Z,rfi) :- label(X,Y,req), label(Y,Z,rfi).\n"
                "% req o rm = rm \n"
                "label(X,Z,rm) :- label(X,Y,req), label(Y,Z,rm).\n"
                "% req o rmi = rmi \n"
                "label(X,Z,rmi) :- label(X,Y,req), label(Y,Z,rmi).\n"
                "% req o ro = ro \n"
                "label(X,Z,ro) :- label(X,Y,req), label(Y,Z,ro).\n"
                "% req o roi = roi \n"
                "label(X,Z,roi) :- label(X,Y,req), label(Y,Z,roi).\n"
                "% rp o req = r< \n"
                "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,req).\n"
                "% rp o rp = r< \n"
                "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rp).\n"
                "% rp o rpi = r= < > d di s si f fi m mi o oi \n"
                "label(X,Z,req) | label(X,Z,rp) | label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,rmi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,rp), label(Y,Z,rpi).\n"
                "% rp o rd = r< d s m o \n"
                "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rp), label(Y,Z,rd).\n"
                "% rp o rdi = r< \n"
                "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rdi).\n"
                "% rp o rs = r< \n"
                "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rs).\n"
                "% rp o rsi = r< \n"
                "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rsi).\n"
                "% rp o rf = r< d s m o \n"
                "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rp), label(Y,Z,rf).\n"
                "% rp o rfi = r< \n"
                "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rfi).\n"
                "% rp o rm = r< \n"
                "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rm).\n"
                "% rp o rmi = r< d s m o \n"
                "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rp), label(Y,Z,rmi).\n"
                "% rp o ro = r< \n"
                "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,ro).\n"
                "% rp o roi = r< d s m o \n"
                "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rp), label(Y,Z,roi).\n"
                "% rpi o req = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,req).\n"
                "% rpi o rp = r= < > d di s si f fi m mi o oi \n"
                "label(X,Z,req) | label(X,Z,rp) | label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,rmi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,rp).\n"
                "% rpi o rpi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rpi).\n"
                "% rpi o rd = r> d f mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,rd).\n"
                "% rpi o rdi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rdi).\n"
                "% rpi o rs = r> d f mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,rs).\n"
                "% rpi o rsi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rsi).\n"
                "% rpi o rf = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rf).\n"
                "% rpi o rfi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rfi).\n"
                "% rpi o rm = r> d f mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,rm).\n"
                "% rpi o rmi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rmi).\n"
                "% rpi o ro = r> d f mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,ro).\n"
                "% rpi o roi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,roi).\n"
                "% rd o req = rd \n"
                "label(X,Z,rd) :- label(X,Y,rd), label(Y,Z,req).\n"
                "% rd o rp = r< \n"
                "label(X,Z,rp) :- label(X,Y,rd), label(Y,Z,rp).\n"
                "% rd o rpi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rd), label(Y,Z,rpi).\n"
                "% rd o rd = rd \n"
                "label(X,Z,rd) :- label(X,Y,rd), label(Y,Z,rd).\n"
                "% rd o rdi = r= < > d di s si f fi m mi o oi \n"
                "label(X,Z,req) | label(X,Z,rp) | label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,rmi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,rd), label(Y,Z,rdi).\n"
                "% rd o rs = rd \n"
                "label(X,Z,rd) :- label(X,Y,rd), label(Y,Z,rs).\n"
                "% rd o rsi = r> d f mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rd), label(Y,Z,rsi).\n"
                "% rd o rf = rd \n"
                "label(X,Z,rd) :- label(X,Y,rd), label(Y,Z,rf).\n"
                "% rd o rfi = r< d s m o \n"
                "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rd), label(Y,Z,rfi).\n"
                "% rd o rm = r< \n"
                "label(X,Z,rp) :- label(X,Y,rd), label(Y,Z,rm).\n"
                "% rd o rmi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rd), label(Y,Z,rmi).\n"
                "% rd o ro = r< d s m o \n"
                "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rd), label(Y,Z,ro).\n"
                "% rd o roi = r> d f mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rd), label(Y,Z,roi).\n"
                "% rdi o req = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,rdi), label(Y,Z,req).\n"
                "% rdi o rp = r< di fi m o \n"
                "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rdi), label(Y,Z,rp).\n"
                "% rdi o rpi = r> di si mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,rpi).\n"
                "% rdi o rd = r= d di s si f fi o oi \n"
                "label(X,Z,req) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,rd).\n"
                "% rdi o rdi = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,rdi), label(Y,Z,rdi).\n"
                "% rdi o rs = rdi fi o \n"
                "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rdi), label(Y,Z,rs).\n"
                "% rdi o rsi = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,rdi), label(Y,Z,rsi).\n"
                "% rdi o rf = rdi si oi \n"
                "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,rf).\n"
                "% rdi o rfi = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,rdi), label(Y,Z,rfi).\n"
                "% rdi o rm = rdi fi o \n"
                "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rdi), label(Y,Z,rm).\n"
                "% rdi o rmi = rdi si oi \n"
                "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,rmi).\n"
                "% rdi o ro = rdi fi o \n"
                "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rdi), label(Y,Z,ro).\n"
                "% rdi o roi = rdi si oi \n"
                "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,roi).\n"
                "% rs o req = rs \n"
                "label(X,Z,rs) :- label(X,Y,rs), label(Y,Z,req).\n"
                "% rs o rp = r< \n"
                "label(X,Z,rp) :- label(X,Y,rs), label(Y,Z,rp).\n"
                "% rs o rpi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rs), label(Y,Z,rpi).\n"
                "% rs o rd = rd \n"
                "label(X,Z,rd) :- label(X,Y,rs), label(Y,Z,rd).\n"
                "% rs o rdi = r< di fi m o \n"
                "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rs), label(Y,Z,rdi).\n"
                "% rs o rs = rs \n"
                "label(X,Z,rs) :- label(X,Y,rs), label(Y,Z,rs).\n"
                "% rs o rsi = r= s si \n"
                "label(X,Z,req) | label(X,Z,rs) | label(X,Z,rsi) :- label(X,Y,rs), label(Y,Z,rsi).\n"
                "% rs o rf = rd \n"
                "label(X,Z,rd) :- label(X,Y,rs), label(Y,Z,rf).\n"
                "% rs o rfi = r< m o \n"
                "label(X,Z,rp) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rs), label(Y,Z,rfi).\n"
                "% rs o rm = r< \n"
                "label(X,Z,rp) :- label(X,Y,rs), label(Y,Z,rm).\n"
                "% rs o rmi = rmi \n"
                "label(X,Z,rmi) :- label(X,Y,rs), label(Y,Z,rmi).\n"
                "% rs o ro = r< m o \n"
                "label(X,Z,rp) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rs), label(Y,Z,ro).\n"
                "% rs o roi = rd f oi \n"
                "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rs), label(Y,Z,roi).\n"
                "% rsi o req = rsi \n"
                "label(X,Z,rsi) :- label(X,Y,rsi), label(Y,Z,req).\n"
                "% rsi o rp = r< di fi m o \n"
                "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rsi), label(Y,Z,rp).\n"
                "% rsi o rpi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rsi), label(Y,Z,rpi).\n"
                "% rsi o rd = rd f oi \n"
                "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rsi), label(Y,Z,rd).\n"
                "% rsi o rdi = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,rsi), label(Y,Z,rdi).\n"
                "% rsi o rs = r= s si \n"
                "label(X,Z,req) | label(X,Z,rs) | label(X,Z,rsi) :- label(X,Y,rsi), label(Y,Z,rs).\n"
                "% rsi o rsi = rsi \n"
                "label(X,Z,rsi) :- label(X,Y,rsi), label(Y,Z,rsi).\n"
                "% rsi o rf = roi \n"
                "label(X,Z,roi) :- label(X,Y,rsi), label(Y,Z,rf).\n"
                "% rsi o rfi = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,rsi), label(Y,Z,rfi).\n"
                "% rsi o rm = rdi fi o \n"
                "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rsi), label(Y,Z,rm).\n"
                "% rsi o rmi = rmi \n"
                "label(X,Z,rmi) :- label(X,Y,rsi), label(Y,Z,rmi).\n"
                "% rsi o ro = rdi fi o \n"
                "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rsi), label(Y,Z,ro).\n"
                "% rsi o roi = roi \n"
                "label(X,Z,roi) :- label(X,Y,rsi), label(Y,Z,roi).\n"
                "% rf o req = rf \n"
                "label(X,Z,rf) :- label(X,Y,rf), label(Y,Z,req).\n"
                "% rf o rp = r< \n"
                "label(X,Z,rp) :- label(X,Y,rf), label(Y,Z,rp).\n"
                "% rf o rpi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rf), label(Y,Z,rpi).\n"
                "% rf o rd = rd \n"
                "label(X,Z,rd) :- label(X,Y,rf), label(Y,Z,rd).\n"
                "% rf o rdi = r> di si mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rf), label(Y,Z,rdi).\n"
                "% rf o rs = rd \n"
                "label(X,Z,rd) :- label(X,Y,rf), label(Y,Z,rs).\n"
                "% rf o rsi = r> mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rf), label(Y,Z,rsi).\n"
                "% rf o rf = rf \n"
                "label(X,Z,rf) :- label(X,Y,rf), label(Y,Z,rf).\n"
                "% rf o rfi = r= f fi \n"
                "label(X,Z,req) | label(X,Z,rf) | label(X,Z,rfi) :- label(X,Y,rf), label(Y,Z,rfi).\n"
                "% rf o rm = rm \n"
                "label(X,Z,rm) :- label(X,Y,rf), label(Y,Z,rm).\n"
                "% rf o rmi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rf), label(Y,Z,rmi).\n"
                "% rf o ro = rd s o \n"
                "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rf), label(Y,Z,ro).\n"
                "% rf o roi = r> mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rf), label(Y,Z,roi).\n"
                "% rfi o req = rfi \n"
                "label(X,Z,rfi) :- label(X,Y,rfi), label(Y,Z,req).\n"
                "% rfi o rp = r< \n"
                "label(X,Z,rp) :- label(X,Y,rfi), label(Y,Z,rp).\n"
                "% rfi o rpi = r> di si mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rfi), label(Y,Z,rpi).\n"
                "% rfi o rd = rd s o \n"
                "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rfi), label(Y,Z,rd).\n"
                "% rfi o rdi = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,rfi), label(Y,Z,rdi).\n"
                "% rfi o rs = ro \n"
                "label(X,Z,ro) :- label(X,Y,rfi), label(Y,Z,rs).\n"
                "% rfi o rsi = rdi \n"
                "label(X,Z,rdi) :- label(X,Y,rfi), label(Y,Z,rsi).\n"
                "% rfi o rf = r= f fi \n"
                "label(X,Z,req) | label(X,Z,rf) | label(X,Z,rfi) :- label(X,Y,rfi), label(Y,Z,rf).\n"
                "% rfi o rfi = rfi \n"
                "label(X,Z,rfi) :- label(X,Y,rfi), label(Y,Z,rfi).\n"
                "% rfi o rm = rm \n"
                "label(X,Z,rm) :- label(X,Y,rfi), label(Y,Z,rm).\n"
                "% rfi o rmi = rdi si oi \n"
                "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rfi), label(Y,Z,rmi).\n"
                "% rfi o ro = ro \n"
                "label(X,Z,ro) :- label(X,Y,rfi), label(Y,Z,ro).\n"
                "% rfi o roi = rdi si oi \n"
                "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rfi), label(Y,Z,roi).\n"
                "% rm o req = rm \n"
                "label(X,Z,rm) :- label(X,Y,rm), label(Y,Z,req).\n"
                "% rm o rp = r< \n"
                "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,rp).\n"
                "% rm o rpi = r> di si mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rm), label(Y,Z,rpi).\n"
                "% rm o rd = rd s o \n"
                "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rm), label(Y,Z,rd).\n"
                "% rm o rdi = r< \n"
                "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,rdi).\n"
                "% rm o rs = rm \n"
                "label(X,Z,rm) :- label(X,Y,rm), label(Y,Z,rs).\n"
                "% rm o rsi = rm \n"
                "label(X,Z,rm) :- label(X,Y,rm), label(Y,Z,rsi).\n"
                "% rm o rf = rd s o \n"
                "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rm), label(Y,Z,rf).\n"
                "% rm o rfi = r< \n"
                "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,rfi).\n"
                "% rm o rm = r< \n"
                "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,rm).\n"
                "% rm o rmi = r= f fi \n"
                "label(X,Z,req) | label(X,Z,rf) | label(X,Z,rfi) :- label(X,Y,rm), label(Y,Z,rmi).\n"
                "% rm o ro = r< \n"
                "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,ro).\n"
                "% rm o roi = rd s o \n"
                "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rm), label(Y,Z,roi).\n"
                "% rmi o req = rmi \n"
                "label(X,Z,rmi) :- label(X,Y,rmi), label(Y,Z,req).\n"
                "% rmi o rp = r< di fi m o \n"
                "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rmi), label(Y,Z,rp).\n"
                "% rmi o rpi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,rpi).\n"
                "% rmi o rd = rd f oi \n"
                "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rmi), label(Y,Z,rd).\n"
                "% rmi o rdi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,rdi).\n"
                "% rmi o rs = rd f oi \n"
                "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rmi), label(Y,Z,rs).\n"
                "% rmi o rsi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,rsi).\n"
                "% rmi o rf = rmi \n"
                "label(X,Z,rmi) :- label(X,Y,rmi), label(Y,Z,rf).\n"
                "% rmi o rfi = rmi \n"
                "label(X,Z,rmi) :- label(X,Y,rmi), label(Y,Z,rfi).\n"
                "% rmi o rm = r= s si \n"
                "label(X,Z,req) | label(X,Z,rs) | label(X,Z,rsi) :- label(X,Y,rmi), label(Y,Z,rm).\n"
                "% rmi o rmi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,rmi).\n"
                "% rmi o ro = rd f oi \n"
                "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rmi), label(Y,Z,ro).\n"
                "% rmi o roi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,roi).\n"
                "% ro o req = ro \n"
                "label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,req).\n"
                "% ro o rp = r< \n"
                "label(X,Z,rp) :- label(X,Y,ro), label(Y,Z,rp).\n"
                "% ro o rpi = r> di si mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,ro), label(Y,Z,rpi).\n"
                "% ro o rd = rd s o \n"
                "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rd).\n"
                "% ro o rdi = r< di fi m o \n"
                "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rdi).\n"
                "% ro o rs = ro \n"
                "label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rs).\n"
                "% ro o rsi = rdi fi o \n"
                "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rsi).\n"
                "% ro o rf = rd s o \n"
                "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rf).\n"
                "% ro o rfi = r< m o \n"
                "label(X,Z,rp) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rfi).\n"
                "% ro o rm = r< \n"
                "label(X,Z,rp) :- label(X,Y,ro), label(Y,Z,rm).\n"
                "% ro o rmi = rdi si oi \n"
                "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,ro), label(Y,Z,rmi).\n"
                "% ro o ro = r< m o \n"
                "label(X,Z,rp) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,ro).\n"
                "% ro o roi = r= d di s si f fi o oi \n"
                "label(X,Z,req) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,ro), label(Y,Z,roi).\n"
                "% roi o req = roi \n"
                "label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,req).\n"
                "% roi o rp = r< di fi m o \n"
                "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,roi), label(Y,Z,rp).\n"
                "% roi o rpi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,roi), label(Y,Z,rpi).\n"
                "% roi o rd = rd f oi \n"
                "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rd).\n"
                "% roi o rdi = r> di si mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rdi).\n"
                "% roi o rs = rd f oi \n"
                "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rs).\n"
                "% roi o rsi = r> mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rsi).\n"
                "% roi o rf = roi \n"
                "label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rf).\n"
                "% roi o rfi = rdi si oi \n"
                "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rfi).\n"
                "% roi o rm = rdi fi o \n"
                "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,roi), label(Y,Z,rm).\n"
                "% roi o rmi = r> \n"
                "label(X,Z,rpi) :- label(X,Y,roi), label(Y,Z,rmi).\n"
                "% roi o ro = r= d di s si f fi o oi \n"
                "label(X,Z,req) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,ro).\n"
                "% roi o roi = r> mi oi \n"
                "label(X,Z,rpi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,roi).\n"
                , {"label("})));
#endif
    }

// N18 too big
// {{{1 N19 Abstract Dialectical Frameworks Well-founded Model

    SECTION("aspcomp2013_19") {
        // Author: Stefan Ellmauthaler, Johannes Wallner
        REQUIRE(
            "([[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)],"
            "[accept(1),accept(2),reject(4)]],"
            "[-:74:15-16: info: global variable in tuple of aggregate element:\n  I\n"
            ",-:82:21-22: info: global variable in tuple of aggregate element:\n  I\n])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "statement(1). statement(2). statement(3). statement(4). \n"
                "ac(1,c(v)). ac(2,1). ac(3,or(neg(3),4)). ac(4,c(f)). \n"
                "\n"
                "% encoding\n"
                "\n"
                "% splitting a formula into its subformulas\n"
                "subformula2(X,F) :- ac(X,F),statement(X).\n"
                "subformula2(X,F) :- subformula2(X,and(F,_)).\n"
                "subformula2(X,F) :- subformula2(X,and(_,F)).\n"
                "subformula2(X,F) :- subformula2(X,or(_,F)).\n"
                "subformula2(X,F) :- subformula2(X,or(F,_)).\n"
                "subformula2(X,F) :- subformula2(X,neg(F)).\n"
                "subformula2(X,F) :- subformula2(X,xor(F,_)).\n"
                "subformula2(X,F) :- subformula2(X,xor(_,F)).\n"
                "subformula2(X,F) :- subformula2(X,imp(F,_)).\n"
                "subformula2(X,F) :- subformula2(X,imp(_,F)).\n"
                "subformula2(X,F) :- subformula2(X,iff(F,_)).\n"
                "subformula2(X,F) :- subformula2(X,iff(_,F)).\n"
                "subformula(F) :- subformula2(_,F).\n"
                "\n"
                "% decide whether a subformula is an atom or not\n"
                "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=and(F1,F2).\n"
                "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=or(F1,F2).\n"
                "noatom(F) :- subformula(F), subformula(F1), F=neg(F1).\n"
                "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=xor(F1,F2).\n"
                "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=imp(F1,F2).\n"
                "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=iff(F1,F2).\n"
                "\n"
                "atom(X) :- subformula(X), not noatom(X).\n"
                "atom(X) :- subformula(X), X=c(v).\n"
                "atom(X) :- subformula(X), X=c(f).\n"
                "\n"
                "% check whether an interpretation is a model or not at a specific iteration\n"
                "ismodel(X,I) :- atom(X), in(X,I).\n"
                "ismodel(X,I) :- atom(X), X=c(v), iteration(I).\n"
                "ismodel(F,I) :- subformula(F), subformula(F1), F=neg(F1), nomodel(F1,I).\n"
                "ismodel(F,I) :- subformula(F), F=and(F1,F2), ismodel(F1,I), ismodel(F2,I).\n"
                "ismodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=or(F1,F2), ismodel(F1,I).\n"
                "ismodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=or(F1,F2), ismodel(F2,I).\n"
                "ismodel(F,I) :- subformula(F), F=xor(F1,F2), ismodel(F1,I), nomodel(F2,I).\n"
                "ismodel(F,I) :- subformula(F), F=xor(F1,F2), ismodel(F2,I), nomodel(F1,I).\n"
                "ismodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=imp(F1,F2), nomodel(F1,I).\n"
                "ismodel(F,I) :- subformula(F), F=imp(F1,F2), ismodel(F1,I), ismodel(F2,I).\n"
                "ismodel(F,I) :- subformula(F), F=iff(F1,F2), ismodel(F1,I), ismodel(F2,I).\n"
                "ismodel(F,I) :- subformula(F), F=iff(F1,F2), nomodel(F1,I), nomodel(F2,I).\n"
                "\n"
                "nomodel(X,I) :- atom(X), out(X,I).\n"
                "nomodel(X,I) :- atom(X), X=c(f), iteration(I).\n"
                "nomodel(F,I) :- subformula(F), subformula(F1), F=neg(F1), ismodel(F1,I).\n"
                "nomodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=and(F1,F2), nomodel(F1,I).\n"
                "nomodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=and(F1,F2), nomodel(F2,I).\n"
                "nomodel(F,I) :- subformula(F), F=or(F1,F2), nomodel(F1,I), nomodel(F2,I).\n"
                "nomodel(F,I) :- subformula(F), F=xor(F1,F2), ismodel(F1,I), ismodel(F2,I).\n"
                "nomodel(F,I) :- subformula(F), F=xor(F1,F2), nomodel(F1,I), nomodel(F2,I).\n"
                "nomodel(F,I) :- subformula(F), F=imp(F1,F2), ismodel(F1,I), nomodel(F2,I).\n"
                "nomodel(F,I) :- subformula(F), F=iff(F1,F2), nomodel(F1,I), ismodel(F2,I).\n"
                "nomodel(F,I) :- subformula(F), F=iff(F1,F2), nomodel(F2,I), ismodel(F1,I).\n"
                "\n"
                "% get the number of statements and create an ordering\n"
                "snum(I) :- I = #count{Y : statement(Y)}.\n"
                "iteration(I) :- snum(J), I=J-1.\n"
                "iteration(I) :- iteration(J), I=J-1, I>=0.\n"
                "\n"
                "% create undecided set of variables at the starting point of the function\n"
                "undec(X,I) :- snum(I), statement(X).\n"
                "\n"
                "% iterate the function one step further, and guess an additional element for A or R\n"
                "inA(X,I) :- inA(X,J), J=I+1, iteration(I).\n"
                "inR(X,I) :- inR(X,J), J=I+1, iteration(I).\n"
                "select(X,I) :- not deselect(X,I), statement(X), iteration(I), undec(X,J), J=I+1.\n"
                "deselect(X,I) :- not select(X,I), statement(X), iteration(I), undec(X,J), J=I+1.\n"
                ":- A=#count { I,X : select(X,I)}, iteration(I), A>1.\n"
                "undec(X,I) :- iteration(I), undec(X,J), J=I+1, deselect(X,I).\n"
                "% check whether the selected element is in A or not.\n"
                "in(X,I) | out(X,I) :- undec(X,J), J=I+1, iteration(I).\n"
                "in(X,I) :- iteration(I), J=I+1, inA(X,J).\n"
                "out(X,I) :- iteration(I), J=I+1, inR(X,J).\n"
                "\n"
                "okA(I) :- select(X,I), ac(X,F), ismodel(F,I).\n"
                "okA(I) :- A= #count{I,X : select(X,I)}, iteration(I), A=0.\n"
                "inA(X,I) :- okA(I), select(X,I).\n"
                "\n"
                "in(X,I) :- okA(I), undec(X,J), J=I+1, iteration(I).\n"
                "out(X,I) :- okA(I), undec(X,J), J=I+1, iteration(I).\n"
                "\n"
                "\n"
                "% check whether the selected element is in R or not.\n"
                "okR(I) :- select(X,I), ac(X,F), nomodel(F,I), not okA(I).\n"
                "in(X,I) :- okR(I), undec(X,J), J=I+1, iteration(I).\n"
                "out(X,I) :- okR(I), undec(X,J), J=I+1, iteration(I).\n"
                "inR(X,I) :- okR(I), select(X,I).\n"
                "\n"
                "ok(I) :- okA(I).\n"
                "ok(I) :- okR(I).\n"
                "\n"
                ":- not ok(I), iteration(I).\n"
                "\n"
                "accept(X) :- inA(X,0).\n"
                "reject(X) :- inR(X,0).\n"
                "\n"
                ":~ statement(X), not accept(X). [1@2,X]\n"
                ":~ statement(X), not reject(X). [1@1,X]\n"
                "%#maximize [accept(X)@2].\n"
                "%#maximize [reject(X)@1].\n"
                , {"accept(", "reject("}, {2, 3})));
    }

// {{{1 N20 Visit-all

    SECTION("aspcomp2013_20") {
        // Author: Giovambattista Ianni,Nir Lipovetzky*, Carlos Linares López*
        REQUIRE(
            "([[move(x1y1,x2y1,3),move(x2y1,x1y1,2),move(x2y1,x3y1,4),move(x2y2,x2y1,1),move(x2y2,x2y3,7),move(x2y3,x1y3,8),move(x3y1,x3y2,5),move(x3y2,x2y2,6)],"
            "[move(x1y1,x2y1,3),move(x2y1,x1y1,2),move(x2y1,x3y1,4),move(x2y2,x2y1,1),move(x2y3,x1y3,8),move(x3y1,x3y2,5),move(x3y2,x3y3,6),move(x3y3,x2y3,7)],"
            "[move(x1y1,x2y1,5),move(x2y1,x1y1,4),move(x2y1,x2y2,6),move(x2y2,x2y3,7),move(x2y2,x3y2,1),move(x2y3,x1y3,8),move(x3y1,x2y1,3),move(x3y2,x3y1,2)],"
            "[move(x1y3,x2y3,3),move(x2y1,x1y1,8),move(x2y2,x2y3,1),move(x2y2,x3y2,5),move(x2y3,x1y3,2),move(x2y3,x2y2,4),move(x3y1,x2y1,7),move(x3y2,x3y1,6)],"
            "[move(x1y3,x2y3,3),move(x2y1,x1y1,8),move(x2y2,x2y3,1),move(x2y3,x1y3,2),move(x2y3,x3y3,4),move(x3y1,x2y1,7),move(x3y2,x3y1,6),move(x3y3,x3y2,5)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "connected(x1y1,x2y1). connected(x2y1,x1y1). \n"
                "connected(x2y1,x3y1). connected(x3y1,x2y1).\n"
                "\n"
                "connected(x2y2,x3y2). connected(x3y2,x2y2).\n"
                "\n"
                "connected(x1y3,x2y3). connected(x2y3,x1y3). \n"
                "connected(x2y3,x3y3). connected(x3y3,x2y3).\n"
                "\n"
                "connected(x2y1,x2y2). connected(x2y2,x2y1).\n"
                "connected(x2y2,x2y3). connected(x2y3,x2y2).\n"
                "\n"
                "connected(x3y1,x3y2). connected(x3y2,x3y1).\n"
                "connected(x3y2,x3y3). connected(x3y3,x3y2).\n"
                "\n"
                "at(x2y2).\n"
                "\n"
                "visit(x1y1). visit(x2y1). visit(x3y1).\n"
                "visit(x2y2). visit(x3y2).\n"
                "visit(x1y3). visit(x2y3).\n"
                "\n"
                "step(1). step(2). step(3).\n"
                "step(4). step(5). step(6).\n"
                "step(7). step(8).\n"
                "\n"
                "% encoding\n"
                "\n"
                "%\n"
                "% initial status\n"
                "%\n"
                "visited(X) :- at(X).\n"
                "atrobot(X,0) :- at(X).\n"
                "\n"
                "% GENERATE  >>>>>\n"
                "1 <= { move( Curpos,Nextpos,T ) : connected( Curpos,Nextpos ) , Curpos != Nextpos } <= 1 :- step(T).\n"
                "% <<<<<  GENERATE\n"
                "% \n"
                "\n"
                "% \n"
                "% \n"
                "% EFFECTS APPLY  >>>>>\n"
                "\n"
                "% move/3, effects\n"
                "atrobot( Nextpos,T ) :- move( Curpos,Nextpos,T ).\n"
                "del( atrobot( Curpos ),T ) :- move( Curpos,Nextpos,T ).\n"
                "visited( Nextpos ) :- move( Curpos,Nextpos,T ).\n"
                "% <<<<<  EFFECTS APPLY\n"
                "% \n"
                "\n"
                "% \n"
                "% \n"
                "% INERTIA  >>>>>\n"
                "atrobot( X,T ) :- step(T), atrobot( X,T-1 ), not del( atrobot( X ) ,T  ).\n"
                "%\n"
                "% GB: it is not needed to let 'visited' subject to timestamping \n"
                "%\n"
                "% <<<<<  INERTIA\n"
                "% \n"
                "\n"
                "% \n"
                "% \n"
                "% PRECONDITIONS HOLD  >>>>>\n"
                "\n"
                "% move/3, preconditions\n"
                " :- move( Curpos,Nextpos,T ), not atrobot(Curpos, T-1), step(T).\n"
                "% <<<<<  PRECONDITIONS HOLD\n"
                "% \n"
                "\n"
                "goalreached :- N = #count{ X : visited(X) , visit(X) }, N = #count{ X : visit(X) }.\n"
                ":- not goalreached.\n"
                "\n"
                , {"move("})));
    }

// {{{1 N21 Complex Optimization of Answer Sets

    SECTION("aspcomp2013_21") {
        // Author: Martin Gebser, Roland Kaminski, Torsten Schaub
        REQUIRE(
            "([[hold(atom(a)),hold(atom(c)),hold(atom(s)),hold(atom(t)),hold(conjunction(2)),hold(conjunction(4)),hold(conjunction(6)),hold(conjunction(7)),hold(conjunction(8))],"
            "[hold(atom(a)),hold(atom(d)),hold(atom(p)),hold(atom(r)),hold(conjunction(0)),hold(conjunction(1)),hold(conjunction(3)),hold(conjunction(4))]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "wlist(0,0,pos(atom(q)),1). wlist(0,1,pos(atom(r)),1). \n"
                "set(0,neg(atom(c))). rule(pos(sum(0,0,2)),pos(conjunction(0))).\n"
                "set(1,pos(atom(r))). rule(pos(atom(a)),pos(conjunction(1))).\n"
                "set(2,neg(atom(d))). rule(pos(sum(0,0,2)),pos(conjunction(2))).\n"
                "set(3,neg(atom(t))). rule(pos(atom(d)),pos(conjunction(3))).\n"
                "wlist(1,0,pos(atom(p)),1). wlist(1,1,pos(atom(t)),1).\n"
                "set(4,pos(atom(a))). set(4,neg(atom(b))).\n"
                "rule(pos(sum(0,1,2)),pos(conjunction(4))). set(5,pos(atom(t))).\n"
                "set(5,neg(atom(r))). set(5,neg(atom(s))).\n"
                "rule(pos(atom(b)),pos(conjunction(5))). set(6,neg(atom(r))).\n"
                "set(6,neg(atom(q))). rule(pos(atom(s)),pos(conjunction(6))).\n"
                "set(7,pos(atom(s))). rule(pos(atom(a)),pos(conjunction(7))).\n"
                "rule(pos(atom(a)),pos(conjunction(3))). set(8,neg(atom(p))).\n"
                "rule(pos(atom(c)),pos(conjunction(8))). set(9,pos(atom(a))).\n"
                "set(9,neg(atom(t))). set(9,neg(atom(b))).\n"
                "set(9,neg(atom(p))). rule(pos(false),pos(conjunction(9))).\n"
                "set(10,pos(atom(q))). set(10,pos(atom(r))).\n"
                "set(10,neg(atom(c))). rule(pos(false),pos(conjunction(10))).\n"
                "set(11,pos(atom(q))). set(11,pos(atom(r))). set(11,neg(atom(d))).\n"
                "rule(pos(false),pos(conjunction(11))). set(12,pos(atom(r))).\n"
                "set(12,pos(atom(t))). set(12,neg(atom(b))). set(12,neg(atom(q))).\n"
                "rule(pos(false),pos(conjunction(12))).\n"
                "wlist(2,0,pos(atom(q)),1). wlist(2,1,pos(atom(r)),1).\n"
                "wlist(2,2,pos(atom(p)),1). wlist(2,3,pos(atom(s)),1).\n"
                "\n"
                "minimize(1,2). optimize(1,1,incl).\n"
                "\n"
                ":- not hold(atom(r)), not hold(atom(t)).\n"
                "\n"
                "% encoding\n"
                "\n"
                "eleb(P) :- rule(_,pos(P)).\n"
                "\n"
                "nhold(conjunction(S)) :- eleb(conjunction(S)), not hold(P), set(S,pos(P)).\n"
                "nhold(conjunction(S)) :- eleb(conjunction(S)),     hold(P), set(S,neg(P)).\n"
                " hold(conjunction(S)) :- eleb(conjunction(S)), not nhold(conjunction(S)).\n"
                "\n"
                "hold(atom(A))                     :- rule(pos(atom(A)),   pos(B)), hold(B).\n"
                "                                  :- rule(pos(false),     pos(B)), hold(B).\n"
                "{ hold(P) : wlist(S,_,pos(P),_) } :- rule(pos(sum(_,S,_)),pos(B)), hold(B).\n"
                "\n"
                "elem(E) :- eleb(E).\n"
                "elem(E) :- rule(pos(E),_).\n"
                "elem(P) :- rule(pos(sum(_,S,_)),_), wlist(S,_,pos(P),_).\n"
                "elem(P) :- minimize(J,S),           wlist(S,_,pos(P),W).\n"
                "\n"
                "supp(atom(A),B) :- rule(pos(atom(A)),   pos(B)).\n"
                "supp(atom(A),B) :- rule(pos(sum(_,S,_)),pos(B)), wlist(S,_,pos(atom(A)),_).\n"
                "\n"
                "supp(atom(A))   :- supp(atom(A),B).\n"
                "\n"
                "set(S) :- set(S,E).\n"
                "fact(atom(A))   :- rule(pos(atom(A)),pos(conjunction(S))), not set(S).\n"
                "\n"
                "true(atom(A))                 :- fact(atom(A)).\n"
                "true(atom(A)) | fail(atom(A)) :- supp(atom(A)), not fact(atom(A)).\n"
                "                fail(atom(A)) :- elem(atom(A)), not supp(atom(A)).\n"
                "\n"
                "fail(false).\n"
                "\n"
                "sett(S,0,P)    :- set(S,P).\n"
                "sett(S,N+1,P2) :- sett(S,N,P1), sett(S,N,P2), P1 < P2.\n"
                "\n"
                "setn(S,N,P) :- sett(S,N,P), not sett(S,N+1,P).\n"
                "setn(S,N)  :- setn(S,N,_).\n"
                "\n"
                "true(conjunction(S),N+1) :- elem(conjunction(S)), setn(S,N), not setn(S,N+1).\n"
                "true(conjunction(S),N)   :- elem(conjunction(S)), true(P), setn(S,N,pos(P)), true(conjunction(S),N+1).\n"
                "true(conjunction(S),N)   :- elem(conjunction(S)), fail(P), setn(S,N,neg(P)), true(conjunction(S),N+1).\n"
                "\n"
                "true(conjunction(S)) :- true(conjunction(S),0).\n"
                "fail(conjunction(S)) :- elem(conjunction(S)), set(S,pos(P)), fail(P).\n"
                "fail(conjunction(S)) :- elem(conjunction(S)), set(S,neg(N)), true(N).\n"
                "\n"
                "suppt(S,0,P)    :- supp(S,P).\n"
                "suppt(S,N+1,P2) :- suppt(S,N,P1), suppt(S,N,P2), P1 < P2.\n"
                "\n"
                "suppn(S,N,P) :- suppt(S,N,P), not suppt(S,N+1,P).\n"
                "suppn(S,N)  :- suppn(S,N,_).\n"
                "\n"
                "suppf(S,N+1) :- suppn(S,N), not suppn(S,N+1).\n"
                "suppf(S,N)   :- fail(P), suppn(S,N,P), suppf(S,N+1).\n"
                "\n"
                "bot :- true(atom(A)), suppf(atom(A),0).\n"
                "bot :- rule(pos(H),pos(B)), true(B), fail(H).\n"
                "\n"
                "true(atom(A)) :- supp(atom(A)), not fact(atom(A)), bot.\n"
                "fail(atom(A)) :- supp(atom(A)), not fact(atom(A)), bot.\n"
                "\n"
                "target(P,N) :- minimize(_,S), wlist(S,N,pos(P),_).\n"
                "target(N) :- target(P,N).\n"
                "\n"
                "equal(N+1) :- target(N), not target(N+1).\n"
                "equal(N) :- target(P,N), true(P),     hold(P), equal(N+1).\n"
                "equal(N) :- target(P,N), fail(P), not hold(P), equal(N+1).\n"
                "\n"
                "bot :- equal(0).\n"
                "bot :- target(P,_), true(P), not hold(P).\n"
                "\n"
                ":- not bot.\n"
                "\n"
                , {"hold("})));
    }

// {{{1 N22 Knight Tour with Holes

    SECTION("aspcomp2013_22") {
        // Author: Francesco Calimeri, Neng-Fa Zhou*
        REQUIRE(
            "([[move(1,1,2,3),move(1,2,3,1),move(1,3,2,1),move(1,4,2,2),move(1,5,2,7),move(1,6,2,8),move(1,7,3,8),move(1,8,3,7),move(2,1,1,3),move(2,2,4,1),move(2,3,3,1),move(2,4,1,6),move(2,5,1,7),move(2,6,3,8),move(2,7,4,8),move(2,8,1,6),move(3,1,2,3),move(3,2,5,1),move(3,3,2,1),move(3,4,1,3),move(3,5,1,6),move(3,6,1,7),move(3,7,5,8),move(3,8,1,7),move(4,1,2,2),move(4,2,2,1),move(4,3,2,2),move(4,4,2,3),move(4,5,3,7),move(4,6,2,7),move(4,7,2,8),move(4,8,2,7),move(5,1,7,2),move(5,2,3,1),move(5,3,7,2),move(5,4,7,3),move(5,5,6,7),move(5,6,4,8),move(5,7,7,8),move(5,8,3,7),move(6,1,8,2),move(6,2,4,1),move(6,3,8,2),move(6,4,8,3),move(6,5,8,6),move(6,6,8,7),move(6,7,4,8),move(6,8,8,7),move(7,1,8,3),move(7,2,5,1),move(7,3,6,1),move(7,4,8,2),move(7,5,8,7),move(7,6,6,8),move(7,7,5,8),move(7,8,8,6),move(8,1,6,2),move(8,2,6,1),move(8,3,6,2),move(8,4,7,2),move(8,5,7,3),move(8,6,7,8),move(8,7,6,8),move(8,8,6,7)],"
            "[move(1,1,2,3),move(1,2,3,1),move(1,3,2,1),move(1,4,2,2),move(1,5,2,7),move(1,6,2,8),move(1,7,3,8),move(1,8,3,7),move(2,1,1,3),move(2,2,4,1),move(2,3,3,1),move(2,4,1,6),move(2,5,1,7),move(2,6,3,8),move(2,7,4,8),move(2,8,1,6),move(3,1,2,3),move(3,2,5,1),move(3,3,2,1),move(3,4,1,3),move(3,5,1,6),move(3,6,1,7),move(3,7,5,8),move(3,8,1,7),move(4,1,2,2),move(4,2,2,1),move(4,3,2,2),move(4,4,2,3),move(4,5,3,7),move(4,6,2,7),move(4,7,2,8),move(4,8,6,7),move(5,1,7,2),move(5,2,3,1),move(5,3,7,2),move(5,4,7,3),move(5,5,6,7),move(5,6,4,8),move(5,7,7,8),move(5,8,3,7),move(6,1,8,2),move(6,2,4,1),move(6,3,8,2),move(6,4,8,3),move(6,5,8,6),move(6,6,8,7),move(6,7,4,8),move(6,8,8,7),move(7,1,8,3),move(7,2,5,1),move(7,3,6,1),move(7,4,8,2),move(7,5,8,7),move(7,6,6,8),move(7,7,5,8),move(7,8,8,6),move(8,1,6,2),move(8,2,6,1),move(8,3,6,2),move(8,4,7,2),move(8,5,7,3),move(8,6,7,8),move(8,7,6,8),move(8,8,6,7)],"
            "[move(1,1,2,3),move(1,2,3,1),move(1,3,2,1),move(1,4,2,2),move(1,5,2,7),move(1,6,2,8),move(1,7,3,8),move(1,8,3,7),move(2,1,1,3),move(2,2,4,1),move(2,3,3,1),move(2,4,3,6),move(2,5,1,7),move(2,6,3,8),move(2,7,4,8),move(2,8,1,6),move(3,1,2,3),move(3,2,5,1),move(3,3,2,1),move(3,4,1,3),move(3,5,1,6),move(3,6,1,7),move(3,7,5,8),move(3,8,1,7),move(4,1,2,2),move(4,2,2,1),move(4,3,2,2),move(4,4,2,3),move(4,5,3,7),move(4,6,2,7),move(4,7,2,8),move(4,8,3,6),move(5,1,7,2),move(5,2,3,1),move(5,3,7,2),move(5,4,7,3),move(5,5,6,7),move(5,6,4,8),move(5,7,7,8),move(5,8,3,7),move(6,1,8,2),move(6,2,4,1),move(6,3,8,2),move(6,4,8,3),move(6,5,8,6),move(6,6,8,7),move(6,7,4,8),move(6,8,8,7),move(7,1,8,3),move(7,2,5,1),move(7,3,6,1),move(7,4,8,2),move(7,5,8,7),move(7,6,6,8),move(7,7,5,8),move(7,8,8,6),move(8,1,6,2),move(8,2,6,1),move(8,3,6,2),move(8,4,7,2),move(8,5,7,3),move(8,6,7,8),move(8,7,6,8),move(8,8,6,7)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "size(9).\n"
                "\n"
                "forbidden(1,9). forbidden(2,9). forbidden(3,9). forbidden(4,9). forbidden(5,9). forbidden(6,9). forbidden(7,9). forbidden(8,9). forbidden(9,9).\n"
                "\n"
                "forbidden(9,1). forbidden(9,2). forbidden(9,3). forbidden(9,4). forbidden(9,5). forbidden(9,6). forbidden(9,7). forbidden(9,8). forbidden(9,9).\n"
                "\n"
                ":- not move(1,5,2,7).\n"
                ":- not move(7,5,8,7).\n"
                ":- not move(1,3,2,1).\n"
                ":- not move(1,4,2,2).\n"
                "%:- not move(2,3,3,1).\n"
                ":- not move(7,4,8,2).\n"
                ":- not move(7,8,8,6).\n"
                ":- not move(2,1,1,3).\n"
                "%:- not move(2,4,1,6).\n"
                ":- not move(2,5,1,7).\n"
                ":- not move(3,1,2,3).\n"
                ":- not move(4,5,3,7).\n"
                ":- not move(5,6,4,8).\n"
                ":- not move(7,6,6,8).\n"
                ":- not move(8,6,7,8).\n"
                ":- not move(2,8,1,6).\n"
                ":- not move(3,3,2,1).\n"
                ":- not move(7,3,6,1).\n"
                ":- not move(8,4,7,2).\n"
                ":- not move(8,5,7,3).\n"
                ":- not move(1,7,3,8).\n"
                ":- not move(2,7,4,8).\n"
                ":- not move(3,7,5,8).\n"
                ":- not move(5,1,7,2).\n"
                ":- not move(5,7,7,8).\n"
                ":- not move(6,1,8,2).\n"
                ":- not move(6,5,8,6).\n"
                ":- not move(6,6,8,7).\n"
                "%:- not move(1,2,3,1).\n"
                ":- not move(1,8,3,7).\n"
                ":- not move(2,2,4,1).\n"
                ":- not move(3,2,5,1).\n"
                ":- not move(5,3,7,2).\n"
                "%:- not move(5,4,7,3).\n"
                ":- not move(6,3,8,2).\n"
                ":- not move(6,4,8,3).\n"
                ":- not move(6,8,8,7).\n"
                ":- not move(3,5,1,6).\n"
                ":- not move(3,6,1,7).\n"
                ":- not move(4,1,2,2).\n"
                ":- not move(4,6,2,7).\n"
                "%:- not move(4,7,2,8).\n"
                ":- not move(6,7,4,8).\n"
                ":- not move(7,7,5,8).\n"
                ":- not move(8,1,6,2).\n"
                ":- not move(8,7,6,8).\n"
                ":- not move(3,4,1,3).\n"
                "%:- not move(3,8,1,7).\n"
                ":- not move(4,2,2,1).\n"
                ":- not move(4,3,2,2).\n"
                ":- not move(4,4,2,3).\n"
                "%:- not move(4,8,2,7).\n"
                ":- not move(5,2,3,1).\n"
                ":- not move(5,8,3,7).\n"
                ":- not move(6,2,4,1).\n"
                "%:- not move(7,2,5,1).\n"
                "%:- not move(8,2,6,1).\n"
                ":- not move(8,3,6,2).\n"
                ":- not move(8,8,6,7).\n"
                ":- not move(1,1,2,3).\n"
                ":- not move(1,6,2,8).\n"
                "%:- not move(2,6,3,8).\n"
                ":- not move(5,5,6,7).\n"
                ":- not move(7,1,8,3).\n"
                "\n"
                "% encoding\n"
                "\n"
                "% Knight Tour\n"
                "\n"
                "% Input:\n"
                "% - size(N), if the chessboard is NxN\n"
                "% - forbidden(X,Y), if X,Y cannot be reached by the knight.\n"
                "\n"
                "% Output:\n"
                "% - move(X1,Y1,X2,Y2), if the knight moves from X1,Y1 to X2,Y2.\n"
                "\n"
                "\n"
                "\n"
                "\n"
                "% Define the chessboard.\n"
                "number(X) :- size(X).\n"
                "number(X) :- number(Y), X=Y-1, X>0.\n"
                "cell(X,Y) :- number(X), number(Y).\n"
                "\n"
                "% Guess the moves.\n"
                "move(X1,Y1,X2,Y2) | non_move(X1,Y1,X2,Y2) :- valid(X1,Y1,X2,Y2), not forbidden(X1,Y1), not forbidden(X2,Y2).\n"
                "\n"
                "% Compute all valid moves from each cell.\n"
                "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X1 = X2+2, Y1 = Y2+1.\n"
                "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X1 = X2+2, Y2 = Y1+1.\n"
                "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X2 = X1+2, Y1 = Y2+1.\n"
                "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X2 = X1+2, Y2 = Y1+1.\n"
                "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X1 = X2+1, Y1 = Y2+2.\n"
                "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X1 = X2+1, Y2 = Y1+2.\n"
                "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X2 = X1+1, Y1 = Y2+2.\n"
                "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X2 = X1+1, Y2 = Y1+2.\n"
                "\n"
                "% Exactly one move entering to each cell.\n"
                ":- cell(X,Y), not forbidden(X,Y), not exactlyOneMoveEntering(X,Y).\n"
                "exactlyOneMoveEntering(X,Y) :- move(X,Y,X1,Y1), not atLeastTwoMovesEntering(X,Y).\n"
                "atLeastTwoMovesEntering(X,Y) :- move(X,Y,X1,Y1), move(X,Y,X2,Y2), X1 != X2.\n"
                "atLeastTwoMovesEntering(X,Y) :- move(X,Y,X1,Y1), move(X,Y,X2,Y2), Y1 != Y2.\n"
                "\n"
                "% Exactly one move leaving each cell.\n"
                ":- cell(X,Y), not forbidden(X,Y), exactlyOneMoveLeaving(X,Y).\n"
                "exactlyOneMoveLeaving(X,Y) :- move(X1,Y1,X,Y), not atLeastTwoMovesLeaving(X,Y).\n"
                "atLeastTwoMovesLeaving(X,Y) :- move(X1,Y1,X,Y), move(X2,Y2,X,Y), X1 != X2.\n"
                "atLeastTwoMovesLeaving(X,Y) :- move(X1,Y1,X,Y), move(X2,Y2,X,Y), Y1 != Y2.\n"
                "\n"
                "% Each non-forbidden cell must be reached by the knight.\n"
                "reached(X,Y) :- move(_,_,X,Y).\n"
                "reached(X,Y) :- move(X,Y,_,_).\n"
                "% reached(X2,Y2) :- reached(X1,Y1), move(X1,Y1,X2,Y2).\n"
                ":- cell(X,Y), not forbidden(X,Y), not reached(X,Y).\n"
                "\n"
                "% Each forbidden cell must remain unreached.\n"
                ":- forbidden(X,Y), reached(X,Y).\n"
                , {"move("})));
    }

// {{{1 O23 Maximal Clique Problem

    SECTION("aspcomp2013_23") {
        // Author: Guenther Charwat, Martin Kronegger, Johan Wittocx*
        REQUIRE(
            "([[clique(1),clique(2),clique(5)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "node(1). node(2). node(3). node(4). node(5). node(6). \n"
                "edge(1,2). edge(1,5). edge(2,3). edge(2,5). edge(3,4). \n"
                "edge(4,5). edge(4,6).\n"
                "\n"
                "% encoding\n"
                "\n"
                "% Based on the 2009 ASP Competition encoding \n"
                "% submitted by the DLV team\n"
                "\n"
                "% order edges in order to reduce checks\n"
                "uedge(X,Y) :- edge(X,Y), X < Y.\n"
                "uedge(Y,X) :- edge(X,Y), Y < X.\n"
                "\n"
                "% guess the clique\n"
                "clique(X) | nonClique(X) :- node(X).\n"
                "\n"
                "% ensure property\n"
                ":- clique(X), clique(Y), not uedge(X,Y), X < Y.\n"
                "\n"
                "% maximize\n"
                ":~ nonClique(X). [1,X]\n"
                "\n"
                , {"clique("}, {3})));
    }

// {{{1 O24 Labyrinth

    SECTION("aspcomp2013_24") {
        // Author: Carmine Dodaro, Giovambattista Ianni, Martin Gebser*
        REQUIRE(
            "([[push(1,w,1),push(2,n,2)],[push(1,w,1),push(3,s,2)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "field(1,1).\n"
                "field(1,2).\n"
                "field(1,3).\n"
                "field(1,4).\n"
                "field(2,1).\n"
                "field(2,2).\n"
                "field(2,3).\n"
                "field(2,4).\n"
                "field(3,1).\n"
                "field(3,2).\n"
                "field(3,3).\n"
                "field(3,4).\n"
                "field(4,1).\n"
                "field(4,2).\n"
                "field(4,3).\n"
                "field(4,4).\n"
                "init_on(3,2).\n"
                "goal_on(1,4).\n"
                "connect(1,1,s).\n"
                "connect(1,1,w).\n"
                "connect(1,2,n).\n"
                "connect(1,2,e).\n"
                "connect(1,2,w).\n"
                "connect(1,3,e).\n"
                "connect(1,4,n).\n"
                "connect(1,4,w).\n"
                "connect(2,1,n).\n"
                "connect(2,1,w).\n"
                "connect(2,2,n).\n"
                "connect(2,2,w).\n"
                "connect(2,3,n).\n"
                "connect(2,3,s).\n"
                "connect(2,4,n).\n"
                "connect(2,4,e).\n"
                "connect(2,4,w).\n"
                "connect(3,1,n).\n"
                "connect(3,1,s).\n"
                "connect(3,2,n).\n"
                "connect(3,2,w).\n"
                "connect(3,3,e).\n"
                "connect(3,4,n).\n"
                "connect(3,4,s).\n"
                "connect(3,4,w).\n"
                "connect(4,1,n).\n"
                "connect(4,1,w).\n"
                "connect(4,2,n).\n"
                "connect(4,2,s).\n"
                "connect(4,2,e).\n"
                "connect(4,2,w).\n"
                "connect(4,3,n).\n"
                "connect(4,3,e).\n"
                "connect(4,4,w).\n"
                "max_steps(2).\n"
                "\n"
                "% encoding\n"
                "\n"
                "dir(e). dir(w). dir(n). dir(s).\n"
                "inverse(e,w). inverse(w,e).\n"
                "inverse(n,s). inverse(s,n).\n"
                "\n"
                "row(X) :- field(X,Y).\n"
                "col(Y) :- field(X,Y).\n"
                "\n"
                "num_rows(X) :- row(X), not row(XX), XX = X+1.\n"
                "num_cols(Y) :- col(Y), not col(YY), YY = Y+1.\n"
                "\n"
                "goal(X,Y,0)   :- goal_on(X,Y).\n"
                "reach(X,Y,0)  :- init_on(X,Y).\n"
                "conn(X,Y,D,0) :- connect(X,Y,D).\n"
                "\n"
                "step(S) :- max_steps(S),     0 < S.\n"
                "step(T) :- step(S), T = S-1, 1 < S.\n"
                "\n"
                "%%  Direct neighbors\n"
                "\n"
                "dneighbor(n,X,Y,XX,Y) :- field(X,Y), field(XX,Y), XX = X+1.\n"
                "dneighbor(s,X,Y,XX,Y) :- field(X,Y), field(XX,Y), XX = X-1.\n"
                "dneighbor(e,X,Y,X,YY) :- field(X,Y), field(X,YY), YY = Y+1.\n"
                "dneighbor(w,X,Y,X,YY) :- field(X,Y), field(X,YY), YY = Y-1.\n"
                "\n"
                "%%  All neighboring fields\n"
                "\n"
                "neighbor(D,X,Y,XX,YY) :- dneighbor(D,X,Y,XX,YY).\n"
                "neighbor(n,X,Y, 1, Y) :- field(X,Y), num_rows(X).\n"
                "neighbor(s,1,Y, X, Y) :- field(X,Y), num_rows(X).\n"
                "neighbor(e,X,Y, X, 1) :- field(X,Y), num_cols(Y).\n"
                "neighbor(w,X,1, X, Y) :- field(X,Y), num_cols(Y).\n"
                "\n"
                "%%  Select a row or column to push\n"
                "\n"
                "neg_goal(T) :- goal(X,Y,T), not reach(X,Y,T).\n"
                "\n"
                "rrpush(T)   :- step(T), neg_goal(S), S = T-1, not ccpush(T).\n"
                "ccpush(T)   :- step(T), neg_goal(S), S = T-1, not rrpush(T).\n"
                "\n"
                "orpush(X,T) :- row(X), row(XX), rpush(XX,T), X != XX.\n"
                "ocpush(Y,T) :- col(Y), col(YY), cpush(YY,T), Y != YY.\n"
                "\n"
                "rpush(X,T)  :- row(X), rrpush(T), not orpush(X,T).\n"
                "cpush(Y,T)  :- col(Y), ccpush(T), not ocpush(Y,T).\n"
                "\n"
                "push(X,e,T) :- rpush(X,T), not push(X,w,T).\n"
                "push(X,w,T) :- rpush(X,T), not push(X,e,T).\n"
                "push(Y,n,T) :- cpush(Y,T), not push(Y,s,T).\n"
                "push(Y,s,T) :- cpush(Y,T), not push(Y,n,T).\n"
                "\n"
                "%%  Determine new position of a (pushed) field\n"
                "\n"
                "shift(XX,YY,X,Y,T) :- neighbor(e,XX,YY,X,Y), push(XX,e,T), step(T).\n"
                "shift(XX,YY,X,Y,T) :- neighbor(w,XX,YY,X,Y), push(XX,w,T), step(T).\n"
                "shift(XX,YY,X,Y,T) :- neighbor(n,XX,YY,X,Y), push(YY,n,T), step(T).\n"
                "shift(XX,YY,X,Y,T) :- neighbor(s,XX,YY,X,Y), push(YY,s,T), step(T).\n"
                "shift( X, Y,X,Y,T) :- field(X,Y), not push(X,e,T), not push(X,w,T), not push(Y,n,T), not push(Y,s,T), step(T).\n"
                "\n"
                "%%  Move connections around\n"
                "\n"
                "conn(X,Y,D,T) :- conn(XX,YY,D,S), S = T-1, dir(D), shift(XX,YY,X,Y,T), step(T).\n"
                "\n"
                "%%  Location of goal after pushing\n"
                "\n"
                "goal(X,Y,T) :- goal(XX,YY,S), S = T-1, shift(XX,YY,X,Y,T), step(T).\n"
                "\n"
                "%%  Locations reachable from new position\n"
                "\n"
                "reach(X,Y,T) :- reach(XX,YY,S), S = T-1, shift(XX,YY,X,Y,T), step(T).\n"
                "reach(X,Y,T) :- reach(XX,YY,T), dneighbor(D,XX,YY,X,Y), conn(XX,YY,D,T), conn(X,Y,E,T), inverse(D,E), step(T).\n"
                "\n"
                "%%  Goal must be reached\n"
                "\n"
                ":- neg_goal(S), max_steps(S).\n"
                "\n"
                "%% Project output\n"
                "\n"
                "% #hide.\n"
                "% #show push(Z,D,T).\n"
                "\n"
                , {"push("})));
    }

// {{{1 O25 Minimal Diagnosis

    SECTION("aspcomp2013_25") {
        // Author: Marcello Balduccini, Martin Gebser*
        REQUIRE(
            "([[active(0),active(3)]],"
            "[-:33:30-38: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:34:30-38: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:36:33-41: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:37:33-41: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:40:33-41: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:41:33-41: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:48:43-51: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:49:43-51: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:57:28-36: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:71:68-76: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:72:68-76: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:73:68-76: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:75:68-76: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:76:68-76: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:84:68-76: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:85:68-76: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:86:68-76: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:99:102-110: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:99:116-124: info: atom does not occur in any rule head:\n  input(W)\n"
            ",-:100:102-110: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:100:116-124: info: atom does not occur in any rule head:\n  input(W)\n"
            ",-:101:102-110: info: atom does not occur in any rule head:\n  input(V)\n"
            ",-:101:116-124: info: atom does not occur in any rule head:\n  input(W)\n])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "vertex(0). vertex(1). vertex(2). vertex(3). vertex(4). \n"
                "obs_vlabel(1,p). obs_vlabel(3,p).\n"
                "\n"
                "edge(0,1).         edge(0,3).         edge(0,4).\n"
                "obs_elabel(0,1,p). obs_elabel(0,3,m). obs_elabel(0,4,m).\n"
                "\n"
                "edge(1,0).\n"
                "obs_elabel(1,0,p).\n"
                "\n"
                "edge(1,2).\n"
                "obs_elabel(1,2,p).\n"
                "\n"
                "edge(2,4).\n"
                "obs_elabel(2,4,m).\n"
                "\n"
                "edge(3,1).         edge(3,2).         edge(3,4).\n"
                "obs_elabel(3,1,p). obs_elabel(3,2,p). obs_elabel(3,4,p).\n"
                "\n"
                "% encoding\n"
                "\n"
                "%%%%%%%%%%%%%%%%%\n"
                "% Preprocessing %\n"
                "%%%%%%%%%%%%%%%%%\n"
                "\n"
                "sign(m). sign(p).\n"
                "\n"
                "diff(V,V)  :- edge(V,V), obs_elabel(V,V,m), not obs_elabel(V,V, p).\n"
                "diff(U,V)  :- edge(U,V), obs_elabel(U,V,m), not obs_elabel(U,V, p), obs_vlabel(U,S), obs_vlabel(V,S).\n"
                "diff(U,V)  :- edge(U,V), obs_elabel(U,V, p), not obs_elabel(U,V,m), obs_vlabel(U,S), obs_vlabel(V,T), S != T.\n"
                "\n"
                "nontriv(V) :- vertex(V), not input(V), edge(U,V), not diff(U,V).\n"
                "trivial(V) :- vertex(V), not input(V), not nontriv(V).\n"
                "\n"
                "btedge(W,U,V) :- vertex(V), not input(V), not trivial(V), edge(W,V), edge(U,V), edge(Z,V), W < Z, Z < U.\n"
                "ntedge(W,U,V) :- vertex(V), not input(V), not trivial(V), edge(W,V), edge(U,V), W < U, not btedge(W,U,V).\n"
                "nfirst(U,V)   :- ntedge(W,U,V).\n"
                "nlast(W,V)    :- ntedge(W,U,V).\n"
                "first(U,V)    :- vertex(V), not input(V), not trivial(V), edge(U,V), not nfirst(U,V).\n"
                "last(U,V)     :- vertex(V), not input(V), not trivial(V), edge(U,V), not nlast(U,V).\n"
                "\n"
                "\n"
                "%%%%%%%%%%%%%\n"
                "% Generator %\n"
                "%%%%%%%%%%%%%\n"
                "\n"
                "active(V) | inactive(V) :- vertex(V), not input(V).\n"
                "inactive(V)             :- vertex(V), not input(V), active(W), trivial(W), V != W.\n"
                "singleton               :- active(V), trivial(V).\n"
                "\n"
                "reach(U,V) :- edge(U,V), active(V), not trivial(V).\n"
                "reach(V,U) :- edge(U,V), active(V), not trivial(V),                        not obs_vlabel(U,p), not obs_vlabel(U,m).\n"
                "reach(U,W) :- edge(U,V), active(V), not trivial(V), reach(V,W), vertex(W).\n"
                "reach(V,W) :- edge(U,V), active(V), not trivial(V), reach(U,W), vertex(W), not obs_vlabel(U,p), not obs_vlabel(U,m).\n"
                "\n"
                "aedge(V) :- vertex(V), not input(V), not trivial(V), not obs_vlabel(V,p), not obs_vlabel(V,m), active(W), edge(V,W).\n"
                "\n"
                ":- active(V), not trivial(V), active(W), not trivial(W), not reach(V,W).\n"
                ":- active(V), not trivial(V), not obs_vlabel(V,p), not obs_vlabel(V,m), not aedge(V).\n"
                "\n"
                "\n"
                "%%%%%%%%%%%%%%%%%%%%%%\n"
                "% Inconsistency Test %\n"
                "%%%%%%%%%%%%%%%%%%%%%%\n"
                "\n"
                "vlabel(V,p)   | vlabel(V,m)   :- active(V),    not trivial(V),               not obs_vlabel(V,p),   not obs_vlabel(V,m).\n"
                "vlabel(U,p)   | vlabel(U,m)   :- active(V),    not trivial(V), edge(U,V),    not obs_vlabel(U,p),   not obs_vlabel(U,m).\n"
                "llabel(U,V,p) | llabel(U,V,m) :- active(V),    not trivial(V), edge(U,V),    not obs_elabel(U,V,p), not obs_elabel(U,V,m).\n"
                "\n"
                "vlabel(V,S)   :- vertex(V), obs_vlabel(V,S),   not trivial(V), not input(V).\n"
                "vlabel(U,S)   :- edge(U,V), obs_vlabel(U,S),   not trivial(V), not input(V).\n"
                "llabel(U,V,S) :- edge(U,V), obs_elabel(U,V,S), not trivial(V), not input(V).\n"
                "\n"
                "oppo(U,V)     :- llabel(U,V,m), vlabel(U,S),   not trivial(V), not input(V), not obs_elabel(U,V,p), active(V), vlabel(V,S).\n"
                "oppo(U,V)     :- llabel(U,V,p), vlabel(U,S),   not trivial(V), not input(V), not obs_elabel(U,V,m), active(V), vlabel(V,T), S != T.\n"
                "\n"
                "coppo(U,V)    :- oppo(U,V), first(U,V).\n"
                "coppo(U,V)    :- oppo(U,V), coppo(W,V), ntedge(W,U,V).\n"
                "\n"
                "bot           :- singleton.\n"
                "bot           :- active(V), coppo(U,V), last(U,V).\n"
                "\n"
                "vlabel(V,S)   :- bot, vertex(V), sign(S),      not trivial(V), not input(V), not obs_vlabel(V,p),   not obs_vlabel(V,m).\n"
                "vlabel(U,S)   :- bot, edge(U,V), sign(S),      not trivial(V), not input(V), not obs_vlabel(U,p),   not obs_vlabel(U,m).\n"
                "llabel(U,V,S) :- bot, edge(U,V), sign(S),      not trivial(V), not input(V), not obs_elabel(U,V,p), not obs_elabel(U,V,m).\n"
                "\n"
                ":- not bot.\n"
                "\n"
                "\n"
                "%%%%%%%%%%%%%%%%%%%\n"
                "% Minimality Test %\n"
                "%%%%%%%%%%%%%%%%%%%\n"
                "\n"
                "mvlabel(W,V,p)   | mvlabel(W,V,m)   :-                active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V.\n"
                "mvlabel(W,U,p)   | mvlabel(W,U,m)   :- edge(U,V),     active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V.\n"
                "mllabel(W,U,V,p) | mllabel(W,U,V,m) :- edge(U,V),     active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V.\n"
                "\n"
                "mvlabel(W,V,S)   :- obs_vlabel(V,S),                  vertex(W), not trivial(V), not trivial(W), not input(V), not input(W),        W != V.\n"
                "mvlabel(W,U,S)   :- obs_vlabel(U,S),    edge(U,V),    vertex(W), not trivial(V), not trivial(W), not input(V), not input(W),        W != V.\n"
                "mllabel(W,U,V,S) :- obs_elabel(U,V,S),  edge(U,V),    vertex(W), not trivial(V), not trivial(W), not input(V), not input(W),        W != V.\n"
                "\n"
                "minfl(W,V,p)     :- mvlabel(W,U,S), mllabel(W,U,V,S), active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V.\n"
                "minfl(W,V,m)     :- mvlabel(W,U,S), mllabel(W,U,V,T), active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V, S != T.\n"
                "\n"
                ":- active(V), active(W), not trivial(V), not trivial(W), W != V, mvlabel(W,V,S), not minfl(W,V,S).\n"
                "\n"
                "\n"
                "%%%%%%%%%%\n"
                "% Output %\n"
                "%%%%%%%%%%\n"
                "\n"
                "% #hide.\n"
                "% #show active(V).\n"
                , {"active("})));
    }

// {{{1 O26 Hanoi Tower

    SECTION("aspcomp2013_26") {
        // Author: Gayathri Namasivayam, Miroslaw Truszczynski, Shaden Smith, Alex Westlund
        REQUIRE(
            "([[put(0,3,9),put(1,2,8),put(2,8,9)],[put(0,4,9),put(1,2,8),put(2,8,9)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "steps(3). time(0). time(1). time(2). time(3). disk(1). disk(2). disk(3). disk(4). disk(5). disk(6). disk(7). disk(8). disk(9). on0(5,1). on0(6,5). on0(7,6). on0(8,7). on0(9,8). ongoal(5,1). ongoal(6,5). ongoal(7,6). ongoal(8,2). ongoal(9,8).\n"
                "\n"
                "% encoding\n"
                "\n"
                "% The meaning of the time predicate is self-evident. As for the disk\n"
                "% predicate, there are k disks 1,2,...,k. Disks 1, 2, 3, 4 denote pegs. \n"
                "% Disks 5, ... are \"movable\". The larger the number of the disk, \n"
                "% the \"smaller\" it is.\n"
                "%\n"
                "% The program uses additional predicates:\n"
                "% on(T,N,M), which is true iff at time T, disk M is on disk N\n"
                "% move(t,N), which is true iff at time T, it is disk N that will be\n"
                "% moved\n"
                "% where(T,N), which is true iff at time T, the disk to be moved is moved\n"
                "% on top of the disk N.\n"
                "% goal, which is true iff the goal state is reached at time t\n"
                "% steps(T), which is the number of time steps T, required to reach the goal (provided part of Input data)\n"
                "\n"
                "% Read in data \n"
                "   on(0,N1,N) :- on0(N,N1).\n"
                "    onG(K,N1,N) :- ongoal(N,N1), steps(K).\n"
                "          \n"
                "% Specify valid arrangements of disks\n"
                "   % Basic condition. Smaller disks are on larger ones\n"
                "   :- time(T), on(T,N1,N), N1>=N.\n"
                "   \n"
                "% Specify a valid move (only for T<t)\n"
                "   % pick a disk to move\n"
                "    move(T,N) | noMove(T,N) :- disk(N), time(T), steps(K), T<K.\n"
                "    :- move(T,N1), move(T,N2), N1 != N2.\n"
                "    :- time(T), steps(K), T<K, not diskMoved(T).\n"
                "    diskMoved(T) :- move(T,Fv1).\n"
                "\n"
                "   % pick a disk onto which to move\n"
                "    where(T,N) | noWhere(T,N) :- disk(N), time(T), steps(K), T<K.\n"
                "    :- where(T,N1), where(T,N2), N1 != N2.\n"
                "    :- time(T), steps(K), T<K, not diskWhere(T).\n"
                "    diskWhere(T) :- where(T,Fv1).\n"
                "\n"
                "   % pegs cannot be moved\n"
                "   :- move(T,N), N<5.\n"
                "\n"
                "   % only top disk can be moved\n"
                "   :- on(T,N,N1), move(T,N).\n"
                "\n"
                "   % a disk can be placed on top only.\n"
                "   :- on(T,N,N1), where(T,N).\n"
                "\n"
                "   % no disk is moved in two consecutive moves\n"
                "   :- move(T,N), move(TM1,N), TM1=T-1.\n"
                "\n"
                "% Specify effects of a move\n"
                "   on(TP1,N1,N) :- move(T,N), where(T,N1), TP1=T+1.\n"
                "\n"
                "   on(TP1,N,N1) :- time(T), steps(K), T<K,\n"
                "                   on(T,N,N1), not move(T,N1), TP1=T+1.\n"
                "\n"
                "% Goal description\n"
                "    :- not on(K,N,N1), onG(K,N,N1), steps(K).\n"
                "    :- on(K,N,N1), not onG(K,N,N1),steps(K).\n"
                "\n"
                "% Solution\n"
                "    put(T,M,N) :- move(T,N), where(T,M), steps(K), T<K.\n"
                , {"put("})));
    }

// {{{1 O27 Graph Colouring

    SECTION("aspcomp2013_27") {
        // Author: Johannes Wallner, Marcello Balduccini*, Yuliya Lierler*
        REQUIRE(
            "([[chosenColour(1,blue),chosenColour(2,green),chosenColour(3,red)],"
            "[chosenColour(1,blue),chosenColour(2,red),chosenColour(3,green)],"
            "[chosenColour(1,green),chosenColour(2,blue),chosenColour(3,red)],"
            "[chosenColour(1,green),chosenColour(2,red),chosenColour(3,blue)],"
            "[chosenColour(1,red),chosenColour(2,blue),chosenColour(3,green)],"
            "[chosenColour(1,red),chosenColour(2,green),chosenColour(3,blue)]],[])" == IO::to_string(solve(
                "% instance\n"
                "\n"
                "node(1). node(2). node(3). \n"
                "link(1,2). link(2,1). link(2,3). \n"
                "link(3,2). link(3,1). link(1,3). \n"
                "colour(red). colour(green). colour(blue).\n"
                "\n"
                "% encoding\n"
                "\n"
                "% Guess colours.\n"
                "chosenColour(N,C) | notChosenColour(N,C) :- node(N), colour(C).\n"
                "\n"
                "% At least one color per node.\n"
                ":- node(X), not colored(X).\n"
                "colored(X) :- chosenColour(X,Fv1).\n"
                "\n"
                "% Only one color per node.\n"
                ":- chosenColour(N,C1), chosenColour(N,C2), C1!=C2. \n"
                "\n"
                "% No two adjacent nodes have the same colour. \n"
                ":- link(X,Y),  X<Y, chosenColour(X,C), chosenColour(Y,C).\n"
                "\n"
                , {"chosenColour("})));
    }

// }}}1

}

} } } // namespace Test Output Gringo


