Skip to content

planning

Christian Muise edited this page Apr 4, 2020 · 1 revision

Introduction

The sas library provides various methods for dealing with SAS+ planning problems. Most of the code is verbatim from Fast Downward (developed by Malte Helmert), but parts are augmented / documented for use as a stand-alone library.

Note: Some of the functionality listed here (as part of the krtoolkit) may not be found in the original SAS libraries. These have been added to enrich the functionality of the libraries found within the krtoolkit.


Parsing

There are three parsing methods so far that deal with files output from the PDDL->SAS+ translation process. All of the data structures that are returned are described below.

test.groups

This file contains information for translating the SAS+ formulation back to a human readable form (ie. the PDDL naming conventions). planning.sas.parseGroups provides a method of parsing such files:

from krrt.planning.sas import parseGroups
group_key = parseGroups('test.groups')

A GroupKey object is returned.

output.sas

This file contains the SAS+ encoding of the problem. More information / explanation about the contents can be found here. planning.sas.parseSAS provides a method of parsing such files:

from krrt.planning.sas import parseSAS
sas_task = parseSAS('output.sas', 'test.groups')

A SasTask object is returned.

Note: The test.groups file is required for this method as well.

output

This file contains additional SAS+ information of interest. More detailed information can be found here. Specifically the following three pieces can be parsed:

  • CG: The Causal Graph is a directed graph that captures the dependencies between variables in the SAS+ domain.
  • DTG: For each SAS+ variable, a Domain Transition Graph is constructed that indicate how the values of a SAS+ variable can be changed.
  • SG: Rarely used, the Successor Generator encodes a data structure that can be used for efficient calculation of applicable operators.

Each part has it's own parsing function, and all three can be parsed with the single parsePRE function:

from krrt.planning.sas import parseCG, parseDTG, parseSG, parsePRE

# Parse each individually
cg = parseCG('output')
dtgs = parseDTG('output')
sg = parseSG('output')

# Or parse them all at once
all_objects = parsePRE('output')
cg = all_objects['cg']
dtgs = all_objects['dtg']
sg = all_objects['sg']

The parseCG and parseSG functions return a CG and SG object respectively. The parseDTG function returns a list of DTGs (the index corresponding the the variable number). The parsePRE function returns a dict with keys as 'cs', 'dtg', and 'sg'. The values follow what each individual parsing function would generate.

Sometimes it is useful to have the planning task of the preprocessed form. Since it is structured different, extra care must be taken when parsing. The method to do this is to first convert the preprocessed SAS+ output, and then use the parseSAS function:

from krrt.planning.sas import convert_PRE, parseSAS

#--- First convert the output to trick the SAS+ parser
convert_PRE('output', 'output.pre')

#--- Next parse the sas task
task = parseSAS('output.pre', 'test.groups')

all.groups

This file contains information about all of the mutex relations that the translation phase discovers. Naturally this includes all of the variables in test.groups, but mutex relations are discovered and recorded. planning.sas.AllGroups provides the functionality for parsing this information:

from krrt.planning.sas import AllGroups
from krrt.planning.sas import parseSAS, convert_PRE

#--- Get a hold of the original and preprocessed tasks
convert_PRE('output', 'output.pre')
orig_task = parseSAS('output.sas', 'test.groups')
pre_task = parseSAS('output.pre', 'test.groups')

#--- Create the AllGroups object
all_groups = AllGroups('all.groups', orig_task, pre_task)

An AllGroups object is returned.

Note: Both the original translation and preprocessed SAS+ encodings are required due to the indexing convention used in the all.groups file.


SAS+ Data Structures

Groups

The GroupKey object has the following functionality:

group_key.dump() Display the group key in the same format as test.groups.
group_key[var] Return the group associated with variable name var.

A Group object contains information about a single SAS+ variable. It has the following functionality:

group.dump() Display information about the group as would be seen in test.groups.
group.varname The name of the SAS+ variable.
group.values A list of values the SAS+ variable can take on.
group[i] The i^th^ value that the SAS+ variable can take on.

To illustrate this, here is a snippet of code that reads in the test.groups file, and builds a dict with the variable name as a key and it's cardinality as the value.

from krrt.planning.sas import parseGroups

# Parse the test.groups
group_key = parseGroups('test.groups')

# Iterate over each group, and add the information
cardinalities = {}
for group in group_key:
    cardinalities[group.varname] = len(group.values)

# Print the result
print cardinalities

AllGroups

Currently, the AllGroups object is simply a wrapper around a list of MutexGroup objects.

