
This describes the July-1993 code in directory /home/kaml1/usr3/sr/cdrummon/stak/newCode
for defining, abstracting and searching a graph (state space).

Outline:
1. System Overview

2. How to load the software

3. How to use the software once loaded

4. How to create your own search space (to be used as above)

==========================================================================

1.  System Overview
--------------------------------------
The original software was based on the notion of various forms
of abstraction and search based on properties of the underlying
graph. To define the particular methods a preprocessor took 
source files and produced sml files implementing one particular
form. 

The basic forms  are:

    do no abstraction
    do some abstraction     (ABS)

    specify search endpoints (start,goal) as individual states
    search endpoints are specified by predicates         (PRED)

    refinement strictly follows the abstract plan
    refinement is opportunistic                    ( OP )

    refinement does not assume classes are strongly-connected
    refinement assumes classes are strongly-connected          ( SC )

In the modifcations in this directory the search methods have been combined,
with the exception of the use of predicates, into a single collection of sml
modules. This allowed the comparison of the speed of the different methods.
In addition, multiple abstraction methods have
been defined which can be used in conjunction to form a single abstraction
hierarchy. Thus to use the software it is necessary to select both an
abstraction and a search strategy.



--------------------------------------------------------------------------

2. How to load the software
---------------------------

There are 3 steps in loading the software:

  (i)   start sml

          sml <CR>

  (ii)  load in all the stuff needed to define your graph

          use "load-1.sml" ;

  (iii) load in the definition your graph

          use "the file that contains your graph definition" ;
          structure ThePuzzle = the name of the structure defining your graph ;
          (i.e. example-nim.sml)

  (iv) load in the stuff that transforms your structure into a searching function

          USE load2 ;    (**** note, it's "USE" not "use" *****)




--------------------------------------------------------------------------
3. How to use the software once loaded

After you've loaded the software, there will be in your environment a function
called "mkProblem". The "method" argument indicates the method of abstraction and
is of type absSelect shown below

datatype starType  = SsM | SpM | SpsM | SsR | SpR | SpsR |  SDd 
     and absSelect  = T | \ of (starType * int) | P | Pc | N | NA | A
		    | Wad | Wau | \\ of (absSelect * absSelect)

There are various types of Star, Tree and Pair abstractions indicated by
starting with a upper case letter S, T and P respectively. Star abstractions
combine a node with its neighbours and their neighbours to a depth 
specified by the associated integer.  The neighbours are either just the successor
nodes (Ss), just the predecessor nodes (Sp) or the successor and predecessor nodes (Sps).
There are other variants described more fully in "abs-generator-stars.sml". Trees combine
a node with all its neigbours that have only one input arc. Pairs combine two
neighbouring nodes. No orphans (N) combines all single nodes with a neigbour.
To form the selector these are combined:

e.g.  A\\T\\SpsM\0\\N 

This example means construct an abstraction hiearchy where the preferred direction of search 
alternates by first forming abstractions based on trees. Then abstract all remaining
nodes according to the star method, using both predecessors and successors, the 0
indicating only the immediate neighbours are used. If not all the nodes are combined
into classes combine those on their own with the class of the first neighbour.
Unfortunately not all combinations are legal or useful. Wad and Wau are for
no abstraction and are by themselves. Otherwise the first characters should be A
indicating an alternating preferred direction of search or NA indicating a non-
alternating direction. (Most but not all illegal types are trapped with the
exception bad_abstraction_method.)

e.g.  	val gl = mkProblem (A\\T\\SpsM\0\\N)   PUZZLE_PARAMETER  ; 

Using mkProblem with such an argument returns a record consisting of
encode and decode functions plus the graphical hierarchy used. This record
can be passed to a function called runTrial which will assign a 
random start state and goal state and return a couple consisting of the graph
and a test function. Before running the test function the type of search must
be selected. There are four options, alternating opportunism AO, path opportunism
PO, no opportunism NO and no abstraction NAB selected in the following manner :

setSearchType Wm  PO;

The test function takes an integer argument defining
the number of times the test is repeated for the same start and goal. It returns
a tuple like the following

(12,0.5,0.01,0.0,0.7,[274,279,9],562)

(path length,user time,_,_,_,edges traversed at each abstract level,
 total edges traversed).

 The times are the total for  the number of trials. The path length are
 for one test (this is always the same as the process is deterministic).
 Aternatively multiple trials can be run with different start and gaol
 nodes by using function "total" which takes an integer argument for
 the number of different pairs and retruns the total for the user time
 and the number of edges traversed


--------------------------------------------------------------------------
4. How to create your own search space (to be used as above)

Your search space definition must be a structure with signature GENERIC_PUZZLE.
The simplest possible structure of this kind is exemplified by the 5-puzzle
definition (in the file "example-5puzzle.sml).

According to the GENERIC_PUZZLE signature you must define the following things:

external_state -- this type specifies how you, the user, wish to "see" the states
                  (for example, when you supply the start and goal states to fp)
internal_state -- this types specifies how the states will be represented
                  internally.  This should be the same as external_state unless
                  you want to try and minimize the costs of storing and
                  computing with the search space.
sameState      -- takes a pair of internal_state values as input and returns
                  true if they represent the "same" state.  Usually this is
                  the built-in equality function, but you might use a
                  representation that required some other equality function
                  (e.g. set equality).
hashState      -- any function that maps internal_state to integer (preferably
                  with not too many collisions!).  It is used internally to
                  define a mapping from states to nodes in the graph.
puzzle_parameter --
                  Most puzzle definitions actually define a parameterized family
                  of puzzles, with each different value of the parameter giving
                  rise to a different instance of the family.  For example,
                  the Towers of Hanoi is a family of puzzles, parameterized by
                  the number of disks (see the file "example-hanoi.sml").
                  The type of the family's parameter (which may, of course, be a
                  tuple containing several "parameters") is "puzzle_parameter".
                       The 5-puzzle is an example of a structure that defines
                  a specific puzzle, not a parametrized family.  In this case,
                  puzzle_parameter must still be specified in order
                  for the type-checking to succeed (I used unit).
mkInstance -- is a function that takes a specific value of type "puzzle-parameter"
              and creates the instance of your puzzle family corresponding to
              that parameter value.  In particular, mkInstance returns a
              labelled record with these four things in it:

      encode, decode -- functions that translate between types external_state
                        and internal_state.
      successor      -- maps a state (internal_state) to the list of states
                        that are its successors in state-space.
      initialStates  -- The state-space is constructed by computing the closure
                        of "successor" over this list of states.  These are the
                        initial states in the space-construction process, they
                        are not the initial states in the SEARCH process (they
                        have nothing whatsoever to do with the search process).

randomPath () -- is a function that returns a random pair of start and goal
                 external states, used for testing. (see "example-nim.sml")

Once you've got these defined, you're ready to load it and use it in the
way described in sections 2 and 3.

