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:

More information about how partial deduction is controlled can be found in:


TUTORIAL

There are three ways in which the user can input some source code to ECCE:

  1. choosing a file from disk, and loading it, or
  2. selecting a pre-loaded working example from the right-hand drop menu, or
  3. pasting straight into the source textarea.
The source code must be a pure Prolog program, which can contain built-ins, and this is going to be used as input to the specialiser.

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 ).

The Control Settings

The control settings influence the global control (the control of polyvariance, i.e., how many specialised predicates are generated) and local control (the unfolding or inlining, i.e., how much does the specialiser pre-compute) of the specialiser.
  1. Default Conjunctive: This uses conjunctive partial deduction (i.e., multiple calls can be specialised in conjunction; in other words a single specialised predicate can represent a conjunction of calls) with the default control settings. The local control is not very aggressive, it basically uses determinacy with a lookahead of 1. For global control characteristic trees are used.
  2. Default Fast: this is a less aggressive version of the above. Use it if the above setting times out or gives you too big a specialised program.
  3. Classic: This uses classical partial deduction (i.e., only a single call can be specialised at a time; there are no conjunctions at the global control level) with the default settings for this. The unfolding is more aggressive than for default conjunctive; the global control uses characteristic trees.
  4. Mixtus: This uses classical partial deduction, but tries to mimic the control employed by the Mixtus specialiser (but it is not a 100 percent faithful emulation).
  5. Classic-Fast: this is a less aggressive version of the classic setting above. Use it if the classic setting times out or gives you too big a specialised program.
  6. Minimal: this is a very conservative classical partial deduction: it uses determinate unfolding but is very conservative as far as the generalisation is concerned (will generalize if a new specialized predicate is not more general than all the preceding ones).
  7. Termination: this is a version of Classic which ensures that termination characteristics are not changed (not yet fully tested; please report if termination characteristics are changed). Useful if you want to use Ecce as a pre-processor for a termination analyser. Be sure to leave the post-processor options as off or default.

The Post Processing Settings

The control settings influence the post processor.
  1. Max: All post-processing is turned on: determinate post-unfolding, RAF+FAR redundant argument filtering, dead code elimination, removal of duplicate calls, polyvariance minimization, Most Specific Version computation,...
  2. Default: The same as above, but the Most Specific Version computation is turned off.
  3. Off: All post-processing is turned off.

The Specialisation Tree

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.