Пример #1
0
 def _handle_derived_literals(self, state):
     # first remove any old derived literals since they're outdated
     to_remove = set()
     for lit in state.literals:
         if lit.predicate.is_derived:
             to_remove.add(lit)
     state = state.with_literals(state.literals - to_remove)
     while True:  # loop, because derived predicates can be recursive
         new_derived_literals = set()
         for pred in self.domain.predicates.values():
             if not pred.is_derived:
                 continue
             assignments = find_satisfying_assignments(
                 state.literals,
                 pred.body,
                 type_to_parent_types=self.domain.type_to_parent_types,
                 constants=self.domain.constants,
                 mode="prolog",
                 max_assignment_count=99999)
             for assignment in assignments:
                 objects = [
                     assignment[param_type(param_name)]
                     for param_name, param_type in zip(
                         pred.param_names, pred.var_types)
                 ]
                 derived_literal = pred(*objects)
                 if derived_literal not in state.literals:
                     new_derived_literals.add(derived_literal)
         if new_derived_literals:
             state = state.with_literals(state.literals
                                         | new_derived_literals)
         else:  # terminate
             break
     return state
Пример #2
0
def _select_operator(state, action, domain, inference_mode="infer",
                     require_unique_assignment=True):
    """
    Helper for successor generation
    """
    if inference_mode == "infer":
        inference_mode = "csp" if _check_domain_for_strips(domain) else "prolog"

    if domain.operators_as_actions:
        # There should be only one possible operator if actions are operators
        possible_operators = set()
        for name, operator in domain.operators.items():
            if name.lower() == action.predicate.name.lower():
                assert len(possible_operators) == 0
                possible_operators.add(operator)
    else:
        # Possibly multiple operators per action
        possible_operators = set(domain.operators.values())

    # Knowledge base: literals in the state + action taken
    kb = set(state.literals) | {action}

    selected_operator = None
    assignment = None
    for operator in possible_operators:
        if isinstance(operator.preconds, Literal):
            conds = [operator.preconds]
        else:
            conds = operator.preconds.literals
        # Necessary for binding the operator arguments to the variables
        if domain.operators_as_actions:
            conds = [action.predicate(*operator.params)] + conds
        # Check whether action is in the preconditions
        action_literal = None
        for lit in conds: 
            if lit.predicate == action.predicate:
                action_literal = lit
                break
        if action_literal is None:
            continue
        # For proving, consider action variable first
        action_variables = action_literal.variables
        variable_sort_fn = lambda v : (not v in action_variables, v)
        assignments = find_satisfying_assignments(kb, conds,
            variable_sort_fn=variable_sort_fn,
            type_to_parent_types=domain.type_to_parent_types,
            constants=domain.constants,
            mode=inference_mode)
        num_assignments = len(assignments)
        if num_assignments > 0:
            if require_unique_assignment:
                assert num_assignments == 1, "Nondeterministic envs not supported"
            selected_operator = operator
            assignment = assignments[0]
            break

    return selected_operator, assignment
Пример #3
0
def test_negative_preconditions():
    MoveableType = Type('moveable')
    Holding = Predicate('Holding', 1, var_types=[MoveableType])
    IsPawn = Predicate('IsPawn', 1, var_types=[MoveableType])
    PutOn = Predicate('PutOn', 1, var_types=[MoveableType])
    On = Predicate('On', 2, var_types=[MoveableType, MoveableType])

    # ?x0 must bind to o0 and ?x1 must bind to o1, so ?x2 must bind to o2
    conds = [
        PutOn("?x0"),
        Holding("?x1"),
        IsPawn("?x2"),
        Not(On("?x2", "?x0"))
    ]
    kb = {
        PutOn('o0'),
        IsPawn('o0'),
        IsPawn('o1'),
        IsPawn('o2'),
        Holding('o1'),
    }
    assignments = find_satisfying_assignments(kb,
                                              conds,
                                              allow_redundant_variables=False)
    assert len(assignments) == 1

    # should be the same, even though IsPawn("?x2") is removed
    conds = [PutOn("?x0"), Holding("?x1"), Not(On("?x2", "?x0"))]
    kb = {
        PutOn('o0'),
        IsPawn('o0'),
        IsPawn('o1'),
        IsPawn('o2'),
        Holding('o1'),
    }
    assignments = find_satisfying_assignments(kb,
                                              conds,
                                              allow_redundant_variables=False)
    assert len(assignments) == 1

    print("Pass.")
Пример #4
0
 def _preconds_satisfied(state, action, literals):
     """Helper method for _get_predicted_next_state.
     """
     kb = state.literals | {action}
     assignments = find_satisfying_assignments(kb, literals)
     # NOTE: unlike in the actual environment, here num_found could be
     # greater than 1. This is because the learned operators can be
     # wrong by being overly vague, so that multiple assignments get
     # found. Here, if num_found is greater than 1, we just use the first.
     if len(assignments) == 1:
         return assignments[0]
     return None
