Practical Development  of Internet Prolog Applications using a Java Front End

Samhaa R. El-Beltagy, Mahmoud Rafea, & Ahmed Rafea 
Central Lab for Agricultural Expert Systems
Agricultural Research Center
Ministry of Agriculture and Land Reclamation.
 Cairo, Egypt
El-Nour St. Dokki 12311,Giza Egypt
{samhaa, mahmoud, rafea}@esic.claes.sci.eg

Introduction

The widespread use of the Internet and the World Wide Web has motivated  much work with the aim of  providing interactive applications on the Internet. Sun’s Java[Java97], Netscape plug-ins [BuPlg97], and  Microsoft’s  ActiveX[ActX97] are perhaps the most famous of these endeavors.  In order to support this new technology,  Internet browsers, and tools have undergone   numerous evolutions.  These advances  have made  the Internet a very suitable medium for providing sophisticated services including  those of  logic based nature. Traditionally, one of the  of the problems faced by  such applications, was that the languages in which they are usually developed (logic programming languages) was not directly supported on the Internet. Although, this lack of support has deprived Internet users from using applications that use extensive reasoning facilities  which are most naturally supported by these languages,   various  work arounds that make use of the emerging technology are currently being devised.
The use of Netscape Plug-ins is  one of these alternatives. However, through our experience in devising a prolog plug-in[SiNP97] we have identified several  disadvantages associated with such an approach.  Plug-ins can only support light weight applications, they are platform specific, and a user must download the plugin and install it before using it. Other  approaches propose the use of scripting languages with HTML[3]. While this approach might be effective, it is complex, consumes resources, and cannot be reused without changes to support another application.

This paper introduces an approach that takes advantage of  the current technology through the use of Java, to bring the power of prolog-based applications  to the Internet. The approach adopted follows a client/server architecture where the client is  a front end with reasonable intelligent qualities and the server is the prolog based application. Java has been chosen for the implementation of the  front end for a number of  reasons which are described briefly in the following points:
The first part of this paper introduces the application architecture devised to support this work. An intelligent image retrieval application, and a toy expert system, which have been developed using this approach, are then discussed.

Application Architecture

In the approach presented in this paper, the application consists of a mobile client component, a static server component, and two communication components: one for the client and one for the server. The communication between the client and the server is based on TCP/IP sockets  where exchange of ASCII based string messages is facilitated. The content of the messages is dependent on an application defined protocol supported by the socket components. Figure 1, depicts the relationship between the different application  components.
 
 
Figure 1: Relationship between the application components

 The client side represents the application front end is entirely  written in Java and is comprised of a number of components. At the heart of  the client side is the  interface communication model which is used for intelligent data collection. The  server side, represents the problem-solving/application-code, and the knowledge-base/data components and is entirely written in prolog.

The underlying assumption behind this work is that many applications could be separated into two parts: an application   component and an interface or a front end component. However, this work acknowledges the fact  application separation  is not usually a straight forward task since the control of the  interface is usually managed  by the application itself. For instance, in many  expert systems, the questions to be asked are determined by answers to previously asked questions.  In this case several solutions are possible. The first and the simplest of these, is devising  an application specific interface where the user is presented with all possible  inputs. Needless to say, this approach will not meet the needs of any reasonably large application, and in addition, will confuse the user.  Another approach, is to keep control embedded within the server application. In that case,  the client will be used to present the user with an input request upon receiving such a request from  the server. While this approach might seem reasonable, it suffers from major limitations. First, it relies on heavy communication between the server application and the client front end, so the user may have to wait for prolonged periods depending on the network traffic and band width. Another limitation, is that it engages the server in one connection for an indefinite amount of time, making it  impossible for other users to make use of that same server. Although time-out operations could be implemented to avoid indefinite postponement,  the server will still be not fully utilized. If however, the interface component employed a communication model that had just enough knowledge about which inputs it should ask about and in which cases, then the client could use this knowledge to collect all needed inputs in an intelligent fashion, then batch send them to the server for processing. In this case the connection between the client and the server will only be open for the period of sending the inputs, processing them at the server and receiving the output. For most practical applications, this period is usually reasonably short. Meantime,  if other clients need to service a request, the request will be placed in a wait queue where the waiting time will be short enough to make  that wait transparent. However, care must be taken in the selection of the queue size. Otherwise, if the number of the clients for the application grows, then  wait times might also grow to unsatisfactory  figures.

