예제 #1
0
 def determinize(self, name_suffix=0):
     """Create a deterministic operators with the most likely effects
     """
     op_name = "{}{}".format(self.action.predicate.name, name_suffix)
     probs, effs = self.effect_probs, self.effects
     max_idx = np.argmax(probs)
     max_effects = LiteralConjunction(sorted(effs[max_idx]))
     preconds = LiteralConjunction(
         sorted(self.preconditions) + [self.action])
     params = sorted(
         {v
          for lit in preconds.literals for v in lit.variables})
     return Operator(op_name, params, preconds, max_effects)
예제 #2
0
def create_goal(domain, objects, pile_heights):
    on = domain.predicates['on']
    ontable = domain.predicates['ontable']

    remaining_blocks = sorted(objects)

    goal_lits = []

    for pile_height in pile_heights:
        assert 2 < pile_height
        block_idxs = np.random.choice(len(remaining_blocks),
                                      size=pile_height,
                                      replace=False)
        blocks_in_pile = []
        for idx in block_idxs:
            blocks_in_pile.append(remaining_blocks[idx])
        remaining_blocks = [
            b for i, b in enumerate(remaining_blocks) if i not in block_idxs
        ]
        # left is top
        for b1, b2 in zip(blocks_in_pile[:-1], blocks_in_pile[1:]):
            goal_lits.append(on(b1, b2))
        goal_lits.append(ontable(blocks_in_pile[-1]))

    return LiteralConjunction(goal_lits)
예제 #3
0
def create_goal(domain, objects):
    place_type = domain.types['place']
    presentationdoneat = domain.predicates['presentationdoneat']
    workedoutat = domain.predicates['workedoutat']
    hikedat = domain.predicates['hikedat']
    swamat = domain.predicates['swamat']
    
    goal_lits = []

    while len(goal_lits) == 0:
        for obj in [o for o in objects if o.var_type == place_type]:
            if obj.startswith("office") and np.random.random() < 0.25:
                goal_lits.append(presentationdoneat(obj))
            elif obj.startswith("gym") and np.random.random() < 0.25:
                goal_lits.append(workedoutat(obj))
            elif obj.startswith("forest") and np.random.random() < 0.25:
                goal_lits.append(hikedat(obj))
            elif obj.startswith("beach") and np.random.random() < 0.25:
                goal_lits.append(swamat(obj))

    max_num_goal_lits = np.random.randint(1, 4)
    if len(goal_lits) > max_num_goal_lits:
        np.random.shuffle(goal_lits)
        goal_lits = goal_lits[:max_num_goal_lits]

    return LiteralConjunction(goal_lits)
예제 #4
0
def create_goal(domain, people, hospital_loc, num_selected_people=1):
    person_at = domain.predicates['person-at']
    goal_lits = []
    selected_people = np.random.choice(people, size=num_selected_people, replace=False)
    for person in selected_people:
        goal_lits.append(person_at(person, hospital_loc))
    return LiteralConjunction(goal_lits)
예제 #5
0
    def _create_preconds_pddl_str(self, preconds):
        all_params = set()
        precond_strs = []
        if isinstance(preconds, Literal):
            preconds = LiteralConjunction([preconds])
        for term in preconds.literals:
            params = set(map(str, term.variables))
            if hasattr(term, 'negated_as_failure') and term.negated_as_failure:
                # Negative term. The variables to universally
                # quantify over are those which we have not
                # encountered yet in this clause.
                universally_quantified_vars = list(sorted(params - all_params))
                precond = ""
                for var in universally_quantified_vars:
                    precond += "(forall ({}) ".format(var.replace(":", " - "))
                precond += "(or "
                for var in universally_quantified_vars:
                    var_cleaned = "?" + var[:var.find(":")]
                    for param in list(sorted(all_params)):
                        param_cleaned = "?" + param[:param.find(":")]
                        precond += "(not (Different {} {})) ".format(
                            param_cleaned, var_cleaned)
                precond += "(not {}))".format(term.positive.pddl_str())
                for var in universally_quantified_vars:
                    precond += ")"
                precond_strs.append(precond)
            else:
                # Positive term.
                all_params.update(params)
                precond_strs.append(term.pddl_str())

        return "\n\t\t\t".join(precond_strs)
