This directory contains STATIC 2.0, a static analyzer for the full
PRODIGY 2.0 language, which was designed and implemented by Oren Etzioni,
Julie Roomy, and Rob Spiger. (Copyright 1993 for STATIC 2.0 and
associated documentation is by Oren Etzioni)

The improvements over the original STATIC (AAAI '91) include:

1.  The new version handles the full Prodigy language (including
universal quantification, conditional effects, negation, and
disjunction). 

2.  The new version utilizes typing constraints on variables to
improve the static analysis.

3. Detailed documentation is available (see the ``design'' file in
this directory)



The STATIC 2.0 system is experimental software for research purposes
only.  The system is provided on an ``as is'' basis.  No warranty is
either expressed or implied.  Use at your own risk!

This software is made available under the following conditions:
1) STATIC 2.0 will only be used for internal, noncommercial research purposes.
2) The code will not be distributed to other sites.
3) Any bugs, bug fixes, or extensions will be forwarded to
etzioni@cs.washington.edu.


****************************************************************
The text that follows presupposes that you've read the following:

author="Etzioni, Oren",
title="Acquiring Search-Control Knowledge via Static Analysis",
year="1993",
Journal = "Artificial Intelligence",
note="To appear.  Also available as University of
Washington technical report 92-04-01.

To obtain a copy:
Do an anonymous ftp to june.cs.washington.edu
and cd into pub/etzioni/papers.
The paper is: aij-static.ps.Z

And also:
title="Prodigy 2.0: The Manual and Tutorial",
author="Minton, Steven and Knoblock, Craig A. and Kuokka, Daniel R.
and Gil, Yolanda and Joseph, Robert L. and Carbonell, Jaime G.",
institution="Carnegie Mellon University",
year="1989",
number="CMU-CS-89-146"

To obtain a copy of the manual (and of Prodigy 2.0!) send mail to
prodigy@cs.cmu.edu.


****************************************************************
TO RUN STATIC:

  To get static up and running, simply follow the instructions
  prefaced by >> in the left hand margin.


  To load the necessary files.  This includes both the prodigy
  and static files:

>>  (load "load.lisp")

  If this fails, then the standard paths for the load file are incorrect.
  create a private version of load.lisp and change one or more of the
  following:  PRODIGY-PATH, SIMPLIFY-PATH, ITERATE-PATH, LOCAL-PATH in 
  your private load.lisp file.


  First enter prodigy.

>>  (prodigy)

  Then select a domain.  Typing domain at the prodigy prompt will give you
  a list of the available domains at the current prodigy path.

>>  domain 

  Choose one of the domains.

>>  blocksworld

  Exit prodigy.

>>  quit

  Call static telling it to use default settings.

>>  (static t t t)

  If you leave out the arguments to static, static will prompt you 
  for various options.  Leaving out one of the arguments, allows 
  you to choose which root to expand.  Making the first argument be nil
  allows the user to choose to only perform certain steps of static.  The
  third argument should be t if the domain contains unsolvable problems, and
  false otherwise.


EXAMPLE RUN:


Allegro CL 4.1 [SPARC; R1] (4/3/92 15:41)
Copyright (C) 1985-1992, Franz Inc., Berkeley, CA, USA.  All Rights Reserved.
;   Loading /homes/rivers/etzioni/ai/emacs/standard.clinit.cl.
;     Libfasl loading /projects/ai/utils/defsystem.sfasl4.
;     Libfasl loading /projects/ai/cl4.1/installed/lib/code/loop.fasl.
.clinit.cl finished 
;; Optimization settings: safety 1, space 1, speed 1, debug 2
;; For a complete description of all compiler switches given the current
;; optimization settings evaluate (EXPLAIN-COMPILER-SETTINGS).