In order to bring this concept into existence, we have implemented an intelligent  client side communication model  which   is describe in detail in the next section.

Client side Components

The client side is composed of a communication model, a socket interface, and employs components from implemented reusable libraries.

The Communication Model

The implemented communication model employs a  similar, though not identical,  strategy  to  that employed by Hierarchical classification problem solvers. Hierarchical classification(HC) is a problem solving method identified by Chandrasekran for  solving diagnostic types of problems as part of his Generic Task approach to expert system development. In HC, knowledge is  represented as hypotheses hierarchically organized in a tree structure such that general hypothesis are always above more specific ones in the tree. Using a control strategy known as establish and refine, hypothesis are explored  top down. If a hypothesis at the top level  succeeds (establishes), its  immediate  descendants  are  required    to  establish  themselves one by one. This process of attempting to establish the descendants is referred to as "refining" the parent hypothesis. If, on the other hand, a hypothesis fails, then it is said to be ruled out and so are all the hypothesis beneath it in the tree[1]. In our model, knowledge components for which input is desired, are also organized in a hierarchical fashion. The main difference however, is  that no actual problem solving takes place. The evaluation of the tree nodes in this case, only serves to intelligently deduce the next observations for which to ask the user. The process of building  this hierarchy is a fairly simple one given that dependencies and relations between data input items, are known.

Re-Usable Libraries

In order to generalize development using this approach,  a library that supports  hierarchical classification was implemented in Java. In this library   a HC engine,  node definitions and operations were supplied.  In order to build specific applications, the user only has to extend the HC class,  and define nodes in which variables are object instances declared using  another reusable Interface  library.

The interface library was built so as to include a set  of reusable interface components where all error handling and presentation details are concealed from the user.  Implemented types include support for  Boolean, single selection lists, multiple selection lists, strings, integer, real, and date variables. The library is very generic and is extensible. Using this library all a programmer has to do is to declare a variable object using any of these classes.  When a value is needed, a simple method getValue() is invoked upon that object, a dialog requesting the value of that variable is presented to the user and later returned to the caller.

The client socket component

The client socket in conjunction with the server socket,  acts as a communication interface between the Java client front end, and the prolog-based application. The client socket is implemented  as a reusable Java Class. Each time the client front end  needs to communicate with the prolog application, it creates an instance of this component giving it both the host name of the prolog application and the host number on which the server socket  resides. Since the front end is usually implemented as a Java applet, for the purpose of generality, host information is usually passed to it  as parameters from its  initiating HTML page.

The client socket provides two primary methods to handle I/O between the  client and the server. The first of these (void out(String outString))  is a method for writing a string  on the TCP stream connection between the client and the server, while the second (String in()) is a method for reading  from that same stream. Using these two simple methods, sufficient bases for communication between the client and the server, are established.



public ClientSocket(String host, int port) {
        try {
            m_Socket = new Socket(host, port);
            m_os =new PrintStream(m_Socket.getOutputStream()); //get output stream
            m_is =new DataInputStream(m_Socket.getInputStream());//get input stream
        }
        catch (UnknownHostException e) {
                System.err.println("Don't know about host: " + host);
        }
        catch (IOException e) {
                System.err.println("Couldn't get I/O for the connection to: " + host);
        }
}



Figure 3: Code responsible for socket creation and initiation

Server Side Components

The server side consists of an application component  which  itself  could be composed of a number of components,  and a server socket. .
The server socket component
This component is simple.  It is linked with the server application code. The server application is responsible for its initialization. Its functions are:
The service is achieved by  passing Prolog terms sent by the client to the server application through a call to the procedureapplication_handle/2.  Consequently, the server application must define the procedure application_handle/2 so that it never fails and returns with the term that will be sent to the client.  The server socket component code is shown in figure 4.

It should be remarked that the success of this architecture depends on the efficiency of the server application performance. The shorter the time needed to process the client request, the better the behavior of the application on the Internet.

Image search application

The objective behind the development  of this application is two fold. The first is to aid a remote Internet client in searching for the images that best matches his input observations[CuIS97]. The second is to cooperate with an expert system explanation agent .  As described by our general architecture, the application is composed of two parts: a static server component and a client component. Figure 5 shows a simplified diagram of interactions between the application components.

