def reset(self): """ Set up a new PDDL problem and start a new episode. Note that the PDDL files are included in debug_info. Returns ------- obs : { Literal } The set of active predicates. debug_info : dict See self._get_debug_info() """ if not self._problem_index_fixed: self._problem_idx = self.rng.choice(len(self.problems)) self._problem = self.problems[self._problem_idx] initial_state = State(frozenset(self._problem.initial_state), frozenset(self._problem.objects), self._problem.goal) initial_state = self._handle_derived_literals(initial_state) self.set_state(initial_state) self._goal = self._problem.goal debug_info = self._get_debug_info() return self.get_state(), debug_info
def create_states_from_base_literals(base_state_literals, state_literals, problem): return [ State(frozenset({*base_state_literals, *literals}), frozenset(problem.objects), problem.goal) for literals in state_literals ]
def test_hierarchical_spaces(): dir_path = os.path.dirname(os.path.realpath(__file__)) domain_file = os.path.join(dir_path, 'pddl', 'hierarchical_type_test_domain.pddl') problem_file = os.path.join(dir_path, 'pddl', 'hierarchical_type_test_domain', 'hierarchical_type_test_problem.pddl') domain = PDDLDomainParser(domain_file) problem = PDDLProblemParser(problem_file, domain.domain_name, domain.types, domain.predicates, domain.actions) actions = list(domain.actions) action_predicates = [domain.predicates[a] for a in actions] space = LiteralSpace(set(domain.predicates.values()) - set(action_predicates), type_to_parent_types=domain.type_to_parent_types) all_ground_literals = space.all_ground_literals( State(problem.initial_state, problem.objects, problem.goal)) ispresent = Predicate("ispresent", 1, [Type("entity")]) islight = Predicate("islight", 1, [Type("object")]) isfurry = Predicate("isfurry", 1, [Type("animal")]) ishappy = Predicate("ishappy", 1, [Type("animal")]) attending = Predicate("attending", 2, [Type("animal"), Type("object")]) nomsy = Type("jindo")("nomsy") rover = Type("corgi")("rover") rene = Type("cat")("rene") block1 = Type("block")("block1") block2 = Type("block")("block2") cylinder1 = Type("cylinder")("cylinder1") assert all_ground_literals == { ispresent(nomsy), ispresent(rover), ispresent(rene), ispresent(block1), ispresent(block2), ispresent(cylinder1), islight(block1), islight(block2), islight(cylinder1), isfurry(nomsy), isfurry(rover), isfurry(rene), ishappy(nomsy), ishappy(rover), ishappy(rene), attending(nomsy, block1), attending(nomsy, block2), attending(nomsy, cylinder1), attending(rover, block1), attending(rover, block2), attending(rover, cylinder1), attending(rene, block1), attending(rene, block2), attending(rene, cylinder1), } print("Test passed.")
def _create_problem_file(self, raw_problem_fname, use_cache=True): if (not use_cache) or (raw_problem_fname not in self._problem_files): problem_fname = os.path.split(raw_problem_fname)[-1] problem_fname = problem_fname.split('.pddl')[0] problem_fname += '_{}_with_diffs_{}.pddl'.format( self.domain_name, random.randint(0, 9999999)) problem_fname = os.path.join('/tmp', problem_fname) # Parse raw problem problem_parser = PDDLProblemParser(raw_problem_fname, self.domain_name.lower(), self._types, self._predicates, self._actions) new_initial_state = set(problem_parser.initial_state) # Add actions action_lits = set( self._action_space.all_ground_literals(State( new_initial_state, problem_parser.objects, problem_parser.goal), valid_only=False)) new_initial_state |= action_lits # Add 'Different' pairs for each pair of objects Different = Predicate('Different', 2) for obj1 in problem_parser.objects: for obj2 in problem_parser.objects: if obj1 == obj2: continue # if obj1.var_type != obj2.var_type: # continue diff_lit = Different(obj1, obj2) new_initial_state.add(diff_lit) # Write out new temporary problem file problem_parser.initial_state = frozenset(new_initial_state) problem_parser.write(problem_fname) # Add to cache self._problem_files[raw_problem_fname] = problem_fname return self._problem_files[raw_problem_fname]
def reset(self): """ Set up a new PDDL problem and start a new episode. Note that the PDDL files are included in debug_info. Returns ------- obs : { Literal } The set of active predicates. debug_info : dict See self._get_debug_info() """ if not self._problem_index_fixed: # Problem is changing, force ourselves to recompute heuristic self._heuristic = None self._problem_idx = self.rng.choice(len(self.problems)) self._problem = self.problems[self._problem_idx] # Create new heuristic if using reward shaping and either the problem # isn't fixed or no heuristic has been created yet. if (self._shape_reward_mode is not None and self._shape_reward_mode != "optimal" and self._heuristic is None): self._heuristic = self.make_heuristic_function( self._shape_reward_mode) # reset the current heuristic self._current_heuristic = None initial_state = State(frozenset(self._problem.initial_state), frozenset(self._problem.objects), self._problem.goal) self.set_state(initial_state) self._goal = self._problem.goal debug_info = self._get_debug_info() return self.get_state(), debug_info
def _create_problem_file(self, raw_problem_fname, use_cache=True): if (not use_cache) or (raw_problem_fname not in self._problem_files): problem_fname = os.path.split(raw_problem_fname)[-1] problem_fname = problem_fname.split('.pddl')[0] problem_fname += '_{}_with_diffs_{}.pddl'.format( self.domain_name, random.randint(0, 9999999)) problem_fname = os.path.join('/tmp', problem_fname) # Parse raw problem action_names = [ ] # purposely empty b/c we WANT action literals in there problem_parser = PDDLProblemParser(raw_problem_fname, self.domain_name.lower(), self._types, self._predicates, action_names) # Add action literals (in case they're not already present in the initial state) # which will be true when the original domain uses operators_as_actions init_state = State(problem_parser.initial_state, problem_parser.objects, None) act_lits = self._action_space.all_ground_literals(init_state, valid_only=False) problem_parser.initial_state = frozenset( act_lits | problem_parser.initial_state) # Add 'Different' pairs for each pair of objects Different = Predicate('Different', 2) init_state = set(problem_parser.initial_state) for obj1 in problem_parser.objects: for obj2 in problem_parser.objects: if obj1 == obj2: continue # if obj1.var_type != obj2.var_type: # continue diff_lit = Different(obj1, obj2) init_state.add(diff_lit) problem_parser.initial_state = frozenset(init_state) # Also add 'different' pairs for goal if it's existential if isinstance(problem_parser.goal, Exists): diffs = [] for var1 in problem_parser.goal.variables: for var2 in problem_parser.goal.variables: if var1 == var2: continue diffs.append(Different(var1, var2)) problem_parser.goal = Exists( problem_parser.goal.variables, type(problem_parser.goal.body)( problem_parser.goal.body.literals + diffs)) # If no objects, write a dummy one to make FF not crash. if not problem_parser.objects: problem_parser.objects.append("DUMMY") # Write out new temporary problem file problem_parser.write(problem_fname) # Add to cache self._problem_files[raw_problem_fname] = (problem_fname, problem_parser.objects) return self._problem_files[raw_problem_fname]
def _state_to_internal(self, state): state = dict(state) new_state_literals = set() directions_to_deltas = { self.direction_type('up') : (-1, 0), self.direction_type('down') : (1, 0), self.direction_type('left') : (0, -1), self.direction_type('right') : (0, 1), } # conn height, width = 6, 6 for r in range(height): for c in range(width): loc = self.location_type(f"f{r}-{c}f") for direction, (dr, dc) in directions_to_deltas.items(): next_r, next_c = r + dr, c + dc if not (0 <= next_r < height and 0 <= next_c < width): continue next_loc = self.location_type(f"f{next_r}-{next_c}f") conn_lit = self.conn(loc, next_loc, direction) new_state_literals.add(conn_lit) # at occupied_locs = set() hospital_loc = None for obj_name, loc_tup in state.items(): if obj_name in ["carrying", "rescue"]: continue r, c = loc_tup loc = self.location_type(f"f{r}-{c}f") if obj_name.startswith("person"): at_pred = self.person_at elif obj_name.startswith("robot"): at_pred = self.robot_at occupied_locs.add((r, c)) elif obj_name.startswith("wall"): at_pred = self.wall_at occupied_locs.add((r, c)) elif obj_name.startswith("hospital"): at_pred = self.hospital_at assert hospital_loc is None hospital_loc = loc else: raise Exception(f"Unrecognized object {obj_name}") new_state_literals.add(at_pred(obj_name, loc)) assert hospital_loc is not None # carrying/handsfree if state["carrying"] is None: new_state_literals.add(self.handsfree("robot0")) else: new_state_literals.add(self.carrying("robot0", state["carrying"])) # clear for r in range(height): for c in range(width): if (r, c) not in occupied_locs: loc = self.location_type(f"f{r}-{c}f") clear_lit = self.clear(loc) new_state_literals.add(clear_lit) # objects new_objects = frozenset({o for lit in new_state_literals for o in lit.variables }) # goal new_goal = LiteralConjunction([self.person_at(person, hospital_loc) \ for person in sorted(state["rescue"])]) new_state = State(frozenset(new_state_literals), new_objects, new_goal) return new_state
def __call__(self, domain, state, timeout): act_preds = [domain.predicates[a] for a in list(domain.actions)] act_space = LiteralSpace( act_preds, type_to_parent_types=domain.type_to_parent_types) dom_file = tempfile.NamedTemporaryFile(delete=False).name prob_file = tempfile.NamedTemporaryFile(delete=False).name domain.write(dom_file) lits = set(state.literals) if not domain.operators_as_actions: lits |= set(act_space.all_ground_literals(state, valid_only=False)) PDDLProblemParser.create_pddl_file(prob_file, state.objects, lits, "myproblem", domain.domain_name, state.goal, fast_downward_order=True) cur_objects = set() start_time = time.time() if self._force_include_goal_objects: # Always start off considering objects in the goal. for lit in state.goal.literals: cur_objects |= set(lit.variables) # Get scores once. object_to_score = { obj: self._guidance.score_object(obj, state) for obj in state.objects if obj not in cur_objects } # Initialize threshold. threshold = self._gamma for _ in range(self._max_iterations): # Find new objects by incrementally lowering threshold. unused_objs = sorted(list(state.objects - cur_objects)) new_objs = set() while unused_objs: # Geometrically lower threshold. threshold *= self._gamma # See if there are any new objects. new_objs = { o for o in unused_objs if object_to_score[o] > threshold } # If there are, try planning with them. if new_objs: break cur_objects |= new_objs # Keep only literals referencing currently considered objects. cur_lits = set() for lit in state.literals: if all(var in cur_objects for var in lit.variables): cur_lits.add(lit) dummy_state = State(cur_lits, cur_objects, state.goal) # Try planning with only this object set. print("[Trying to plan with {} objects of {} total, " "threshold is {}...]".format(len(cur_objects), len(state.objects), threshold), flush=True) try: time_elapsed = time.time() - start_time # Get a plan from base planner & validate it. plan = self._planner(domain, dummy_state, timeout - time_elapsed) if not validate_strips_plan(domain_file=dom_file, problem_file=prob_file, plan=plan): raise PlanningFailure("Invalid plan") except PlanningFailure: # Try again with more objects. if len(cur_objects) == len(state.objects): # We already tried with all objects, give up. break continue return plan raise PlanningFailure("Plan not found! Reached max_iterations.")