예제 #6
0
def parse_goal(board, types, predicates):
    all_preds = [
        predicates["at-goal"](
            *[TypedEntity("stone-{}".format(i), types['thing'])])
        for i, _ in enumerate(board.boxes)
    ]
    return LiteralConjunction(all_preds)
예제 #7
0
def sample_problem(domain,
                   problem_dir,
                   problem_outfile,
                   num_locs,
                   min_extra_papers=1,
                   max_extra_papers=10):
    loc_type = domain.types['loc']
    paper_type = domain.types['paper']
    at = domain.predicates['at']
    isHomeBase = domain.predicates['ishomebase']
    wantsPaper = domain.predicates['wantspaper']
    unpacked = domain.predicates['unpacked']
    satisfied = domain.predicates['satisfied']

    # Create objects and state
    state = set()
    objects = set()
    home_loc = None
    target_locs = []
    # Add locations
    for loc_idx in range(num_locs):
        loc = loc_type(f"loc-{loc_idx}")
        objects.add(loc)
        # home
        if loc_idx == 0:
            state.add(isHomeBase(loc))
            state.add(at(loc))
            home_loc = loc
        # wants paper
        else:
            state.add(wantsPaper(loc))
            target_locs.append(loc)
    # Add papers
    num_papers = num_locs + np.random.randint(min_extra_papers,
                                              max_extra_papers + 1)
    for paper_idx in range(num_papers):
        paper = paper_type(f"paper-{paper_idx}")
        objects.add(paper)
        state.add(unpacked(paper))

    # Create goal
    goal_lits = [satisfied(loc) for loc in target_locs]
    goal = LiteralConjunction(goal_lits)

    filepath = os.path.join(PDDLDIR, problem_dir, problem_outfile)

    PDDLProblemParser.create_pddl_file(
        filepath,
        objects=objects,
        initial_state=state,
        problem_name="newspaper",
        domain_name=domain.domain_name,
        goal=goal,
        fast_downward_order=True,
    )
    print("Wrote out to {}.".format(filepath))
예제 #8
0
def create_goal(domain, balls, rooms, num_balls):
    at = domain.predicates['at']

    goal_balls = [balls[i] for i in np.random.choice(len(balls), replace=False, size=num_balls)]
    goal_lits = []

    for ball in goal_balls:
        room = rooms[np.random.choice(len(rooms))]
        goal_lits.append(at(ball, room))

    return LiteralConjunction(goal_lits)
 def _foldt_to_operators(self, dt, action_name, suffix=''):
     op_counter = 0
     operators = set()
     for (path, leaf) in dt.get_conditional_literals(dt.root):
         if leaf is None:
             continue
         if any(lit.predicate == Effect(self._NoChange) for lit in leaf):
             continue
         name = "LearnedOperator{}{}{}".format(action_name, op_counter,
                                               suffix)
         op_counter += 1
         # NoChange appears only in effects in the training data, so it
         # should never be in the preconditions of the learned operators.
         assert not any(lit.predicate.positive == self._NoChange
                        for lit in path)
         preconds = LiteralConjunction(path)
         effects = LiteralConjunction([effect_to_literal(l) for l in leaf])
         params = self._get_params_from_preconds(preconds)
         operator = Operator(name, params, preconds, effects)
         operators.add(operator)
     return operators
예제 #10
0
 def _replace_predicate(cls, conds, from_pred, to_pred):
     if isinstance(conds, list):
         return [cls._replace_predicate(c, from_pred, to_pred) for c in conds]
     if isinstance(conds, Literal):
         if conds.predicate == from_pred:
             return to_pred(*conds.variables)
         return conds
     if isinstance(conds, LiteralConjunction):
         return LiteralConjunction(cls._replace_predicate(conds.literals, from_pred, to_pred))
     if isinstance(conds, LiteralDisjunction):
         return LiteralDisjunction(cls._replace_predicate(conds.literals, from_pred, to_pred))
     if isinstance(conds, ForAll):
         assert not conds.is_negative, "Negative universal quantification not implemented (use Exists instead)"
         return ForAll(cls._replace_predicate(conds.body, from_pred, to_pred), conds.variables, 
                       is_negative=conds.is_negative)
     if isinstance(conds, Exists):
         assert not conds.is_negative, "Negative exisential quantification not implemented (use ForAll instead)"
         return Exists(conds.variables,cls._replace_predicate(conds.body, from_pred, to_pred),
                       is_negative=conds.is_negative)
     import ipdb; ipdb.set_trace()
     raise NotImplementedError()
