Attachment 'dlv-complex-tutorial.html'
DownloadDLV-Complex: a (short) Tutorial
This tutorial is aimed at helping you in properly running DLV-Complex programs. The capabilities offered by the system are shown by means of a few simple examples. Hereafter, the binary of the system is supposed to be named dlv-complex, while names of the file storing the proposed examples are specified for each example as a commented line (after a % symbol). Thus, lets start.
Consider the following program:
%% File: tutorial-ex-01.dl %%
p( s(X) ) :- q( X, f(Y, Z) ).
q( a, f( b, c ) ).
Running DLV-Complex on this example, we obtain the following output:
$ dlv-complex -silent tutorial-ex-01.dl
{q(a,f(b,c)), p(s(a))}
The unique answer set is given. In this case, the only option specified on the command line is -silent. This is a DLV option (not peculiar for DLV-Complex) which suppresses various informational output and blank lines.
The finite-domain check is performed with success; thus, the program is guaranteed to terminate.
Consider now the following recursive program:
%% File: tutorial-ex-02.dl %%
p( X, s(Y) ) :- p( f(X), Y ).
p( f( a ), b ).
Running DLV-Complex on this example, we obtain:
$ dlv-complex -silent tutorial-ex-02.dl
NOT FINITE-DOMAIN RULES
p(_0,_2) :- p(_3,_1), #function_builtin(_2,s,_1), #function_builtin(_3,f,_0).
The program does not pass the finite-domain check, because of the second argument of the predicate p. The system outputs the set of rules that are not recognized as finite-domain. Note that rules are printed as internally stored in the system, i.e., after the proper rewriting for managing function symbols and with unique identifiers in place of the original variables.
Even if the program is not recognized as finite-domain, it is easy to see that such a program is finitely-ground, as the increasing nesting level of the second argument of p is blocked by the first argument. We can then ask the system to skip the finite-domain check through the -nofdcheck command line option, obtaining:
$ dlv-complex -silent -nofdcheck tutorial-ex-02.dl
{p(a,s(b)), p(f(a),b)}
Lets drop now the first argument of p, and consider the following modified version of the previous program:
%% File: tutorial-ex-03.dl %%
p( s(Y) ) :- p( Y ).
p( b ).
The program still results as not finite-domain. But, in this case, if we ask the system to skip the finite-domain check (thus forcing the computation), it does not halt at all. Indeed, it indefinitely generates new ground atoms of the form p(s(b)), p(s(s(b))), p(s(s(s(b)))) and so on. Youd better kill the process :)
Nevertheless, we still can perform some safe computation, even in this case. Indeed, we can force the system to limit the generation of ground atoms with a (fixed) maximum nesting level for their terms, by using the MAXNL options. For instance, by specifying MAXNL=4 on the command line, we obtain:
$ dlv-complex -silent -nofdcheck MAXNL=4 tutorial-ex-03.dl
{p(b), p(s(b)), p(s(s(b))), p(s(s(s(b)))), p(s(s(s(s(b)))))}
Lets start now taking advantage from the availability of complex terms such lists and sets. The following program is intended in order to compute all possible ordered lists of numbers between 1 and 4. Note as lists are terms between square brakets ([]).
%% File: tutorial-ex-04.dl %%
number(1..4).
orderedLists([X]) :- number(X).
orderedLists([X|[Y|L]]) :- orderedLists([Y|L]), number(X), X < Y.
Unfortunately, the program results as no finite-domain.
$ dlv-complex -silent tutorial-ex-04.dl
NOT FINITE-DOMAIN RULES
orderedLists(_4) :- orderedLists(_5), number(_0), #less_builtin(_0,_1), #list_builtin(_4,HeadTailList,_0,_3), #list_builtin(_5,HeadTailList,_1,_2), #list_builtin(_3,HeadTailList,_1,_2).
Nevertheless, we know that the computation would terminate, because the possible elements of the lists are limited to the numbers 1..4, and each newly generated list (see the last recursive rule) must come from an already generated list by means of the addition of an element which is lower to the one which is currently the head of the list. Thus, we can safely skip the finite-domain check.
$ dlv-complex -silent tutorial-ex-04.dl -nofdcheck
Error: arithmetics is only supported if #maxint has been set.
The error here comes from the need of set the maximum value for integer values within the program (the system requires this every time we exploit a built-in that involves integer values). We can do the job by setting maxint (in this case, by specifying -N=10 on the command line), exactly as we would do while using DLV (see the DLV manual for further details), finally getting the result.
$ dlv-complex -silent tutorial-ex-04.dl nofdcheck N=10
{number(1), number(2), number(3), number(4), orderedLists([1]), orderedLists([2]), orderedLists([3]), orderedLists([4]), orderedLists([1,2]), orderedLists([1,3]), orderedLists([1,4]), orderedLists([2,3]), orderedLists([2,4]), orderedLists([3,4]), orderedLists([1,2,3]), orderedLists([1,2,4]), orderedLists([1,3,4]), orderedLists([2,3,4]), orderedLists([1,2,3,4])}
What to do now, if we want to exploit the provided library for list and set manipulation? We must first ensure to have the library itself (tipically, a file named ListAndSet.so or ListAndSet.dll, depending on your operating system): you can freely download it from the DLV-Complex website. By default, it is supposed to stay in the ./LIB folder, where . is the folder containing the DLV-Complex executable. Of course, you can locate it anywhere else, provided that you tell the system where to find it.
Lets have a look at the following example. It is intended to compute all lists of 3 elements or less chosen among {a,b,c,d} with no repetitions.
%% File: tutorial-ex-05.dl %%
#include<ListAndSet>
element(a). element(b). element(c). element(d).
Lists([X]) :- element(X).
Lists([X|[Y|L]]) :- Lists([Y|L]), element(X), #length(L) < 2, not #member(X,[Y|L])
First of all, note the #include<ListAndSet> line in the preamble. This tells the system to include the library, so that we can exploit the built-ins there included. In this example, #length(L) (being #length an interpreted function) is returns (as a term) the length of list L; #member(X,Y) (being #member a built-in predicate) is true if X is a member of list Y. Please refer to the reference guide for a full list and details about what is available in ListAndSet library.
Running DLV-Complex on this example produces the following (expected) output.
$ dlv-complex tutorial-ex-05.dl -silent -nofdcheck -N=3
{element(a), element(b), element(c), element(d), Lists([a]), Lists([b]), Lists([c]), Lists([d]), Lists([a,b]), Lists([a,c]), Lists([a,d]), Lists([b,a]), Lists([b,c]), Lists([b,d]), Lists([c,a]), Lists([c,b]), Lists([c,d]), Lists([d,a]), Lists([d,b]), Lists([d,c]), Lists([a,b,c]), Lists([a,b,d]), Lists([a,c,b]), Lists([a,c,d]), Lists([a,d,b]), Lists([a,d,c]), Lists([b,a,c]), Lists([b,a,d]), Lists([b,c,a]), Lists([b,c,d]), Lists([b,d,a]), Lists([b,d,c]), Lists([c,a,b]), Lists([c,a,d]), Lists([c,b,a]), Lists([c,b,d]), Lists([c,d,a]), Lists([c,d,b]), Lists([d,a,b]), Lists([d,a,c]), Lists([d,b,a]), Lists([d,b,c]), Lists([d,c,a]), Lists([d,c,b])}
The following program selects from a given EDB of words (represented as lists of chars) only those resulting as palindromic.
%% File: tutorial-ex-06.dl %%
#include<ListAndSet>
% EDB
word([a,n,n,a]).
word([a,n,n,a,m,a,r,i,a]).
word([a,d,a]).
% Select palindromic words.
palindromic(X) :- word(X), #reverse(X)==X.
The result of the computation is the following:
$ dlv-complex tutorial-ex-06.dl -silent
{word([a,n,n,a]), word([a,n,n,a,m,a,r,i,a]), word([a,d,a]), palindromic([a,n,n,a]), palindromic([a,d,a])}
Note that, this time, we did not need to skip the finite-domain check, as the program is finite-domain. Also, theres no need to set maxint.
As a last example, let us imagine that the administrator of a social network wants to increase the connections between users. In order to do that, (s)he decides to propose a connection to pairs of users that result, from their personal profile, to share more than two interests. If the data about users are given by means of EDB atoms of the form user(id, {interest1, . . . , interestn}), the following program computes the set of common interests between all pairs of users (by means of predicate sharedInterests), and selects all pairs of users sharing more than two interests (by means of predicate proposeConnection.
%% File: tutorial-ex-07.dl %%
#include<ListAndSet>
% EDB
user(john,{painting,music,reading}). user(mary,{sport,music}).
user(bill,{painting,music,sport,reading}). user(frank,{sport,dance}).
sharedInterests(U1,U2,#intersection(S1, S2)) :- user(U1,S1), user(U2, S2),U1 <> U2.
proposeConnection(pair(U1,U2)) :- sharedInterests(U1,U2,S), #card(S) > 2.
Note as set are terms between braces ({}). In this example, #intersection(S1,S2) (being #intersection an interpreted function) returns (as a term) the intersection of sets S1 and S2; #card(S), on the other hand, returns (as a term) the cardinality of set S.
Let us imagine that the ListAndSet library stays in folder /usr/local/mylib; we tell the system to look up there by means of option -libpath.
$ dlv-complex tutorial-ex-07.dl -silent -filter=proposeConnection,sharedInterests -N=10 -libpath=/usr/local/mylib
{sharedInterests(john,mary,{music}), sharedInterests(john,bill,{music,painting,reading}), sharedInterests(john,frank,{}), sharedInterests(mary,john,{music}), sharedInterests(mary,bill,{music,sport}), sharedInterests(mary,frank,{sport}), sharedInterests(bill,john,{music,painting,reading}), sharedInterests(bill,mary,{music,sport}), sharedInterests(bill,frank,{sport}), sharedInterests(frank,john,{}), sharedInterests(frank,mary,{sport}), sharedInterests(frank,bill,{sport}), proposeConnection(pair(john,bill)), proposeConnection(pair(bill,john))}
Attached Files
You are not allowed to attach a file to this page.