Embedded logic -- crossing the paradigm boundary

Instructor's Guide


intro, components, case study, crossing boundaries, styles, platform, summary, Q/A, literature
Knowledge is a substantial ingredient in many applications. By knowledge we mean information and rules operating on that information, to obtain derived information. As in any (software) engineering effort, maintenance, that is knowledge maintenance, is of crucial importance. When we do not avoid the dispersion of knowledge and information in the actual code of the system, maintenance will be difficult. Put differently, for reasons of flexibility and maintenance we need to factor out the (volatile) knowledge and information components.

Traditionally, the information components are often taken care of by a database that allows for the formulation of views to obtain (possibly aggregate) information. Logic or logic programming is a strictly more powerful mechanism to deal with information and knowledge. In our group, we have been studying the use of logic programming in knowledge-intensive software engineering applications.


  
embedded logic
<query kit=pl src=local.pl cmd=X:email_address(X)> <param format=" \%s"> <param result=""> <param display="<h4>The query</h4>"> <param header="<h4>The adresses</h4> <ul>"> <param footer="</ul>"> email_address(E) :- person(X), property(X,name:N), property(X,familyname:F), email(X,E), cout(['
  • ', N,' ',F,' has email adress ']), cout([ '<a href=mailto:', E, '>', E, '</a>',nl]). </query>
  • As an example, consider the query above, which is expressed in an SGML/XML like syntax. The query command X:email_address(X) asks for all X for which the predicate email_address(X) holds. The predicate email_address is defined between the query begin and end tags.

    The query tag is an element of one of the text processing filters to provide hypermedia support for software engineering described in  [HypermediaSE]. Processing the fragment above results in an HTML list of names and email addresses. The collection of filters itself is written in lex, yacc and C++. To process the query, an embedded logic programming interpreter is invoked. To merge the output from the query, a handler is installed for the cout command.

    The query example was motivated by the need to maintain Web pages for the administration of a colloquium within our group. The actual knowledge base consists of a list of people and some rules to determine their affiliations and email addresses. The knowledge base is made available by consulting the file local.pl.

    As concerns the implementation, the Java fragment below indicates how to access the logic programming interpreter from a (Java) program.

    
      query pl = new query("kit=pl src=remote.pl"); 
    logic.java
    pl.eval("X:assistant(X)"); String res = null; while ( (res = pl.result()) != null ) { System.out.println("
  • " + res); }
  • After creating a query object, the goal X:assistant(X) is invoked, which can be taken to mean, give me every X for which the predicate assistant(X) holds. The final output is obtained by iterating over the results of the evaluation of that goal. As a comment, multiple results may be obtained in Prolog by backtracking over the possible choice points.

    Distributed knowledge servers

    Maintaining knowledge is difficult. As a rule of thumb, avoid the replication of knowledge as much as possible. However, this means that we may need to access knowledge from remote sources. One (obvious) solution that presents itself is to allow for url-enabled consults, as illustrated in the fragment below.
    
      
    remote.pl
    :- source('www.cs.vu.nl/~eliens/db/se/people.pl'). :- source('www.cs.vu.nl/~eliens/db/se/institute.pl'). :- source('www.cs.vu.nl/~eliens/db/se/property.pl'). :- source('www.cs.vu.nl/~eliens/db/se/query.pl').
    This solution has (indeed) be implemented in our filters, since the url addressing scheme is straightforward and easy to implement.

    However, processing the information accessed by url is still done locally. So, the next step that may be suggested is to distribute the knowledge processing itself, for example by using CORBA.

    
      interface query { 
    query.idl
    void source(in string file); long eval(in string cmd); string result(in long id); oneway void halt(); };
    Exploiting the integration of CORBA and hush, we have defined an interface for query in IDL and implemented query client and query server objects. These objects may be created by giving appropriate parameters to the query constructor invocation. This approach allows for embedding remote knowledge processing transparently in our collection of filters. Nevertheless, although we showed that this approach is feasible, we have not addressed the problems that may occur due to the unavailability or faults of the server.