Example #1
0
 def test_scan_tokens_problem(self):
     parser = PDDL_Parser()
     self.assertEqual(parser.scan_tokens('examples/dinner/pb1.pddl'), [
         'define', ['problem', 'pb1'], [':domain', 'dinner'],
         [':init', ['garbage'], ['clean'], ['quiet']],
         [':goal', ['and', ['dinner'], ['present'], ['not', ['garbage']]]]
     ])
Example #2
0
 def test_scan_tokens_domain(self):
     parser = PDDL_Parser()
     self.assertEqual(parser.scan_tokens('examples/dinner/dinner.pddl'), [
         'define', ['domain', 'dinner'], [':requirements', ':strips'],
         [
             ':predicates', ['clean'], ['dinner'], ['quiet'], ['present'],
             ['garbage']
         ],
         [
             ':action', 'cook', ':precondition', ['clean'], ':effect',
             ['dinner']
         ],
         [
             ':action', 'wrap', ':precondition', ['quiet'], ':effect',
             ['present']
         ],
         [
             ':action', 'carry', ':precondition', ['garbage'], ':effect',
             ['and', ['not', ['garbage']], ['not', ['clean']]]
         ],
         [
             ':action', 'dolly', ':precondition', ['garbage'], ':effect',
             ['and', ['not', ['garbage']], ['not', ['quiet']]]
         ]
     ])
 def test_scan_tokens_problem(self):
     parser = PDDL_Parser()
     self.assertEqual(parser.scan_tokens('dinner/pb1.pddl'),
         ['define', ['problem', 'pb1'],
         [':domain', 'dinner'],
         [':init', ['garbage'], ['clean'], ['quiet']],
         [':goal', ['and', ['dinner'], ['present'], ['not', ['garbage']]]]]
     )
 def test_scan_tokens_domain(self):
     parser = PDDL_Parser()
     self.assertEqual(parser.scan_tokens('dinner/dinner.pddl'),
         ['define', ['domain', 'dinner'],
         [':requirements', ':strips'],
         [':predicates', ['clean'], ['dinner'], ['quiet'], ['present'], ['garbage']],
         [':action', 'cook',
             ':parameters', [],
             ':precondition', ['and', ['clean']],
             ':effect', ['and', ['dinner']]],
         [':action', 'wrap',
             ':parameters', [],
             ':precondition', ['and', ['quiet']],
             ':effect', ['and', ['present']]],
         [':action', 'carry',
             ':parameters', [],
             ':precondition', ['and', ['garbage']],
             ':effect', ['and', ['not', ['garbage']], ['not', ['clean']]]],
         [':action', 'dolly',
             ':parameters', [],
             ':precondition', ['and', ['garbage']],
             ':effect', ['and', ['not', ['garbage']], ['not', ['quiet']]]]]
     )