예제 #11
0
def create_problem(grid, domain, problem_dir, problem_outfile):
    
    # Create location objects
    loc_type = domain.types['loc']
    objects = set()
    grid_locs = np.empty(grid.shape, dtype=object)
    for r in range(grid.shape[0]):
        for c in range(grid.shape[1]):
            obj = loc_type(f'r{r}_c{c}')
            objects.add(obj)
            grid_locs[r, c] = obj

    initial_state = set()

    # Add at, isWater, isHill, isGoal
    at = domain.predicates['at']
    isWater = domain.predicates['iswater']
    isHill = domain.predicates['ishill']
    isGoal = domain.predicates['isgoal']
    for r in range(grid.shape[0]):
        for c in range(grid.shape[1]):
            obj = grid_locs[r, c]
            if grid[r, c] == I:
                initial_state.add(at(obj))
            elif grid[r, c] == W:
                initial_state.add(isWater(obj))
            elif grid[r, c] == H:
                initial_state.add(isHill(obj))
            elif grid[r, c] == G:
                initial_state.add(isGoal(obj))

    # Add adjacent
    adjacent = domain.predicates['adjacent']

    def get_neighbors(r, c):
        for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
            nr = r + dr
            nc = c + dc
            if 0 <= nr < grid.shape[0] and 0 <= nc < grid.shape[1]:
                yield (nr, nc)

    for r in range(grid.shape[0]):
        for c in range(grid.shape[1]):    
            obj = grid_locs[r, c]
            for (nr, nc) in get_neighbors(r, c):
                nobj = grid_locs[nr, nc]
                initial_state.add(adjacent(obj, nobj))

    # Add onTrail
    onTrail = domain.predicates['ontrail']

    # Get the path
    path = []
    r, c = np.argwhere(grid == I)[0]
    while True:
        path.append((r, c))
        if grid[r, c] == G:
            break
        for (nr, nc) in get_neighbors(r, c):
            if (nr, nc) in path:
                continue
            if grid[nr, nc] in [P, G, H]:
                r, c = nr, nc
                break
        else:
            raise Exception("Should not happen")

    for (r, c), (nr, nc) in zip(path[:-1], path[1:]):
        obj = grid_locs[r, c]
        nobj = grid_locs[nr, nc]
        initial_state.add(onTrail(obj, nobj))

    # Goal
    goal_rcs = np.argwhere(grid == G)
    assert len(goal_rcs) == 1
    goal_r, goal_c = goal_rcs[0]
    goal_obj = grid_locs[goal_r, goal_c]
    goal = LiteralConjunction([at(goal_obj)])

    filepath = os.path.join(PDDLDIR, problem_dir, problem_outfile)

    PDDLProblemParser.create_pddl_file(
        filepath,
        objects=objects,
        initial_state=initial_state,
        problem_name="hiking",
        domain_name=domain.domain_name,
        goal=goal,
        fast_downward_order=True,
    )
    print("Wrote out to {}.".format(filepath))