The static server component

The static server application was implemented using SICStus prolog[2]. It, consists of a  reusable search engine, and a domain specific  image  database mapping observations to  images (figure 5). The input to the search engine is a list of observations and the output is a list of image-file structures. Each image-file structure consists of a file name and the actual observations associated with the image in the file. The database is constructed though the use of two predicates: finding/4 and image/2.

The database predicates take the following pattern: The input list defined by the aaplication protocol  takes the following form:
 [attribute1 op value1, attribute2 op value2, ....]
where <op> is among  = ,  > ,  < ,  >= , or  =<.

The output is a string of the following form: OR where <attribute><op><value>, ... are those belonging to the image.

start_server(Port, QueueLength) :-
        socket('AF_INET', Socket),
        socket_bind(Socket, 'AF_INET'(localhost, Port)),
        socket_listen(Socket, QueueLength),
        loop(Socket).

loop(Socket) :-
        socket_accept(Socket, Client, Stream),
        on_exception(RE, get_request(Stream, Request), h1(Stream,Client,RE)),
        on_exception(PE, process(Request, Stream, Client), h1(Stream, Client, PE)),
        loop(Socket).

get_request(Stream, Request):-
        read(Stream, Request).

process(bye, Stream, _Client) :-
        close(Stream).
process(Request, Stream, Client) :-
        on_exception(E, user:application_handle(Request,Result), h2(Stream, no, E)),
        return(Stream,Result),
        on_exception(RE, get_request(Stream, Request1), h1(Stream,Client,RE)),
        on_exception(PE, process(Request1, Stream, Client), h1(Stream, Client, PE)).

return(Stream,Result) :-
        nonvar(Result), !,
        format(Stream, "~w~n", [Result]),
        flush_output(Stream).
return(_, _).

h1(Stream, C, E) :-
        format(Stream, "error~n",[]),
        format(user_output, "Client: ~w~nError: ~w",[C, E]).

h2(Stream, Ack, E) :-
        format(Stream, "~w~n",[Ack]),
        format(user_output, "Application Error: ~w~n",[E]).



Figure 4: Prolog code of the server socket component
 
 

Figure 5: A simplified diagram of the image fetching   process.


