SATPLAN USERS GUIDE Henry Kautz and Bart Selman AT&T Research June 3, 1996 I. Introduction Satplan is a planning system that works by converting planning problems into propositional satisfiability, and then solving those instances using general satisfiability algorithms. Although the program is targeted for planning, it can be easily adapted to generate and solve encodings of other kinds of combinatorial problems. The system consists of three basic parts: "satplan" generates a cnf encoding; "solve" tries to find a satisfying truth assignment for the instance; "interpret" prints the satisfying truth-assignment in an understandable form For example, suppose the file "bw_orig.ops" contains a set of operators for the blocks world, and "anomaly.facts" contains a problem specification for the well-known Sussman anomaly. Then the follow series of commands generates a cnf encoding of the anomaly, solves it, and prints the result: satplan -o bw_orig -f anomaly solve anomaly -s t interpret anomaly A copy of the interpretation is also saved in the file "anomaly.interp". The fastest way to get started is to try the examples in the examples/ directory of the distribution. Below we describe each of the three programs in detail, and then describe the format of operator and facts files. II. Installation See the file system/README.install for information on installing the system. Note that the instructions for installation include setting an environmental variable SATPLAN to the directory containing the system. III. Satplan Satplan is invoked as follows: satplan -o OPERATORS -f FACTS -t STEPS where OPERATORS is a file containing axioms specific to a planning domain. This filename must end with the extension ".ops" (which may be omitted on the command line: "-o foo" is the same as "-o foo.ops"). The OPERATORS file may appear in either the current working directory or in $SATPLAN/lib. FACTS is a file containing the specification (initial and goal state) of the particular plannning instance. This filename must end with the extension ".facts" (which may be omitted on the command line: "-f foo" is the same as "-o foo.facts"). The FACTS file must appear in the current working directory. STEPS is an integer, giving the maximum time step in the plan. Times thus range from 0 up to STEPS. For domains where all actions are sequential (e.g. the blocks world), STEPS is the same as the number of actions in the solution. For domains where actions can be performed in parallel (e.g. the logistics domain), STEPS is the amount of time needed to perform the plan assuming maximum parallelization. If STEPS is not given on the command line, then the default value specified in the FACTS file is used. The size of the encoded problem instance grows rapidly with STEPS, so you want to keep it as small as possible. Whether or not a solution exits to a problem when STEPS is set too large depends upon whether the particular domain axioms allow "null" actions to pad out the solution. The logistics.ops axioms in effect allow null actions; the bw_orig.ops axioms do not. (It is not difficult, however, to devise versions of the blocks world axioms that do allow null actions.) When Satplan runs, it generates two files: FACTS.cnf - contains the problem as an propositional satisfiability problem. The format of the file is: 1. Lines beginning with "c" are comments - must appear first. 2. A line of the form p cnf N M where N is the number of variables and M is the number of clauses. 3. A series of clauses, one per line, of the form N1 N2 N3 ... 0 where each number Ni stands for a proposition, negated to mean "NOT", and ending with a 0. The comments in the file specify when the wff was generated, what axioms were used, and other helpful information. FACTS.map - contains the information used by interpret (see below) to reconstruct the solution in terms of named literals (e.g. "on(A,B,3)") instead of numbered propositions. Satplan works as follows: 1. OPERATORS.ops and FACTS.facts are combined with header files kept in SATPLAN/lib to creat a C program. This program is compiled and executed. 2. Execution of this program generates a formula using ground, instantiated literals. 3. The literal version of the formula is turned into one made up of numbered propositions. 4. The formula is simplified by unit propagation, subsumption, and deletion of unit clauses. IV. Solve The program "solve" provides a uniform interface to different satisfiability testing programs, currently walksat, tableau, and ntab. It's basic use is: solve FILE.cnf -solver K {-out SOLNFILE } { solver specific options } where FILE.cnf is created by satplan; the .cnf extension may be omitted ("FILE" is the same as "FILE.cnf"). If the -solver option is given but FILE.cnf is not, then the wff is read from stdin. K is one of t (for tableau), n (for ntab), or w (for walksat). SOLNFILE is the name of file where the solution is saved, along with comments that record the exact parameters used by the solver. If this option is not specified but FILE.cnf is, then the solution is saved in FILE.out. If the -solver option is not given on the command line, then solve prompts the user for missing options. Type "solve -help" to see the full list of options. When solve runs, it prints tracing information to the screen and saves the trace, solution, and comments in the file FILE.out (or in the file specified by the -out option). FILE.out also contains comments specifying the date and the exact options used for the solver. Note that the actual truth-assignment found is saved in FILE.out, but is not printed to the screen. If a solver is specified on the command line but no FILE.cnf is given, then solve reads from STDIN and writes to the screen; a solution file is created only if an explicit -out option is included. The following are exactly equivalent: solve -solver t foo.cnf solve -solver t -out foo.out < foo.cnf The following is "almost" equivalent; however, in this case foo.out does not include the solution itself, nor the header comments that are used by the "interpret" program discussed below: solve -solver t < foo.cnf > foo.out A note on Walksat: the Walksat solver is randomized algorithm. The default option is for walksat to exit as soon as solution is found. To gather good timing statistics, however, you may want to solve the problem instance many times. To do this, use the "-m" option: solve foo.cnf -solver w -tries 100 -m performs exactly 100 tries (restarts), no matter how many tries (if any) ends in a solution. On the other hand, solve foo.cnf -solver w -tries 100 performs AT MOST 100 tries, but terminates as soon as a solution is found. For more information on options to walksat, type solve -solver w -help V. Interpret Interpret takes a solution file in the FILE.out format and pretty prints it. Both the FILE.out and the corresponding FILE.map file must be in the current working directory. To invoke it simply type interpret FILE.out where the ".out" extension is optional. IMPORTANT: if .out extension is omitted, as in interpret FILE then Interpret will try to simply read FILE, and only if it does not exist, will it look for FILE.out. The pretty-printed solution is sent to both the screen and to the file FILE.interp. If no file is specified on the command line, then the interpretation is sent only to STDOUT. Thus interpret < foo.out > foo.interp interpret foo.out are equivalent. Interpret determines the name of the map file to use from the comments embedded in the .out file, rather than from the name of the .out-type file. The name of the .interp file IS based on name of the .out-type file. Thus, the following sequence: satplan -o bw_orig -f anomaly solve -solver t anomaly -out tableau_soln solve -solver w anomaly -out walksat_soln interpret tableau_soln interpret walksat_soln correctly creates the following files: tableau_soln.interp walksat_soln.interp This feature makes it easier to keep around multiple versions of solution files to a single problem. VI. The OPERATOR and FACTS file Now we come to the trickiest part of the Satplan system, the OPERATOR and FACTS file formats. If you examine some example files, you will see that both are fragments of code in the C programming language. By compiling an operator and facts file together with $SATPLAN/instantiate.c $SATPLAN/instantiate.h Satplan creates an program whose execution instantiates a set of axiom schemas over a specified domain. The two "instantiate" files contain general type definitions, macros, and utility functions. The FACTS file typically contains some global data structures, used to specify the initial and goal states. Most of the work is done in the OPERATORS file. This file contains a "main" function that calls a series of functions, the execution of each of which generates a set of clauses. Consider the file bw_orig.ops. It begins with external declarations for the variable "goal", which is the maximum time step; the "init" and "final" STATES; and two DOMAINS of objects, one called "block" and the other called "fixed". All these variables are given values in a particular .facts file (e.g., anomaly.facts). #include "instantiate.h" extern int goal; extern STATE init; extern STATE final; extern DOMAIN block; extern DOMAIN fixed; The "main" function (re)sets the value of the goal variable (if a -t option is specified when satplan is invoked), and calls functions, defined in that same file, to generate general axioms for moving blocks, and about the predicate "on": int main(int argc, char *argv[]) { if (argc > 1){ if (sscanf(argv[1], " %d", &goal)!=1) error("Must supply number of goal step on command line"); } blocks_axioms(); on_axioms(); Finally, the main function calls the function complete_state (also defined in this file) that generates clauses describing the initial and final states, using the values for the corresponding STATE variables defined in whatever .facts file is linked in. complete_state(init, 0); complete_state(final, goal); end_wff(); return 0; } Look now at anomaly.facts. Here we see domain entities are simply represented by strings. A DOMAIN is a null-terminated array of strings. The default value for the goal is timestep 3: DOMAIN block = { "A", "B", "C", "TABLE", NULL }; DOMAIN fixed = { "TABLE", NULL }; int goal = 3; STATES are again simply null-terminated arrays of strings. The exact interpretation of a STATE depends on the particular functions called in the .ops file (here, the function "complete_state" is called). STATE init = { "A", "B", "B", "TABLE", "C", "TABLE", NULL }; For these blocks axioms, a STATE is assumed to be an exhaustive list of pairs, where the first element of each pair on "on" the second element. In other domains (such as logistics.ops), STATES have a different interpretation. (See specific comments on the domains below.) Finally, let us turn to the functions that actually generate the axioms. Consider the function blocks_axioms. It begins as follows: void blocks_axioms() { int i; for (i=0; i