예제 #12
0
 def _parse_into_literal(self, string, params, is_effect=False):
     """Parse the given string (representing either preconditions or effects)
     into a literal. Check against params to make sure typing is correct.
     """
     assert string[0] == "("
     assert string[-1] == ")"
     if string.startswith("(and") and string[4] in (" ", "\n", "("):
         clauses = self._find_all_balanced_expressions(string[4:-1].strip())
         return LiteralConjunction([
             self._parse_into_literal(clause, params, is_effect=is_effect)
             for clause in clauses
         ])
     if string.startswith("(or") and string[3] in (" ", "\n", "("):
         clauses = self._find_all_balanced_expressions(string[3:-1].strip())
         return LiteralDisjunction([
             self._parse_into_literal(clause, params, is_effect=is_effect)
             for clause in clauses
         ])
     if string.startswith("(forall") and string[7] in (" ", "\n", "("):
         new_binding, clause = self._find_all_balanced_expressions(
             string[7:-1].strip())
         new_name, new_type_name = new_binding.strip()[1:-1].split("-")
         new_name = new_name.strip()
         new_type_name = new_type_name.strip()
         assert new_name not in params, "ForAll variable {} already exists".format(
             new_name)
         params[new_name] = self.types[new_type_name]
         result = ForAll(
             self._parse_into_literal(clause, params, is_effect=is_effect),
             TypedEntity(new_name, params[new_name]))
         del params[new_name]
         return result
     if string.startswith("(exists") and string[7] in (" ", "\n", "("):
         new_binding, clause = self._find_all_balanced_expressions(
             string[7:-1].strip())
         if new_binding[1:-1] == "":
             # Handle existential goal with no arguments.
             body = self._parse_into_literal(clause,
                                             params,
                                             is_effect=is_effect)
             return body
         variables = self._parse_objects(new_binding[1:-1])
         for v in variables:
             params[v.name] = v.var_type
         body = self._parse_into_literal(clause,
                                         params,
                                         is_effect=is_effect)
         result = Exists(variables, body)
         for v in variables:
             del params[v.name]
         return result
     if string.startswith("(probabilistic") and string[14] in (" ", "\n",
                                                               "("):
         assert is_effect, "We only support probabilistic effects"
         lits = []
         probs = []
         expr = string[14:-1].strip()
         for match in re.finditer("(\d*\.?\d+)", expr):
             prob = float(match.group())
             subexpr = self._find_balanced_expression(
                 expr[match.end():].strip(), 0)
             lit = self._parse_into_literal(subexpr,
                                            params,
                                            is_effect=is_effect)
             lits.append(lit)
             probs.append(prob)
         return ProbabilisticEffect(lits, probs)
     if string.startswith("(not") and string[4] in (" ", "\n", "("):
         clause = string[4:-1].strip()
         if is_effect:
             return Anti(
                 self._parse_into_literal(clause,
                                          params,
                                          is_effect=is_effect))
         else:
             return Not(
                 self._parse_into_literal(clause,
                                          params,
                                          is_effect=is_effect))
     string = string[1:-1].split()
     pred, args = string[0], string[1:]
     typed_args = []
     # Validate types against the given params dict.
     assert pred in self.predicates, "Predicate {} is not defined".format(
         pred)
     assert self.predicates[pred].arity == len(args), pred
     for i, arg in enumerate(args):
         if arg not in params:
             raise Exception("Argument {} not in params {}".format(
                 arg, params))
         assert arg in params, "Argument {} is not in the params".format(
             arg)
         if isinstance(params, dict):
             typed_arg = TypedEntity(arg, params[arg])
         else:
             typed_arg = params[params.index(arg)]
         typed_args.append(typed_arg)
     return self.predicates[pred](*typed_args)