;; Starting socket daemon and emacs-lisp interface...
USER(1): (require 'prodigy)
; Loading /projects/ai/site/prodigy.system.
USER(2): (load "load.lisp")
; Loading /homes/rivers/etzioni/ai/static/new/load.lisp.
USER(3): (prodigy)


PRODIGY 2.11   (The Prodigy Project, September 25, 1990)
Mail questions and remarks to prodigy@CS.CMU.EDU


Welcome to   P R O D I G Y ...


Current Domain:   unspecified.
Current Problem:  unspecified.
Active Switches:  none.

Prodigy: domain "blocksworld"
; Loading /projects/ai/prodigy/domains/blocksworld/startup.lisp.


 problem "p24"
; Loading /homes/rivers/etzioni/prodigy/domains/blocksworld/probs/p24.lisp.


Prodigy: run


* * * * * P R O D I G Y 2.11 * * * * *

Goal State: (AND (HOLDING C) (CLEAR B))

CPU time: 0.5 seconds
Number of Nodes: 110
Solution Length: 3
Operator Sequence: 

      UNSTACK A B
      PUT-DOWN A
      PICK-UP C


Prodigy: quit

Type ``(prodigy)'' to begin another session.

BYE
USER(10): (time (static t t t))


Initializing static...
Preprocessing operators...
PICK-UP
PUT-DOWN
STACK
UNSTACK
Done preprocessing operators.

Done Initializing static.

CREATING PSGS



Finished creating PSGs.  
Finding variable types.
Done finding variable types.

LABELING PSGS



Finished labeling PSGs.  

Finding necessary effects of PSGS

Finished finding necessary effects of the PSGS.

FORMING PREFERENCE RULES FROM NECESSARY EFFECTS.

Formed 4 goal preference rules.
FORMING GOAL AND OPERATOR REJECTION RULES FROM NECESSARY EFFECTS.

FORMING FAILURE RULES

Learned 5 reject rules

FORMING PREFERENCE RULES

Learned 0 preference rules 

New Learned Rule: R3-PREFER-ON-TABLE-OVER-ON-USING-OP-ANY
New Learned Rule: R4-PREFER-ON-TABLE-OVER-HOLDING-USING-OP-ANY
New Learned Rule: R5-PREFER-ON-OVER-ON-USING-OP-ANY
New Learned Rule: R6-PREFER-ON-OVER-HOLDING-USING-OP-ANY
New Learned Rule: R7
New Learned Rule: R8
New Learned Rule: R9
New Learned Rule: R10
New Learned Rule: R11
New Learned Rule: R12
New Learned Rule: R13
New Learned Rule: R2
New Learned Rule: R1
cpu time (non-gc) 7984 msec user, 1066 msec system
cpu time (gc)     3033 msec user, 567 msec system
cpu time (total)  11017 msec user, 1633 msec system
real time  12690 msec
space allocation:
 458213 cons cells, 188 symbols, 5538448 other bytes,
NIL
USER(11): (prodigy)


PRODIGY 2.11   (The Prodigy Project, September 25, 1990)
Mail questions and remarks to prodigy@CS.CMU.EDU


Welcome to   P R O D I G Y ...


Current Domain:   blocksworld.
Current Problem:  p24.
Active Switches:  none.

Prodigy: scr

  Available search control rules are:

    Select-First-Goal
    R13
    R12
    R1
    R2
    R11
    R10
    R9
    R8
    R7
    R6-Prefer-On-Over-Holding-Using-Op-Any
    R5-Prefer-On-Over-On-Using-Op-Any
    R4-Prefer-On-Table-Over-Holding-Using-Op-Any
    R3-Prefer-On-Table-Over-On-Using-Op-Any

  Type ``scrule <search-control-rule-name>'' to 
  view a specific search control rule.

Prodigy: run


* * * * * P R O D I G Y 2.11 * * * * *

Goal State: (AND (HOLDING C) (CLEAR B))

CPU time: 0.3 seconds
Number of Nodes: 41
Solution Length: 3
Operator Sequence: 

      UNSTACK A B
      PUT-DOWN A
      PICK-UP C


Prodigy:





ADDITIONAL INFORMATION / FEATURES:
----------------------------------
1)You can view the problem state graph(s) (PSG), anytime after they are created
  with the function:

>>  (browse)

  browse takes an optional argument which is the root of the psg you 
  wish to view.  Browse lets you view each node with all of its information,
  or shows a subtree with just the name and type of each node.


2)You can print all of the problem state graph, anytime after they are created
  with the function:

(Note:  It is helpful to do a 

 >> setenv PRINTER printer-name 

  in unix to send the PSGs to a postscript printer before running lisp.)

>> (print-psgs)

  This function assumes that the directory structure "trees/<domain>"
  already exists.  <domain> is the Prodigy name for the current domain.

  print-psgs can take the following optional arguments:
     name-of-printer 
     T/nil(representing whether or not to shrink the psg to fit on one page)
  The default arguments are:
     reads default printer from environment variable.
     nil(don't shrink to fit)

3)You can print a single PSG, anytime after it has been created with
  the function:

>> (print-psg <root-of-psg> <file-name>)

  Where root-of-psg is the node of the root of the problem state graph, and
  file-name is a path in which all of the directories are already created.
  There are several optional arguments see io/io.lisp for more information.


4)To feed the generated rules to prodigy use the function:

