def _parse_problem(self, f_problem): """ Extract information from the problem file. The following will be extracted: * problem name * objects * initial state * goal state * type_to_obj * obj_to_type """ parse_tree = PDDL_Tree.create(f_problem) assert "problem" in parse_tree, "Problem must have a name" self.problem_name = parse_tree["problem"].named_children()[0] # objects must be parsed first if ":objects" in parse_tree: object_list = PDDL_Utils.read_type(parse_tree[":objects"]) self._add_objects(object_list) #TODO this may not be valid with a non-flat type hierchy obj_map = {obj: list(self.obj_to_type[obj])[0] for obj in self.objects} # the goal can be expressed in either a formula form, or a direct form if len(parse_tree[":goal"].children ) == 1 and parse_tree[":goal"].children[0].name == "and": self.goal = And([ Primitive(self.to_fluents(c)) for c in parse_tree[":goal"].children[0].children ]) else: self.goal = And([ Primitive(self.to_fluents(c)) for c in parse_tree[":goal"].children ]) # it is critical that the formula here be checked against the objects if len(parse_tree[":init"].children) == 1 and \ parse_tree[":init"].children[0].name == "and": self.init = self.to_formula(parse_tree[":init"].children[0], obj_map) else: # initial condition is one big AND # print "```", self.init self.init = And([ self.to_formula(c, obj_map) for c in parse_tree[":init"].children ])
def __init__(self, p, h): self.problem = p self.initial = p.init # self.actions = p.actions self.goal = p.goal # self.type_to_obj = p.type_to_obj # self.objects = p.obj_to_type self.fluents = p.fluents self.operators = p.operators self.precs = {} self.effects = {} self.observes = {} self.adds_fluent = {}#use self.dels_fluent = {}#use self.horizon = h self.j = 1 self.logic = Logic() self.jk = [] self.fluent_lits = [] self.op_lits = [] self.djk_lits = [] self.all_literals = [] self.initial_lits = None self.subproblems = [] self.init_known = None self.lit_dict = {} self.lit_lookup = {} self.dg_atom = Predicate('DG', None, []) self.fluents.add(self.dg_atom) self.end_atom = Operator('End', [], self.goal, None, And([Primitive(self.dg_atom)])) self.operators.add(self.end_atom)
def compile(problem, T, M, init_TL): """Returns new GroundProblem instance.""" # verify inputs assert isinstance (problem, GroundProblem), \ "The problem must be ground" assert isinstance(T, list) and \ all([isinstance(t, Literal) for t in T]), \ "Tags must be a list of Literals" assert isinstance(M, list) and \ all([isinstance(m, tuple) for m in M]),\ "Merges must be a list of tuples" assert isinstance(init_TL, list) and \ all([isinstance(e, tuple) for e in init_TL]),\ "Initial tag literals must be a list of tuples" fluents = [] fluent_dict = {} conversion_dict = {} for fluent in problem.fluents: l_name = "K%s" % fluent.name kl = Predicate(l_name, None, fluent.ground_args) fluents.append(kl) fluent_dict[hash(kl)] = kl conversion_dict[hash(fluent)] = kl l_not_name = "K_not_%s" % fluent.name k_notl = Predicate(l_not_name, None, fluent.ground_args) fluents.append(k_notl) fluent_dict[hash(k_notl)] = k_notl for tag in T: l_name = "K_%s_|_%s" % (fluent.name, tag.name) kl = Predicate(l_name, None, fluent.ground_args) fluents.append(kl) fluent_dict[hash(kl)] = kl l_not_name = "K_not_%s_|_%s" % (fluent.name, tag.name) k_notl = Predicate(l_not_name, None, fluent.ground_args) fluents.append(k_notl) fluent_dict[hash(k_notl)] = k_notl print "* New fluents *" for fluent in fluents: print fluent #TODO new initial state print "* New goal state *" goal_fluents = [] for arg in problem.goal.args: p = Primitive(conversion_dict[hash(arg.predicate)]) goal_fluents.append(p) print p
def _partial_ground_formula(self, formula, assignment, fluent_dict): """ Inputs: formula The formula to be converted assignment a dictionary mapping each possible variable name to an object Returns: A formula that has the particular valuation for the variables as given in input. The old formula is *untouched* """ if formula is None: return None if isinstance(formula, Primitive): new_prim = Primitive(self._predicate_to_fluent(formula.predicate, assignment, fluent_dict)) new_prim.agent_list = formula.agent_list new_prim.negated_rml = formula.negated_rml for k in assignment: new_prim.agent_list = new_prim.agent_list.replace(k, assignment[k]) return new_prim elif isinstance(formula, Forall): new_conjuncts = [] var_names, val_generator = self._create_valuations(formula.params) for valuation in val_generator: new_assignment = {var_name: val for var_name, val in zip(var_names, valuation)} for k in assignment: new_assignment[k] = assignment[k] new_conjuncts.append(self._partial_ground_formula(formula.args[0], new_assignment, fluent_dict)) return And(new_conjuncts) elif isinstance(formula, When): return When(self._partial_ground_formula(formula.condition, assignment, fluent_dict), self._partial_ground_formula(formula.result, assignment, fluent_dict)) else: return type(formula)([self._partial_ground_formula(arg, assignment, fluent_dict) for arg in formula.args])
def create_literals(self): self.all_atoms = list(self.fluents) + list(self.possible_ops) + self.jk for t in range(self.horizon): for j in range(self.j): for f in self.fluents: lit = Literal('fluent', f, (j,t)) self.fluent_lits.append(lit) self.lit_lookup[f, j, t] = lit for t in range(self.horizon-1): for j in range(self.j): for o in self.possible_ops: lit = Literal('action', o, (j,t)) self.op_lits.append(lit) self.lit_lookup[o, j, t] = lit self.precs[lit] = self.lit_formula(o.precondition, j,t) self.effects[lit] = self.lit_formula(o.effect, j, t+1) self.observes[lit] = self.lit_formula(o.observe,j,t+1) if o.name == 'End': self.effects[lit] = And([ self.effects[lit], self.lit_formula(Primitive(self.dg_atom), j, self.horizon-1)]) for t in range(self.horizon): for djk in self.jk: lit = Literal('D', djk, t) self.djk_lits.append(Literal('D', djk, t)) self.lit_lookup['D',djk, t] = lit self.all_literals = self.fluent_lits + self.op_lits + self.djk_lits self.goal_lits = [self.lit_lookup[self.dg_atom, j, self.horizon-1] for j in range(self.j)] self.initial_lits = [self.lit_formula(self.init_known, j, 0) for j in range(self.j)] self.subinit_lits = [self.lit_formula(And(self.subproblems[j]),j, 0) for j in range(self.j)] self.initnot_lits = [self.lit_formula(And([Not([Primitive(i)]) for i in self.initnot]),j,0) for j in range(self.j)] d = 1 for l in self.all_literals: self.lit_dict[l] = d d += 1
def to_formula(self, node, parameter_map=None): """ Return a formula out of this PDDL_Tree node. For now, will assume this makes sense. """ # forall is so weird that we can treat it as an entirely seperate entity if "forall" == node.name: # treat args differently in this case assert len(node.children) in[2, 4],\ "Forall must have a variable(typed or untyped) and formula that it quantifies" i = len(node.children) - 1 if len(node.children) == 2 and len(node.children[0].children) > 0: # adjust this node by changing the structure of the first child new_child = PDDL_Tree(PDDL_Tree.EMPTY) new_child.add_child(PDDL_Tree(node.children[0].name)) for c in node.children[0].children: new_child.add_child(c) node.children[0] = new_child l = PDDL_Utils.read_type(new_child) for v, t in l: parameter_map[v] = t args = [ self.to_formula(c, parameter_map) for c in node.children[i:] ] for v, t in l: del (parameter_map[v]) return Forall(l, args) i = 0 args = [self.to_formula(c, parameter_map) for c in node.children[i:]] if "and" == node.name: return And(args) elif "or" == node.name: return Or(args) elif "oneof" == node.name: return Oneof(args) elif "not" == node.name: return Not(args) elif "xor" == node.name: return Xor(args) elif "nondet" == node.name: assert len(node.children) == 1,\ "nondet must only have a single child as a predicate" # make p != p2, otherwise might run into issues with mutation in some later step return Oneof([args[0], Not(args)]) elif "unknown" == node.name: assert len(node.children) == 1,\ "unknown must only have a single child as a predicate" # make p != p2, otherwise might run into issues with mutation in some later step p = Primitive( self.to_predicate(node.children[0], map=parameter_map)) p2 = Primitive( self.to_predicate(node.children[0], map=parameter_map)) return Xor([p, Not([p2])]) elif "when" == node.name: assert len(args) == 2,\ "When clause must have exactly 2 children" return When(args[0], args[1]) else: # it's a predicate return Primitive(self.to_predicate(node, map=parameter_map))
def to_formula(self, node, parameter_map=None): """ Return a formula out of this PDDL_Tree node. For now, will assume this makes sense. """ # forall is so weird that we can treat it as an entirely seperate entity if "forall" == node.name: # treat args differently in this case assert len(node.children) in[2, 4],\ "Forall must have a variable(typed or untyped) and formula that it quantifies" i = len(node.children) - 1 if len(node.children) == 2 and len(node.children[0].children) > 0: # adjust this node by changing the structure of the first child new_child = PDDL_Tree(PDDL_Tree.EMPTY) new_child.add_child(PDDL_Tree(node.children[0].name)) for c in node.children[0].children: new_child.add_child(c) node.children[0] = new_child l = PDDL_Utils.read_type(new_child) else: l = [(node.children[0].name, node.children[2].name)] for v, t in l: parameter_map[v] = t args = [ self.to_formula(c, parameter_map) for c in node.children[i:] ] for v, t in l: del (parameter_map[v]) return Forall(l, args) i = 0 args = [self.to_formula(c, parameter_map) for c in node.children[i:]] def handle_modality(node, pref_len, modality): assert 1 <= len( node.children) <= 2, "Error: Found %d children." % len( node.children) #print "%s / %s / %s" % (str(node), str(pref_len), str(modality)) ag = node.name[pref_len:-1] if len(node.children) == 1: pred = self.to_formula(node.children[0], parameter_map) else: pred = self.to_formula(node.children[1], parameter_map) pred.negated_rml = True assert not isinstance( pred, Not ), "Error: Cannot nest lack of belief with (not ...): %s" % pred.dump( ) assert isinstance( pred, Primitive ), "Error: Type should have been Primitive, but was %s" % str( type(pred)) pred.agent_list = "%s%s %s" % (modality, ag, pred.agent_list) return pred if "and" == node.name: return And(args) elif "or" == node.name: return Or(args) elif "oneof" == node.name: return Oneof(args) elif "not" == node.name: return Not(args) elif "xor" == node.name: return Xor(args) elif "nondet" == node.name: assert len(node.children) == 1,\ "nondet must only have a single child as a predicate" # make p != p2, otherwise might run into issues with mutation in some later step return Oneof([args[0], Not(args)]) elif "unknown" == node.name: assert len(node.children) == 1,\ "unknown must only have a single child as a predicate" # make p != p2, otherwise might run into issues with mutation in some later step p = Primitive( self.to_predicate(node.children[0], map=parameter_map)) p2 = Primitive( self.to_predicate(node.children[0], map=parameter_map)) return Xor([p, Not([p2])]) elif "when" == node.name: assert len(args) == 2,\ "When clause must have exactly 2 children" return When(args[0], args[1]) elif "P{" == node.name[:2]: return handle_modality(node, 2, 'P') elif "!P{" == node.name[:3]: return handle_modality(node, 3, '!P') elif "B{" == node.name[:2]: return handle_modality(node, 2, 'B') elif "!B{" == node.name[:3]: return handle_modality(node, 3, '!B') elif "!" == node.name[0]: node.name = node.name[1:] pred = Primitive(self.to_predicate(node, map=parameter_map)) pred.negated_rml = True return pred else: # it's a predicate return Primitive(self.to_predicate(node, map=parameter_map))