예제 #13
0
 def _parse_into_literal(self, string, params, is_effect=False):
     """Parse the given string (representing either preconditions or effects)
     into a literal. Check against params to make sure typing is correct.
     """
     assert string[0] == "("
     assert string[-1] == ")"
     if string.startswith("(and") and string[4] in (" ", "\n", "("):
         clauses = self._find_all_balanced_expressions(string[4:-1].strip())
         return LiteralConjunction([
             self._parse_into_literal(clause, params, is_effect=is_effect)
             for clause in clauses
         ])
     if string.startswith("(or") and string[3] in (" ", "\n", "("):
         clauses = self._find_all_balanced_expressions(string[3:-1].strip())
         return LiteralDisjunction([
             self._parse_into_literal(clause, params, is_effect=is_effect)
             for clause in clauses
         ])
     if string.startswith("(forall") and string[7] in (" ", "\n", "("):
         new_binding, clause = self._find_all_balanced_expressions(
             string[7:-1].strip())
         new_name, new_type_name = new_binding.strip()[1:-1].split("-")
         new_name = new_name.strip()
         new_type_name = new_type_name.strip()
         assert new_name not in params, "ForAll variable {} already exists".format(
             new_name)
         params[new_name] = self.types[new_type_name]
         result = ForAll(
             self._parse_into_literal(clause, params, is_effect=is_effect),
             TypedEntity(new_name, params[new_name]))
         del params[new_name]
         return result
     if string.startswith("(exists") and string[7] in (" ", "\n", "("):
         new_binding, clause = self._find_all_balanced_expressions(
             string[7:-1].strip())
         variables = self._parse_objects(new_binding[1:-1])
         for v in variables:
             params[v.name] = v.var_type
         body = self._parse_into_literal(clause,
                                         params,
                                         is_effect=is_effect)
         result = Exists(variables, body)
         for v in variables:
             del params[v.name]
         return result
     if string.startswith("(not") and string[4] in (" ", "\n", "("):
         clause = string[4:-1].strip()
         if is_effect:
             return Anti(
                 self._parse_into_literal(clause,
                                          params,
                                          is_effect=is_effect))
         else:
             return Not(
                 self._parse_into_literal(clause,
                                          params,
                                          is_effect=is_effect))
     string = string[1:-1].split()
     pred, args = string[0], string[1:]
     # Validate types against the given params dict.
     assert pred in self.predicates, "Predicate {} is not defined".format(
         pred)
     assert self.predicates[pred].arity == len(args), pred
     for i, arg in enumerate(args):
         if arg not in params:
             import ipdb
             ipdb.set_trace()
         assert arg in params, "Argument {} is not in the params".format(
             arg)
     return self.predicates[pred](*args)
예제 #14
0
    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
예제 #15
0
def find_ff_replan_policy(ndr_operators, action_space, observation_space):
    # First pull out the most likely effect per NDR to form
    # deterministic operators
    deterministic_operators = []
    for ndr_list in ndr_operators.values():
        for i, ndr in enumerate(ndr_list):
            op_name = "{}{}".format(ndr.action.predicate.name, i)
            probs, effs = ndr.effect_probs, ndr.effects
            max_idx = np.argmax(probs)
            max_effects = LiteralConjunction(sorted(effs[max_idx]))
            if len(max_effects.literals
                   ) == 0 or NOISE_OUTCOME in max_effects.literals:
                continue
            preconds = LiteralConjunction(
                sorted(ndr.preconditions) + [ndr.action])
            params = sorted(
                {v
                 for lit in preconds.literals for v in lit.variables})
            operator = Operator(op_name, params, preconds, max_effects)
            deterministic_operators.append(operator)

    domain_name = "mydomain"
    planner = FastForwardPlanner(deterministic_operators, domain_name,
                                 action_space, observation_space)

    # Only replan if outcome is not expected
    expected_next_state = None
    plan = []

    def get_next_expected_state(state, action):
        return ndr_operators[action.predicate].predict_max(state, action)

    # Given a state, replan and execute first section in plan
    def policy(obs):
        nonlocal expected_next_state
        nonlocal plan

        state = obs.literals
        goal = obs.goal
        objects = obs.objects

        if False:  #len(plan) > 0:
            expected_next_state = get_next_expected_state(state, plan[0])
            return plan.pop(0)

        # Add possible actions to state
        full_state = set(state)
        full_state.update(action_space.all_ground_literals(obs))

        # Create problem file
        fname = '/tmp/problem.pddl'
        PDDLProblemParser.create_pddl_file(fname, objects, full_state,
                                           "myproblem", domain_name, goal)
        # Get plan
        print("goal:", goal)
        try:
            plan = planner.get_plan(fname, use_cache=False)
            print("plan:", plan)
        except NoPlanFoundException:
            # Default to random
            print("no plan found")
            return action_space.sample(obs)
        # Updated expected next state
        expected_next_state = get_next_expected_state(state, plan[0])
        return plan.pop(0)

    return policy