>> (feed-rules)

  Static automatically calls this function after generating rules
  from failure and success nodes.  If this function is called x times,
  the rules will be fed x times (ie, if called twice then there will be
  duplicates of all rules).

5)There are several ways to view the generated search control rules
  (see 6, 7, and 8 also).  To view all rules in their Prodigy format,
  use static to learn and feed failure/success rules, then call:

>> (show-rules)

    This displays the rules learned by Static and "loaded" in Prodigy
  with (feed-rules) (feed-rules is implicitly called by Static).  
    Just because the rules are currently loaded does not mean that
  prodigy will "see" them even if prodigy's global variables are correctly
  set.  To be safe it's best to write the rules out to a file, and then
  read them back in. 
    (show-rules) can also be called from within Prodigy.


6)To show all of the rules currently "loaded" in Prodigy use the function:

>>  (show-currently-loaded-rules)

    Just because the rules are currently loaded does not mean that
  prodigy will "see" them even if prodigy's global variables are correctly
  set.  To be safe it's best to write the rules out to a file, and then
  read them back in. 
    (show-currently-loaded-rules) will includes generated rules as well 
  as any rules which existed previous to running Static.


7)An alternate way to view the control rules generated by static
  is to look at the global variables which store the generated rules.

	*all-frules*	- all the op rejection rules ever learned
	*frules*	- the op rejection rules kept
	*brules*	- the bindings selection rules
	*srules*	- op preference rules learned from "success"
	*node-rules*	- node rejection rules
	*op-pv-rules*	- operator preference rules (base on protection
			  violation)
	*pv-rules*	- protection violation rules
	*op-gc-rules*	- operator preference rules (based on goal
			  clobbering)
	*gc-rules*	- goal clobbering rules
	*sole-op-frules* - op rejection rules generated from situations
			   in which only one operator applies (see design
			   for more information).
    *preferenc-rules* goal preference rules.

8) To view just the rejection rules in a convenient format.  

>> (format-rules)

  These rules do not have to be loaded.


9)To write the generated rules out to a file, use the function:

>>  (write-rules "filename")

  Where filename is a path, and all of the directories in the path
  already exist.


10)To read the rules from a file, use the function:

>>  (read-rules "filename")

  Where filename is a path to the file previously written to by 
  write-rules.


11)For a more comprehensive review of the algorithms and design issues
involved in the creation of static for the full prodigy language, see
"design" in the same directory as this file.  


12) To see documentation on STATIC's simplifier look in:
rob-simplify/rob-simplify.doc.

13) To store the necessary effects of each PSG use the function

>> (dribble-ne filename)

    which will store the necessary effects into a specified file.  It
    may be called after running static.

****************************************************************
-----------------------------------------
Trouble shooting and additional features:

TOO SLOW:
---------
 1)  Static's performance is greatly improved by adding specific domain
  information into its knowledge base.  Much of this information is
  intuitively obvious to humans, but not to static.  For example, 
  static needs to be told that, pickup(Robot, Robot) will never
  occur in the domain of stripsworld.
    Specific domain information already exists for the following domains
	blocksworld    mod-bw    schedworld    extended-strips
        kite-building


    In order to add specific information about other domains, modify the
  file "create/domain.lisp" in the static directory.
	1) First add an abbreviation of your new domain to read-domain()
	2) Next add one or more of the following:

	  A) non-goals -- These predicates will never be goals.
              Example: (last-scheduled)
              In the schedworld domain last-scheduled is a bookeeping
              predicate used to keep track of time.  It is used to
              generate choices and if it causes backtracking, the
              backtracking will not lead to a success path.
              Notes:
                Most bookeeping predicates can go in this list. 

	  B) non-gratis-list -- These predicates are always true.
	      Example: (is-object <X>)
	      In any interesting blocksworld domain there is at least
	      one block in all states (if there isn't no goals involving
              blocks can be achieved anyway).
	      Notes: 
                  Many static and non-static generators can go in this
                list.

	  C) bad-ops -- Used to specify to STATIC which operators are