Пример #5
0
    def _select_operator(self, state, action):
        """
        Helper function for step.
        """
        if self.operators_as_actions:
            # There should be only one possible operator if actions are operators
            possible_operators = set()
            for name, operator in self.domain.operators.items():
                if name.lower() == action.predicate.name.lower():
                    assert len(possible_operators) == 0
                    possible_operators.add(operator)
        else:
            # Possibly multiple operators per action
            possible_operators = set(self.domain.operators.values())

        # Knowledge base: literals in the state + action taken
        kb = self._get_observation(state) | {action}

        selected_operator = None
        assignment = None
        for operator in possible_operators:
            if isinstance(operator.preconds, Literal):
                conds = [operator.preconds]
            else:
                conds = operator.preconds.literals
            # Necessary for binding the operator arguments to the variables
            if self.operators_as_actions:
                conds = [action.predicate(*operator.params)] + conds
            # Check whether action is in the preconditions
            action_literal = None
            for lit in conds:
                if lit.predicate == action.predicate:
                    action_literal = lit
                    break
            if action_literal is None:
                continue
            # For proving, consider action variable first
            action_variables = action_literal.variables
            variable_sort_fn = lambda v: (not v in action_variables, v)
            assignments = find_satisfying_assignments(
                kb,
                conds,
                variable_sort_fn=variable_sort_fn,
                type_to_parent_types=self.domain.type_to_parent_types)
            num_assignments = len(assignments)
            if num_assignments > 0:
                assert num_assignments == 1, "Nondeterministic envs not supported"
                selected_operator = operator
                assignment = assignments[0]
                break

        return selected_operator, assignment
Пример #6
0
def test_zero_arity_negative_preconditions():
    MoveableType = Type('moveable')
    Holding = Predicate('Holding', 1, var_types=[MoveableType])
    HandEmpty = Predicate('HandEmpty', 0, var_types=[])

    conds = [Holding("?x1"), Not(HandEmpty())]
    kb = {Holding("a"), HandEmpty()}
    assignments = find_satisfying_assignments(kb,
                                              conds,
                                              allow_redundant_variables=False)
    assert len(assignments) == 0

    print("Pass.")
Пример #7
0
    def _select_operator(self, action):
        """
        Helper function for step.
        """
        # Knowledge base: literals in the state + action taken
        kb = self._get_observation() | {action}

        selected_operator = None
        assignment = None
        for operator in self.domain.operators.values():
            conds = operator.preconds.literals
            assignments = find_satisfying_assignments(kb, conds)
            num_assignments = len(assignments)
            if num_assignments > 0:
                assert num_assignments == 1, "Nondeterministic envs not supported"
                selected_operator = operator
                assignment = assignments[0]
                break

        return selected_operator, assignment
Пример #8
0
 def find_substitutions(self, state, action):
     """Find a mapping from variables to objects in the state
     and action. If non-unique or none, return None.
     """
     cache_key = hash((frozenset(state), action))
     if cache_key not in self._precondition_cache:
         kb = state | {action}
         assert action.predicate == self.action.predicate
         conds = [self.action] + list(self.preconditions)
         assignments = find_satisfying_assignments(
             kb,
             conds,
             allow_redundant_variables=self._allow_redundant_variables)
         if len(assignments) != 1:
             result = None
         else:
             result = assignments[0]
             if not self._allow_redundant_variables:
                 assert len(result.values()) == len(set(result.values()))
         self._precondition_cache[cache_key] = result
     return self._precondition_cache[cache_key]