all_groups.groups List of MutexGroup objects.

MutexGroup

A MutexGroup object currently houses a list of Proposition objects (from the preprocessed SAS+ encoding).

group.props List of Proposition objects representing a mutex relationship.

SAS Task

A SasTask object basically houses a number of items related to a SAS Planning Task. We describe each in detail here:

task.dump() Display information about the SAS planning task.
task.axioms Python list of Axiom objects.
task.variables List of Variable objects in the planning task.
task.operators List of Operator objects in the planning task.
task.goals List of Proposition objects that represent the goal.
task.initial_state List of Proposition objects that represent the initial state.
task.name Name of the SAS planning task.
task.lookupProp[var_no, val_no] Returns the Proposition object corresponding to the provided variable and value number (0-indexed).
task.lookupVarVal[prop] Returns a tuple (var_no, val_no) that corresponds to the provided Proposition object.
task.lookupVarID[name] Returns the variable id given a name.

Note: The last two items are custom to the krtoolkit version of a SAS task object.

Axiom

Coming soon...

Proposition

A Proposition object contains two pieces of information:

prop.name Name of the proposition (ie. holding(robotA, blockB))
prop.var Variable object associated with the proposition.
prop.val Value of the variable (as an integer).

Operator

The Operator object holds information associated with a single SAS operator:

op.dump() Dump information about the operator (preconditions and effects).
op.name Name of the operator (includes the PDDL operator name and arguments).
op.val Value of the operator (as an integer).
op.precond List of Proposition objects that correspond to the preconditions of the operator.
op.effects A Tuple where the first entry is a list of Proposition objects corresponding to the conditional portion of the effect,
and the second entry is a Proposition object corresponding to the variable setting effect.

Note: The prevail conditions (if any) are all compiled away into preconditions during the parsing phase.

Variable

A Variable object contains a number of pieces of information:

var.axiom_layer The axiom layer of this variable. This is -1 if the variable was not introduced to ground away an axiom.
var.is_axiom True if the variable is an axiom, False otherwise.
var.name Name of the variable in the output.sas file.
var.val The id of the SAS+ variable.
var.propositions A List of Proposition objects that are associated with this variable.
var.range An int indicating the size of the domain.

DTG

The DTG object represents a single Domain Transition graph. It has the following members for quick information:

dtg.name Name of the variable associated with the DTG.
dtg.domain_size Size of the domain (number of nodes in the graph).
dtg.axiom_layer Axiom layer of the variable associated with the DTG.
dtg.graph (advanced) The digraph associated with the DTG. For more info, see the pygraph project.

In addition to these bits of information, the DTG object has the following functionality:

dtg.get_transitions(x,y) Returns a list of DTGTransition objects associated with
the edge x->y in the DTG.
dtg.setGoal(val) Set the goal of the DTG to val.
Note: More than one goal is permitted.
dtg.setInit(val) Set the initial value of the DTG to val.
Note: More than one initial value is not permitted.
dtg.dot() Returns a string representation of the DTG in dot format,
including marked up init and goal states.

DTGTransition

Since there may be a number of transitions between two values of a DTG, a special data structure is used to house information about these transitions. The following members are available for use in a DTGTransition object:

dtgt.source_val The value of a source node in the DTG (usually an integer).
dtgt.target_val The value of a target node in the DTG (usually an integer).
dtgt.op_num The operator number associated with this transition.
dtgt.conditions Conditions associated with this transition as (var, val) pairs.

Additionally, the following method is available (and used primarily when constructing the DTG objects):

dtgt.addCond(var, val) Adds the condition (var, val) pair to the list of conditions.

CG

The CG object represents the Causal Graph of a problem. It has the following members for quick information:

cg.var_names List of variable names in the problem.
cg.size Size of the causal graph.
cg.graph (advanced) The digraph associated with the CG. For more info, see the pygraph project.

In addition to these bits of information, the CG object also has the following functionality:

cg.isAcyclic() Checks if the causal graph is acyclic.
cg.dot() Returns a string representation of the CG in dot format.

SG

The SG object represents the Successor Generator for a given SAS+ planning problem. It is a compact data structure that allows for quick analysis of which operators are applicable in a given state. Currently it is just a shell capable of parsing the SG output in SAS+ encodings, and exporting to DOT format for inspection. In the future however, further functionality will be added.

sg.gen_output() Returns the SG encoding as found in the SAS+ encoding.
sg.dot() Returns the dot output of the SG data structure.

SAS+ Operations

Coming soon...


Examples

Coming soon...