Disjunctive logic programs are a powerful tool in knowledge representation and commonsense reasoning. The development of DLV, allows to exploit disjunctive logic programs for solving complex problems. However, disjunctive logic programming systems are currently missing any interface supporting the integration between commonly used software development languages (like Java) and disjunctive logic programs. The DLV Wrapper is a library, actually implemented in Java that wraps the DLV system inside an external application, allowing to embed disjunctive logic programs inside Object-Oriented source code. The DLV Wrapper combine Java code with disjunctive logic programs was originally introduced in Francesco Ricca, “The DLV Java Wrapper” In APPIA-GULP-PRODE, 2003 Joint Conference on Declarative Programming, pp 263-274, AGP-2003, Reggio Calabria, Italy, September 3-5, 2003. The DLV Wrapper gives us full control on DLV execution; a DLV invocation is composed by the following steps:

  • Setup input and invocation parameters
  • Run DLV
  • Handle DLV output

Use DLV Wrapper

The DLV Wrapper API is a Java Library containing a class called DLVWrapper; this class is a singleton that always returns the same object instance of WLVWrapper. The DLVWrapper class implements the necessary methods to create a new object that provides to initialize, execute and recive the results from a DLV process. The interface DLVInvocation implements the pattern Observer and it is the observable that notifies to every signed observer (each class implementing the interface DLVHandler) the results of DLV execution. There are differents type of Observers, everyone is created to receive a particular result from DLV:

  • ModelHandler: receives only notifications of models calculations. This observer receives a ModelResult when the parserOutput calculates an entire model,without waiting the calculation of all models.
  • PredicateHandler: receives only notifications of predicates calculations. This observer receives a PredicateResult when the parserOutput calculates an entire model,without waiting the calculation of all models.
  • PredicateHandlerWithName: receives only notifications of predicates with specified names. In this case A PredicateResult is notified when the parserOutput calculates an entire model, without waiting the calculation of all models.
  • LiteralHandler: receives notifications for each literal computed from DLV invocation when the parserOutput calculates a fact in a model, without waiting the whole model is calculated.
  • QueryTupleHandler: receives notifications about each literal computed from DLV invocation while executing a query.
  • QueryResultHandler: receives a notification about the query result executed by DLV invocation.
  • DlvFinishedHandler: receives a notification when the execution of DLV is finished, notifying errors.

Each observer can subscribe itself to receive the notifications for a particular result. When the DLV invocation is started, it invokes a new Thread which execute DLV and notifies each observer interested on the result computed.

The DLV Wrapper API provides another class used to scroll the results computed from DLV as an Enumeration. The class ModelBufferedHandler is a concrete DLVHandler that allows to scroll the models computed by DLVInvocation. The ModelBufferedHandler constructor receive a DLVInvocation, in this way the new instance created subscribe itself at the invocation and synchronizes its methods (hasMoreModels, nextModel) with the execution state.

A DLVInvocation receives a DLVInputProgram as input that represents a logic program input of DLV. It is possible to compose any DLVInputProgram specifying:

  • a list of DLV files containing parts of the program
  • a list of Expression
  • a DLV program defined with internal Expression
  • a set of strings to add to a local variable.

For further Information please refer to the online documentation (Javadoc API)

Samples of use

This is an example of use DLV Wrapper; firstly it prepare a new instance of DLVInputProgram using all available methods to create a logic program:

/* I create a new instance of DLVInputProgram */
DLVInputProgram inputProgram=new DLVInputProgramImpl();

/* I can add some file to the DLVInputProgram */
File file1=new File(PATH_1);
File file2=new File(PATH_2);
inputProgram.addFile(file1);
inputProgram.addFile(file2);

/* I can specify a part of DLV program using simple strings */
inputProgram.addText(" A STRING ");
/* I can specify a part of DLV program using an entire Program or an Expression */
Program program=new Program();
program.add(new Rule(" A STRING "));
inputProgram.includeProgram(program);
/* I can add directly an Expression that will be added into the default program stored in the DLVInvocation */
inputProgram.addExpression(new Rule(" A STRING "));