Пример #9
0
 def _compute_lifted_mutex_literals(self, initial_state):
     """Lifted mutex computation using MMM sampling-based algorithm.
     """
     print("Computing mutexes...(cache size = {})".format(
         len(self._mutex_cache)))
     if initial_state.literals in self._mutex_cache:
         mutex_pairs = self._mutex_cache[initial_state.literals]
         print("\tUsing cache with {} mutex pairs".format(len(mutex_pairs)))
         return mutex_pairs
     reachable_states = set()
     start_time = time.time()
     print("\tStep 1/2: constructing reachable states...")
     for _1 in range(ac.mutex_num_episodes[self._domain_name]):
         state = initial_state
         reachable_states.add(state.literals)
         for _2 in range(ac.mutex_episode_len[self._domain_name]):
             # Pick a random action.
             for _3 in range(ac.mutex_num_action_samples):
                 action = self._action_space.sample(state)
                 ground_effects = self._get_ground_effects(state, action)
                 if ground_effects is None:
                     continue
                 state = self._execute_effects(state, ground_effects)
                 reachable_states.add(state.literals)
                 break
     print("\tStep 2/2: finding mutex pairs...")
     mutex_pairs = set()
     for pred_pair in itertools.combinations(
             self._observation_space.predicates, 2):
         ph_to_pred_slot = {}
         lit_pair_with_phs = []
         # Create the placeholders
         for i, pred in enumerate(pred_pair):
             ph_for_lit = []
             for j, var_type in enumerate(pred.var_types):
                 ph = var_type('ph{}_{}'.format(i, j))
                 ph_to_pred_slot[ph] = (i, j)
                 ph_for_lit.append(ph)
             ph_lit = pred(*ph_for_lit)
             lit_pair_with_phs.append(ph_lit)
         phs = sorted(ph_to_pred_slot.keys())
         # Consider all substitutions of placeholders to variables
         for vs in self._iter_vars_from_phs(phs):
             lit_pair = [copy.deepcopy(lit) for lit in lit_pair_with_phs]
             # Perform substitution
             for k, v in enumerate(vs):
                 ph = phs[k]
                 (i, j) = ph_to_pred_slot[ph]
                 lit_pair[i].update_variable(j, v)
             # Lits cannot have repeated vars
             pair_valid = True
             for lit in lit_pair:
                 if len(set(lit.variables)) != len(lit.variables):
                     pair_valid = False
                     break
             if pair_valid:
                 # Call it mutex if it can't bind to any of the reachable states.
                 if not any(
                         len(
                             find_satisfying_assignments(
                                 state_lits, lit_pair)) > 0
                         for state_lits in reachable_states):
                     mutex_pairs.add(frozenset(lit_pair))
     print("\tFound {} mutex pairs in {} seconds".format(
         len(mutex_pairs),
         time.time() - start_time))
     self._mutex_cache[initial_state.literals] = mutex_pairs
     return mutex_pairs
Пример #10
0
def test_prover():
    TType = Type('t')
    atom0, atom1, atom2 = TType('atom0'), TType('atom1'), TType('atom2')
    var0, var1, var2, var3 = TType('Var0'), TType('Var1'), TType(
        'Var2'), TType('Var3')

    # Single predicate single arity test
    predicate0 = Predicate('Predicate0', 1, [TType])
    predicate1 = Predicate('Predicate1', 2, [TType, TType])
    predicate2 = Predicate('Predicate2', 1, [TType])

    kb0 = [predicate0(atom0)]
    assignments = find_satisfying_assignments(kb0, [predicate0(var0)])
    assert len(assignments) == 1
    assert len(assignments[0]) == 1
    assert assignments[0][var0] == atom0

    assignments = find_satisfying_assignments(
        kb0, [predicate0(var0), predicate0(var1)])
    assert len(assignments) == 1

    kb1 = [predicate0(atom0), predicate0(atom1)]

    assignments = find_satisfying_assignments(kb1, [predicate0(var0)])
    assert len(assignments) == 2

    assignments = find_satisfying_assignments(
        kb1, [predicate0(var0), predicate0(var1)])
    assert len(assignments) == 2

    assignments = find_satisfying_assignments(
        kb1, [predicate0(var0),
              predicate0(var1),
              predicate0(var2)])
    assert len(assignments) == 2

    kb2 = [predicate0(atom0), predicate0(atom1), predicate0(atom2)]

    assignments = find_satisfying_assignments(kb2, [predicate0(var0)])
    assert len(assignments) == 2

    assignments = find_satisfying_assignments(
        kb2, [predicate0(var0), predicate0(var1)])
    assert len(assignments) == 2

    assignments = find_satisfying_assignments(
        kb2, [predicate0(var0),
              predicate0(var1),
              predicate0(var2)])
    assert len(assignments) == 2

    # Single predicate multiple arity test
    kb3 = [predicate1(atom0, atom1), predicate1(atom1, atom2)]

    assignments = find_satisfying_assignments(kb3, [predicate1(var0, var1)])
    assert len(assignments) == 2

    assignments = find_satisfying_assignments(
        kb3, [predicate1(var0, var1),
              predicate1(var1, var2)])
    assert len(assignments) == 1

    assignments = find_satisfying_assignments(
        kb3, [predicate1(var0, var1),
              predicate1(var1, var0)])
    assert len(assignments) == 0

    assignments = find_satisfying_assignments(
        kb3, [predicate1(var0, var1),
              predicate1(var2, var3)])
    assert len(assignments) == 2

    ## Multiple predicate multiple arity test
    kb4 = [
        predicate0(atom2),
        predicate1(atom0, atom1),
        predicate1(atom1, atom2)
    ]

    assignments = find_satisfying_assignments(
        kb4, [predicate1(var0, var1),
              predicate0(var1),
              predicate0(var0)])
    assert len(assignments) == 0

    ## Tricky case!
    kb6 = [
        predicate0(atom0),
        predicate2(atom1),
        predicate1(atom0, atom2),
        predicate1(atom2, atom1)
    ]

    assignments = find_satisfying_assignments(
        kb6, [predicate0(var0),
              predicate2(var1),
              predicate1(var0, var1)])
    assert len(assignments) == 0

    print("Pass.")