get_image(List, Output) :-
        check_syntax(List), !,
        findall(File, (list_to_key(List, Fs),   image_file(Fs, File)), Files1),
        (       Files1 = [] ->
                (       list_to_key(List, Fs) ->
                        length(Fs, Len),                        % Collect all subsets
                        findall(I-SubL,(sublist(SubL, Fs), length(SubL, SLen),
                                 SLen > 0, SLen < Len, I is 1000 // SLen), SubLs),
                        (       SubLs = [] ->   % Singlton and fail to get an image
                                Output = 'e:No image file found'
                        ;       keysort(SubLs, SubLs1),                 % try maximum
                                SubLs1 = [I-SubFs|Rest],                % get first subset
                                best_image_file(Rest,I,SubFs,[], Files2),
                                (       Files2 = [] -> Output = 'e:No image file found'
                                ;       format_output(Files2, Output)
                                )
                        )
                ;Output='e:Some input observation(s) is/are not defined'
                )
        ;       format_output(Files1, Output)
        ).
get_image(_List, O) :-
O='e:The input is not a valid list ([a op v,...] or op is not defined.)'.


best_image_file([], _, SubFs, Files1, Files) :- % Handle input of two observations
        findall(File, image_file(SubFs, File), Files2),
        (Files2 \== [] -> append(Files2, Files1, Files) ; Files = Files1).
best_image_file([I-Fs|Rest], I1, SubFs, Files1, Files) :- % Collect same weight images
        findall(File, image_file(SubFs, File), Files2), Files2 \== [], !,
        append(Files2, Files1, Files3),
        (I = I1 -> best_image_file(Rest, I, Fs, Files3, Files) ; Files = Files3).
best_image_file([I-Fs|Rest], I1, _, Files1, Files) :-           % Keep on looping
        (       Files1 = [] -> best_image_file(Rest, I, Fs, Files1, Files)
        ;       I = I1      ->  best_image_file(Rest, I, Fs, Files1, Files)
        ;       Files = Files1
        ).

. . . .
. . . .
. . . .



Figure 6: The Core of Prolog Image search engine 

The client component

The client component is composed of an applet which includes a set of observations,  a HC component where the observations are distributed over nodes,  a parser, and a simple GUI. Upon  opening the page that contains the applet,   the applet is downloaded and the control  interface appears. Using this GUI, a user may initiate an image search.  A series of question dialogs then start to appear. The ordering of the appearance of the dialogs is controlled by the answers of the user to the presented questions through the HC component. This process,  constitutes the data collection phase. After this phase is completed, a string representing the aggregate of the inputs is prepared  and passed to  a new instance of  the client socket which establishes a link with the server and uses it to send the string to the prolog search engine residing on the server. After the search engine has processed the input, the client  socket reads the output which represents the file names with  observations that best match the user’s inputs, and the exact observations associated with each, and passes it to the applet.  The client socket then terminates its connection with the server and dies. The client processes the output through the parser, and then presents a list of all image names to the user in a list. Upon selecting an image to view, the client fetches the file using the URL passed to  it by the server, and uses the observations requested   by the user and the actual observations associated with the image to determine matching and mismatching  features. The image is then presented to the user along with the match information.

Expert system application

This application is a toy expert system for diagnosing car faults[CaES97]. The server application is built in SICStus Prolog[2]. It consists of the application knowledge base and a library of general problem solving methods .  The details of the problem solving library are out of scope of this article. Actual expert systems that have already been  developed at the Central laboratory for agricultural expert systems are currently being ported to the proposed architecture.

In the car fault application, the knowledge base consists of nodes for a hierarchical classification generic task and a global database object. The latter represents a blackboard which is used by the reasoning task. The nodes are depicted in figure 7.

 

Figure 7: Nodes of HC for the car fault expert system 

The input the to the expert system is a set of observations and the output is the diagnosis and advice. Inputs to the expert system are collected via client applet and sent to the server application in a similar fashion to that of the image application.  However, the applet GUI  different than that of the image search applet in that it provides a text box where the diagnosis and advice of the expert system appear.

Conclusion and future work

Through the architecture introduced in this paper,  many applications developed in prolog could be easily  ported to the Internet.  The prolog socket component and the Java libraries are reusable without any modification.  An application builder only needs to define relations between data input items using the communication model presented and adapt the prolog application for batch interaction with the client component.

The implementation of work presented here could be greatly simplified through development automation. For that purpose, a number of tools have been implemented  to support this work and its consistency across the client and server components. However,  discussion of  these tools, is beyond  the scope of this paper.

 Future work will focus on enhancing the image tool by using  a static  databases to replace   the prolog database. It will also implement protocol standardization through support of  KQML based message exchange. A number of existing prolog based expert systems are currently being ported to this architecture.

References

  1. El-Beltagy, S., Rafea, A. Kamel, A., Sticklen, J., Schulthess, U., Ward, R. (1995). "An Expert System For Wheat Disorders Diagnosis And Treatment Using A Hierarchical Classification Problem Solver". 2ND IFAC/IFIP/EurAgEng Workshop on Artificial Intelligence in Agriculture, Wageningen,  Netherlands, Pergamon.
  2. SICS Programming Systems Group. SICStus Prolog User's Manual. Swedish Institute of     Computer Science, June 1995.
  3. Szeredi, P., Molnár, K., Scott R. "Serving Multiple HTML Clients from a Prolog Application", Proceedings of the 1st Workshop on Logic Programming Tools for INTERNET Applications , Bonn, Germany, 1996.

Internet References

[ActX97] Activex.com
 URL: http://www.activex.com/ 

[BuPlg97] Building a Plug-in from the ground   up
 URL: http://home.netscape.com/misc/developer/conference/proceedings/ci5/index.html 

[CaES97] Car Fault Expert System
 URL: http://tomato.claes.sci.eg/carFault/ 

[CuIS97] Cuptex Image Server
 URL: http://tomato.claes.sci.eg/cuptexImgs/ 

[Java97] The Java home page.
 URL: http://java.sun.com 

[SiNP97] SICStus Prolog Netscape Plugin
 URL: http://potato.claes.sci.eg/claes/plugin/npsp.html