being rejected by default control rules supplied with the domain.
Example: ((inroom robot <x>) carry-thru-dr push-thru-dr) In the
extended-strips domain.

	  D) invariant-list -- Facts that have to hold.
	       Example: (((exists <y>))
                         ((on-table <x>) (on <x> <y>) (holding <x>)))
               In the blocksworld a block is either on the table, on
               another block, or being held.
         
  	  "A problem-space definition, for Static, consists of a set of
	operators and a set of constraints on legal states.  The constraints
	rule out impossible states.  In the Blocksworld, for example, either
	(arm-empty) is true or the robot is holding some block.  static
	utilizes the constraints on legal states to terminate the
	expansion of the PSG at certain subgoal nodes.  The constraints are
	used to prove that, given the current goal stack, if the subgoal
	arises during actual problem solving it would invariably be matched by
	Prodigys current state.  For example, suppose that the literal 
	(arm-empty) is on the goal stack, and Prodigy subgoals on 
	(holding V).  We know that (arm-empty) is not true because it is 
	on the goal stack (i.e. Prodigy is trying to achieve it).  Therefore,
        the robot is holding SOME block and (holding V) will match the
	current state.
	   In general, we know that literals on the goal stack do not match 
	Prodigy's current state.  Thus, the goal stack provides some 
	information about the current state.  As in the above example, that
	information, in conjunction with the constraints on legal states, 
	is used by the function holds?(p,goal-stack(p)) to determine 
	whether p will be matched by Prodigy's current state, whenever it
	arises in the current goal context.   Constraints on legal states 
	in the Blocksworld appear in [create/domain.lisp].  Exactly one of 
	the literals in each constraint is true in every state.  Using the 
	constraints appropriately requires reasoning about whether the 
	variables at PSG nodes are potentially bound.  Suppose, for example,
	that (holding V) is on the goal stack and the current precondition 
	is (arm-empty).  Since V may be bound to a constant [block-1] during
	actual problem solving, the holding goal may not be satisfied,
	but (arm-empty) may still be false because the robot is holding
	yet another block [block-2]."  Therefore, although we cannot conclude
        that (arm-empty) holds, we can conclude at any level in the tree
        below (arm-empty) that (holding V) holds.

          E) false-list -- Facts that are always false.
               Example: (holding robot)
               In the extended-strips domain, this predicate would never
               occur in prodigy, but may occur in static's simulation.

          F) negation-list -- Predicate which negate each other.
               Example: (on <x> <y>) (on <y> <x>)
               In the blocksworld if a block x is on block y, then
               it is known that block y is NOT on block x.
               This information is used to detect goal interactions and
               used to simplify expressions.  We could potentially
compute this from the invariant-list, but we don't.

	  G) dont-expand-list -- Predicates which are too expensive to expand.
         This refers to STATIC's expansion.  Prodigy does not utlize
	    	this information.
	       Notes:
                 In very large domains, some predicates occur in the
               effects list of many operators.  In static where-ever these
               predicates occur they may generate a huge subtree.  
               Empirically many predicates in this category are 
               usually already true, so that in prodigy they don't 
               actually backtrack (corresponding to small or non-existent
               subtrees).  This list is a simple heuristic allowing the
               user to choose predicates not to expand.  The list is
               implemented in such a way that no matter what predicate
               is placed in this list the rules generated by static are 
               still correct.  However, some information is lost.

      H) rarely-unique-list -- Generators that rarely distinguish
               something as unique.  For example, the predicate object
               in the blocksworld, because there are usually
               many objects.  This will stop STATIC from generating 
               preference rules which are contingent on the fact there
               is only one object in the domain.

      I) typing-info-list -- Specifies typing information of various static
               predicates and constants.  This information is used when
               choosing operators to achieve goals.  The types of each
               variable in a goal are analyzed when picking operators to
               achieve the goal.  If the application of the operator would
               result in a typing conflict as specified in the typing-info-list
               the operator is rejected.  This can be very useful for domains
               with strong typing information because many operators can be rejected.


   GENERAL NOTES: 
      Probably the most important lists are the invariant-list and
    the negation-list.  Not only do these lists reduce the amount of time in
    which static runs, but also they help static create better rules.


     When initially starting with a huge domain, dont-expand-list, can
    be very useful.  Start by adding most of the predicates of the 
    domain to this list, then gradually remove different predicates and
    note the effect on the running time of static.

    --------------
 2)  If your domain is taking an inordinate amount of time.  You may wish
  to truncate static's analysis of the problem state graph(s).  You can
  change the maximum depth of the graph to x, by typing

>> (setq *limit* x)   ;; where x is an integer

  after loading "load.lisp".  Default maximum depth of the graph is 100
  ( 100 is very large ).  This will not change the correctness of the 
  rules generated, but some information may be lost.

****************************************************************

ACKNOWLEDGEMENTS: we have used code by Jonathan Amsterdam (the ITERATE
macro), Joe Bates (to draw PSGs) and by Craig Knoblock (in the STATIC
matcher), and by Steve Minton (in writing/reading the control rules
generated by STATIC).  Special thanks go to Steve Minton who wrote and
distributed Prodigy/EBL.  STATIC is based on an in-depth analysis of
Prodigy/EBL.