The next step is to prepare a new DLV invocation, the class DLVWrapper provides a new instance of DLVInvocation, using the default path or specifying another path of DLV executable:

/* I create a new instance of DLVInvocation using the DLVWrapper class specifying a path for DLV executable */
DLVInvocation invocation=DLVWrapper.getInstance(). createInvocation(PATH_DLV);

The DLVInvocation object is configurable using different parameters before the real execution. The DLVInvocation class provides methos necessary to set the query and to set the execution options.

/* Set the query of DLV invocation. If the Query in the DLVInvocation is not null, any queries in the inputProgram(in the text, files or defaultProgram) is ignored. */
invocation.setQuery(new Query( QUERY STRING );
/* The class DLVInvocation have a method to specify the execution options by simple strings */
invocation.addOption(" OPTION STRING ");
/* Alternatively DLVInvocation provides specified methods to set the execution options */
/* Set the max-int '-N' option. Set the limit of the integer to [0,N] in the DLV invocation. This function remove automatically any existing max-int '-N' option. */
invocation.setMaxint(10);

/* Sets the max number of models computed in the DLV execution. If n is 0, all models are computed. This method deletes each option that contains the string "-n=" and adds a new option "-n='n'. */
invocation.setNumberOfModels(10);
/* Includes only instances of the predicate specified in the filter parameter in output. This method deletes each option that contains the string filter= or -pfilter=, and adds a new option with the new filter */
List filters=new ArrayList();
filters.add( FILTER STRING );
invocation.setFilter(filter, true);

The options can be eliminated with the respective methods:

/* Remove any n° of models option */
invocation.resetNumberOfModels();
/* Remove any max-int option */
invocation.resetMaxint();
/* Reset any filter option */
invocation.resetFilter();
/* Reset all options */
invocation.resetFilter();

When the invocation setting is complete, can be create the observers that receive the notifications about the results of execution. Every DLVHandler (the observer) must be registered on the DLVInvocation (the observable) to receive the notifications.

/* I create a new observer that receive a notification for the models computed and store them in a list */
final List models= new ArrayList();
ModelHandler modelHandler=new ModelHandler(){
final public void handleResult(DLVInvocation obsd, ModelResult res) {
models.add(res);
}
};
/* Subscribe the handler from the DLVInvocation */
invocation.subscribe(modelHandler);
/* I create a new observer that receive a notification for the predicates computed with a specified name and store them in a list */
final List predicates= new ArrayList();
PredicateHandlerWithName predicateHandler=new PredicateHandlerWithName(){
public void handleResult(DLVInvocation obsd, PredicateResult res) {
predicates.add(res);
}
public List getPredicateNames() {
List predicates=new ArrayList();
predicates.add( PREDICATE NAME1 );
predicates.add( PREDICATE NAME2 );
return predicates;
}
};
/* Subscribe the handler from the DLVInvocation */
invocation.subscribe(predicateHandler);
/* Another mode to scroll the computed models is to use the ModelBufferedHandler that is a concrete observer that work like Enumeration. NOTE: the ModelBufferedHandler subscribe itself to the DLVInvocation */
ModelBufferedHandler modelBufferedHandler=new ModelBufferedHandler(invocation);
/* In this moment I can start the DLV execution */
invocation.run();
/* Scroll all models computed */
while(modelBufferedHandler.hasMoreModels()){
Model model=modelBufferedHandler.nextModel();
while(model.hasMorePredicates()){
Predicate predicate=model.nextPredicate();
while(predicate.hasMoreLiterals()){
Literal literal=predicate.nextLiteral();
}
}
}
/* If i wont to wait the finish of execution, i can use thi method */
invocation.waitUntilExecutionFinishes();
/* At the term of execution, I can control the errors created by DLV invocation */
List =invocation.getErrors();

Downloads

Java ARchive Library (JAR) DLVwrapper-v4.2.jar Javadoc API Wrapper Javadoc

Former DLVWrapper web site: https://www.mat.unical.it/wrapper/

Contacts:

ricca[at]mat.unical.it

onofrio.febbraro[at]dlvsystem.com