
AutoToS prompt:

I am playing with a set of blocks where I need to arrange the blocks into stacks. Here are the actions I can do
   Pick up a block from the table
   Put down a block on the table
   Unstack a block from on top of another block
   Stack a block on top of another block

   I have the following restrictions on my actions:
   I can only pick up or unstack one block at a time.
   I can only pick up or unstack a block if my hand is empty.
   I can only pick up a block if the block is on the table and the block is clear. A block is clear if the block has no other blocks on top of it and if the block is not picked up.
   I can only unstack a block from on top of another block if the block I am unstacking was really on top of the other block.
   I can only unstack a block from on top of another block if the block I am unstacking is clear.
   Once I pick up a block, I am holding the block and it is no longer clear and no longer on the table. 
   Once I unstack from on top of another block, I am holding the block and it is no longer clear. Instead, the other block becomes clear.   

   I can only put down a block that I am holding.
   I can only stack a block on top of another block if I am holding the block being stacked.
   I can only stack a block on top of another block if the block onto which I am stacking the block is clear.
   Once I put down a block, my hand becomes empty, the block becomes clear, and it is now on the table.
   Once I stack a block on top of another block, the block on top becomes clear and the block under it is no longer clear.
If a state is defined by a dictionary of following predicates "clear block", "on-table block", "arm-empty", "holding block", and "on block1 block2", how are successor states defined? 
Here is an example of the initial state:
Init: {'clear': ['b'], 'on-table': ['d'], 'arm-empty': True, 'holding': None, 'on': [('a', 'c'), ('b', 'a'), ('c', 'd')]}
Please provide only the Python code for the successor function that returns a list of successor states.

Model response:
```python
def successor_states(state):
    from copy import deepcopy

    def is_action_valid(action, block=None, block1=None, block2=None):
        if action == "pick_up":
            return state['arm-empty'] and block in state['on-table'] and block in state['clear']
        elif action == "put_down":
            return state['holding'] is not None
        elif action == "unstack":
            return state['arm-empty'] and (block1, block2) in state['on'] and block1 in state['clear']
        elif action == "stack":
            return state['holding'] is not None and block1 in state['clear']
        return False

    def apply_action(state, action, block=None, block1=None, block2=None):
        new_state = deepcopy(state)
        if action == "pick_up":
            new_state['on-table'].remove(block)
            new_state['clear'].remove(block)
            new_state['arm-empty'] = False
            new_state['holding'] = block
        elif action == "put_down":
            new_state['on-table'].append(state['holding'])
            new_state['clear'].append(state['holding'])
            new_state['arm-empty'] = True
            new_state['holding'] = None
        elif action == "unstack":
            new_state['on'].remove((block1, block2))
            new_state['clear'].append(block2)
            new_state['clear'].remove(block1)
            new_state['arm-empty'] = False
            new_state['holding'] = block1
        elif action == "stack":
            new_state['on'].append((state['holding'], block1))
            new_state['clear'].remove(block1)
            new_state['clear'].append(state['holding'])
            new_state['arm-empty'] = True
            new_state['holding'] = None
        return new_state

    successors = []
    
    # Generate all possible actions and generate new states
    for block in state['on-table']:
        if is_action_valid("pick_up", block=block):
            new_state = apply_action(state, "pick_up", block=block)
            successors.append(new_state)

    if state['holding'] is not None:
        new_state = apply_action(state, "put_down")
        successors.append(new_state)

    for (block1, block2) in state['on']:
        if is_action_valid("unstack", block1=block1, block2=block2):
            new_state = apply_action(state, "unstack", block1=block1, block2=block2)
            successors.append(new_state)

    if state['holding'] is not None:
        for clear_block in state['clear']:
            if is_action_valid("stack", block1=clear_block):
                new_state = apply_action(state, "stack", block1=clear_block)
                successors.append(new_state)

    return successors
```

AutoToS prompt:

    Provide only the python code that tests whether a state is a goal state. The goal specifies a partial state, the facts that must be true in any full goal state. Assume that the goal configuration is provided in the same dictionary format. 
    Here's an example goal specification:
    Goal: {'clear': [], 'on-table': [], 'on': [('b', 'c'), ('d', 'b')]}
    
Model response:
```python
def is_goal_state(state, goal):
    def match(condition, state_values, goal_values):
        if isinstance(goal_values, list):
            return all(elem in state_values for elem in goal_values)
        return state_values == goal_values
    
    for predicate in goal:
        if not match(predicate, state[predicate], goal[predicate]):
            return False
    return True
```

System message:
Goal Soundness Test Passed
Soundness test

System message:
Successor States Soundness Test Passed
Completeness test
Successor Completeness Test Passed
Evaluating the final outcome
Success: 502, failure: 0, total expansions 50456, total generated 130124