Example #5
0
class trajectory:
    def parseObjects(self, objTokens):
        self.types2objs = {
        }  # Map of types -> objects; useful when you need to know what objects have a specified type
        self.objs2types = {
        }  # Map of objects -> types; useful when you want to know what the type of a specific object is
        objs = []
        isType = False
        for token in objTokens[
                1:]:  # Throw out objTokens[0], which will be the string ':objects'
            if isType:
                if token not in self.types2objs:
                    self.types2objs[token] = []
                self.types2objs[token].extend(objs)
                for obj in objs:
                    self.objs2types[obj] = token
                objs = []
                isType = False
            elif token == '-':
                isType = True
            else:
                objs.append(token)

    # Parses the :init and :state blocks in the trajectory file, and also makes a dictionary of all the predicates that appear in the states, along with the types of their peremeters
    def parseStates(self, tokens):
        self.states = []
        self.predicates = {}
        for block in tokens:
            if block[0] == ':state' or block[0] == ':init':
                self.states.append(block[1:])
                for pred in block[1:]:
                    pName = pred[0]
                    pTypes = []
                    for arg in pred[1:]:
                        pTypes.append(
                            [self.objs2types[arg]]
                        )  # Predicate type lists are now lists of lists of strings- each inner list representing the types observed for one parameter
                    if pName in self.predicates:
                        for oldParamTypes, newType in zip(
                                self.predicates[pName], pTypes):
                            if newType[0] not in oldParamTypes:
                                oldParamTypes.append(newType[0])
                        # if self.predicates[pName] != pTypes:
                        # raise TypeError('Predicate {} believed to have parameter types {}; inconsistent with observed parameters {}'.format(pName, self.predicates[pName], pTypes))
                    else:
                        self.predicates[pName] = pTypes

    def parseActions(self, tokens):
        self.actions = {}
        for block in tokens:
            if block[0] == ':action':
                act_in = block[1]
                # print('Parsing action {}'.format(act_in))
                parTypes = []
                for param in act_in[1:]:
                    parTypes.append(
                        self.objs2types[param]
                    )  # Not doing list-of-lists here- that'll be handled in actionCandidate constructor
                if act_in[0] in self.actions:
                    # print ('Found action with same name: {}'.format(act_in[0]))
                    for oldTypes, newType in zip(
                            self.actions[act_in[0]].parameterTypes, parTypes):
                        if newType not in oldTypes:
                            oldTypes.append(newType)
                    self.actions[act_in[0]].updateParameterTypes(parTypes)
                    # if act.parameterTypes != parTypes:
                    #     raise TypeError('Action {} found using parameters {}; inconsistent with earlier {}. Are you using type inheritance?'.format(act_in[0], parTypes, act.parameterTypes))
                else:
                    newAct = actionCandidate(act_in[0], parTypes, self)
                    self.actions[newAct.name] = newAct

    def refineActions(self, tokens):
        assignments = [((n - 1) // 2 - 1, block[1])
                       for (n, block) in enumerate(tokens)
                       if block[0] == ':action']
        # pprint.pprint(assignments)
        for i, agmt in assignments:
            assignedTypes = [self.objs2types[par] for par in agmt[1:]]
            self.actions[agmt[0]].updateParameterTypes(assignedTypes)
        for act in self.actions.values():
            act.createPrecons(self)
        needsDoubleChecking = False
        for i, agmt in assignments:
            # print('State {}: {}'.format(i, self.states[i]))
            # print('Action {}: {}'.format(i, agmt))
            # print('State {}: {}'.format(i+1, self.states[i+1]))
            # print()
            act = self.actions[agmt[0]]
            assignment = agmt[1:]
            # assignedTypes = [self.objs2types[par] for par in assignment]
            act.prunePrecons(self.states[i], assignment)
            needsDoubleChecking |= act.updateEffects(self.states[i],
                                                     assignment,
                                                     self.states[i + 1])
        if needsDoubleChecking:
            # print('Double-checking action effects\n')
            needsDoubleChecking = False
            for i, agmt in assignments:
                act = self.actions[agmt[0]]
                assignment = agmt[1:]
                # assignedTypes = [self.objs2types[par] for par in assignment]
                needsDoubleChecking |= act.updateEffects(
                    self.states[i], assignment, self.states[i + 1])
            if needsDoubleChecking:
                raise ValueError(
                    "Some actions still had unexpected effects during the second pass. This shouldn't be possible. If you see this message, please let me know. --SE"
                )

    def genTypeclasses(self):  #TODO Add code to deal with deeper hierarchies
        classList = []
        for typesOuter in self.predicates.values():
            for types in typesOuter:
                # print(types)
                sorTypes = list(sorted(types))
                if sorTypes not in classList:
                    classList.append(sorTypes)
        for act in self.actions:
            for types in self.actions[act].parameterTypes:
                sorTypes = list(sorted(types))
                if sorTypes not in classList:
                    classList.append(sorTypes)
        # print(classList)
        self.typeclasses = {}
        for tclass in classList:
            self.typeclasses['_'.join(tclass)] = 'object'
        for typ in self.types2objs.keys():
            container = 'object'
            for tclass in classList:
                if typ in tclass and typ != '_'.join(tclass):
                    container = '_'.join(tclass)
            self.typeclasses[typ] = container

    def __init__(self, filename, domainName='reconstructed'):
        self.domainName = domainName
        self.parser = PDDL_Parser()
        self.tokens = self.parser.scan_tokens(filename)
        pprint.pprint(self.tokens)
        print('=== Objects ===')
        self.parseObjects(self.tokens[1])
        pprint.pprint(self.types2objs)
        print('=== States ===')
        self.parseStates(self.tokens)
        pprint.pprint(self.states)
        print('=== Predicates ===')
        pprint.pprint(self.predicates)
        print('=== Actions ===')
        self.parseActions(self.tokens)
        # print(self.tokens[3])
        # p, n = self.actions[0].assignPrecons(self.tokens[3][1][1:])
        # print('Grounded Positive preconditions')
        # print(p)
        # print('Grounded Negative preconditions')
        # print(n)
        # print('Before State')
        # print(self.states[0])
        # self.actions[0].prunePrecons(self.states[0], self.tokens[3][1][1:])
        # print(self.actions[0])
        self.refineActions(self.tokens)
        pprint.pprint(self.actions)
        self.genTypeclasses()

    def __repr__(self):
        fmtTypeclasses = [
            '{} - {}'.format(k, v) for k, v in self.typeclasses.items()
        ]
        fmtPredicates = []
        for name, types in self.predicates.items():
            fmtParams = [name]
            for i, typ in enumerate(types):
                fmtParams.append('?{} - {}'.format(i, '_'.join(typ)))
            fmtPredicates.append('({})'.format(' '.join(fmtParams)))
        fmtActions = [str(act) for act in self.actions.values()]
        return '''(define (domain {})
(:requirements :typing :negative-preconditions)
(:types {})
(:predicates {})
{})
'''.format(self.domainName, ' '.join(fmtTypeclasses), ' '.join(fmtPredicates),
           ''.join(fmtActions))