/*********************** Graphplan ************************************** (C) Copyright 1995 Avrim Blum and Merrick Furst All rights reserved. Use of this software is permitted for non-commercial research purposes, and it may be copied only for that use. All copies must include this copyright message. This software is made available AS IS, and neither the authors nor CMU make any warranty about the software or its performance. *************************************************************************/ #include "graphplan.h" #include /* The code consists of the following main parts. 1. Reading in the operator and fact files. Note: we take 3 formats. In the non-prodigy formats, everything up to first left paren is a comment. Note: there is no special understanding of "not"s: these are just viewed as another word. In the non-prodigy formats, "(del blah blah)" means to delete "(blah blah)". Note: the code is lex.yy.c and y.tab.{c,h} is only for reading prodigy-style files. 2. Creating the graph. The layered graph will have facts-at-time-1 as the first layer, then ops-at-time-1, then facts-at-time-2, etc. Each layer is stored in a hash table of vertex_s structures. These structures have a "name" field which is the key, and the hash functions return a pointer to the structure. (The reason for doing it this way is that sometimes we want to access a vertex by using its name.) The graph is created in a forward pass until all goals appear and none are listed as being mutually exclusive. Creating the graph involves the following main steps. A. Performing instantiations. The code for this part is a bit messy, but conceputally, it's just performing the task: given a list of facts and an operator, find all the ways in which that operator can be instantiated so that its preconditions are in that list. What is confusing is that we have two different ways of storing the names of things. One way is as a token list (easier for instantiations) and the other way is as a string with words connected by underscores (how they are stored in the graph). B. Calculating mutual exclusions. These propagate and will be used to speed up the later search. We will also use this to make the graph smaller (in particular, if an operator needs two facts that are mutually exclusive, then we don't put it in the graph.) Also, once the graph has "leveled off" (2 adjacent fact layers have the same number of facts and the same number of mutual exclusions) then all future layers will be the same. So, we can just copy and don't need to instantiate any more. 3. Doing the search. This is just a simple backward chaining, done level-by level to make most use of the exclusions. Unsolvable goal sets at a given time step are stored in a hash table so that we can fail more quickly next time. Most of the flags to the user have to do with this part of the planning. E.g., We can do a lowerbounding check based on the principle that if there are 10 goals no two of which can be made true in the same time step then we will need at least 10 steps. Or, we can check subsets of a current goal set to see if any of them has been stored in the unsolvable sets hash table. Right now, there are no operator-ordering or goal-ordering heuristics, except that NOOPs are always tried first. I.e., If there are several ways of making fact F true at time T, and one such way is to have F be true at time T-1, then that way is tried first. This seems to make plans look nicer. */ /* GLOBAL VARIABLES */ char junk[100]; fact_list the_types; /* list of all the different type decls */ fact_list initial_facts, the_goals; /* initial facts and goals */ hashtable_t *fact_table, *op_table; /* the arrays of hash tables */ hashtable_t useful; /* USED for "do_irrel": CHECK USEFUL FACTS. */ hashtable_t types_table; /* holds the types */ extern int hash_hits, hash_inserts; /* entries in plan hash table */ /* these are defaults */ int MAXNODES = 256; /* default MAX number of nodes at any given time step. */ int DEBUG_FLAG = 0, do_memo = 0, do_subsets=0, do_noexcl = 0, do_buildup = 0, do_greedy = 0; int oldstyle = 0; /* type of ops file being read in */ int do_irrel = 0, going_backwards = 0;/* use for finding irrelevant features */ int do_lower = 0; /* try to immediately prove a set is notpossibly doable */ int xviewing = 0; /* graphical animation */ int do_completeness = 1; /* do completeness check */ /* other flags, counters, etc. */ int same_as_prev_flag = 0; /* graph layer is same as previous time step */ int first_full_time, num_hashes[2] = {-1,0}; /* for checking completeness */ /* num_hashes[0] = previous count, and num_hashes[1] = current count */ extern int number_of_recursive_calls, number_of_actions_tried; int bvec_len = 1; /* max facts in a time step / 32 */ int num_goals; int instrs(void) { printf("command line args. Use any of: \n \ -h for this list \n \ -o to specify operator file\n \ -f to specify fact file\n \ -t to specify a fixed number of time steps\n \ -i to specify info level 1 or 2 (default is 0)\n \ -O