ECCE is an automatic online program specialiser for pure Prolog programs
(with built-ins).
It takes a pure Prolog program and a query of interest and then specialises
the program for that particular query.
The research behind the ECCE system is described, amongst others, in the following
papers:
There are three ways in which the user can input some source code to ECCE:
There are five actions available for this input code: Specialisation, Slicing, Most Specific Version (MSV) bottom-up propagation, Redundant Argument Filtering (RAF), and inverse Redundant Argument Filtering (FAR).
In addition to these actions, the user can also perform some extra analysis given in the plug-ins section. Currently, there are two plug-ins incorporated to the tool: Regular Unary Logic (RUL) program analisys and RUL bottom-up analysis.
Actions and plug-ing that are not bottom-up, also require the user to type in a goal in the appropriate text box. These are: Specialisation, Slicing, RAF and RUL analyses.
The user can perform the partial evaluation, i.e. specialisation, of a given source program for a given goal. For instance, by partial evaluation of the following Prolog code (loaded as source, as explained before):
doubleapp(X,Y,Z,XYZ) :- append(X,Y,XY), append(XY,Z,XYZ). append([],L,L). append([H|X],Y,[H|Z]) :- append(X,Y,Z). rev([],X,X). rev([H|X],A,R) :- rev(X,[H|A],R). p :- q. q.using the following goal:
doubleapp(X,Y,Z,XYZ)should produce the following specialised code:
doubleapp(A,B,C,D) :-
doubleapp__1(A,B,C,D).
doubleapp__1([],A,B,C) :-
append__3(A,B,C).
doubleapp__1([A|B],C,D,[A|E]) :-
append_conj__2(B,C,D,E).
append_conj__2([],A,B,C) :-
append__3(A,B,C).
append_conj__2([A|B],C,D,[A|E]) :-
append_conj__2(B,C,D,E).
append__3([],A,A).
append__3([A|B],C,[A|D]) :-
append__3(B,C,D).
Some information about the specialisation process is also included in the header of the resulting file, such as parameters that were used and timing information.
The slicing algorithm of ECCE (described in Proceedings
ESOP'05, LNCS 3444:pp. 61-76.) operates in a similar way: program and goal are determined by the user and, as a result of clicking the Slice button, a sliced version of his original program is produced.
For instance, take the "advisor.pl" working example:
what_to_do_today( _today, _weather, _program ):-
kind_of_day( _today, _daykind ),
kind_of_weather( _weather, _weatherkind ),
proposal( _daykind, _weatherkind, _program ).
kind_of_day( monday, workday ).
kind_of_day( thuesday, workday ).
kind_of_day( wednesday, workday ).
kind_of_day( thursday, workday ).
kind_of_day( friday, workday ).
kind_of_day( saturday, weekend ).
kind_of_day( sunday, weekend ).
kind_of_day( eastern, feastday ).
kind_of_day( first_of_may, feastday ).
kind_of_day( christmas, feastday ).
kind_of_day( new_years_day, badday ).
kind_of_day( friday_the_13th, badday ).
kind_of_weather( sunny, nice ).
kind_of_weather( rainy, nasty ).
kind_of_weather( foggy, nasty ).
kind_of_weather( windy, nasty ).
proposal( workday, _, go_to_work ).
proposal( weekend, nice, go_out_to_the_nature ).
proposal( weekend, nice, visit_the_golf_club ).
proposal( weekend, nice, wash_your_car ).
proposal( weekend, nasty, go_out_to_the_town ).
proposal( weekend, nasty, visit_the_bridge_club ).
proposal( weekend, nasty, enjoy_yourself_at_home ).
proposal( weekend, _, it_is_fun_to_learn_Japanese ).
proposal( badday, _, you_had_better_stay_in_bed ).
proposal( feastday, _weather, _program ):-
proposal( weekend, _weather, _program ).
and slice it for the following goal:
what_to_do_today( first_of_may, W, P )
What you should get back is a program that looks like this:
what_to_do_today( _today, _weather, _program ):-
kind_of_day( _today, _daykind ),
kind_of_weather( _weather, _weatherkind ),
proposal( _daykind, _weatherkind, _program ).
%kind_of_day( monday, workday ).
%kind_of_day( thuesday, workday ).
%kind_of_day( wednesday, workday ).
%kind_of_day( thursday, workday ).
%kind_of_day( friday, workday ).
%kind_of_day( saturday, weekend ).
%kind_of_day( sunday, weekend ).
%kind_of_day( eastern, feastday ).
kind_of_day( first_of_may, feastday ).
%kind_of_day( christmas, feastday ).
%kind_of_day( new_years_day, badday ).
%kind_of_day( friday_the_13th, badday ).
%
kind_of_weather( sunny, nice ).
kind_of_weather( rainy, nasty ).
kind_of_weather( foggy, nasty ).
kind_of_weather( windy, nasty ).
%proposal( workday, _, go_to_work ).
proposal( weekend, nice, go_out_to_the_nature ).
proposal( weekend, nice, visit_the_golf_club ).
proposal( weekend, nice, wash_your_car ).
proposal( weekend, nasty, go_out_to_the_town ).
proposal( weekend, nasty, visit_the_bridge_club ).
proposal( weekend, nasty, enjoy_yourself_at_home ).
proposal( weekend, _, it_is_fun_to_learn_Japanese ).
%proposal( badday, _, you_had_better_stay_in_bed ).
proposal( feastday, _weather, _program ):-
proposal( weekend, _weather, _program ).
To view the Specialisation Tree you need an SVG Viewer.
Green edges labelled with unf(L,N) show the unfolding that has been done; where L is the literal number selected and N is the number of the clause resolved with.
Blue edges denote the descendency relationship at the global control level.
Solid rectangles containing an definition with a double equality are global tree nodes for which code has been generated.
Gray nodes are global tree nodes for which no code was generated, either because the node was abstracted or because it is an instance of another node.
Note: the tree is displayed before the post-processing is run, which may remove certain nodes, e.g., by determinate post-unfolding. Dashed gray edges show instance relationships in the global tree, while dashed red edges show were generalisation occurred.