def minimal_covering_renamings(self, action, add_effect, inv_vars): """computes the minimal renamings of the action parameters such that the add effect is covered by the action. Each renaming is an constraint system""" # add_effect must be covered assigs = self.get_covering_assignments(inv_vars, add_effect.literal) # renaming of operator parameters must be minimal minimal_renamings = [] params = [p.name for p in action.parameters] for assignment in assigs: system = constraints.ConstraintSystem() system.add_assignment(assignment) mapping = assignment.get_mapping() if params: if len(params) == 2: n1 = params[0] n2 = params[1] if mapping.get(n1, n1) != mapping.get(n2, n2): negative_clause = constraints.NegativeClause([(n1, n2) ]) system.add_negative_clause(negative_clause) else: for (n1, n2) in itertools.combinations(params, 2): if mapping.get(n1, n1) != mapping.get(n2, n2): negative_clause = constraints.NegativeClause([ (n1, n2) ]) system.add_negative_clause(negative_clause) minimal_renamings.append(system) return minimal_renamings
def operator_too_heavy(self, h_action): # FOND for nondet_choice in h_action.effects: add_effects = [ eff for eff in nondet_choice if not eff.literal.negated and self.predicate_to_part.get(eff.literal.predicate) ] inv_vars = find_unique_variables(h_action, self) #if len(add_effects) <= 1: # return False for eff1, eff2 in itertools.combinations(add_effects, 2): system = constraints.ConstraintSystem() ensure_inequality(system, eff1.literal, eff2.literal) ensure_cover(system, eff1.literal, self, inv_vars) ensure_cover(system, eff2.literal, self, inv_vars) ensure_conjunction_sat(system, get_literals(h_action.precondition), get_literals(eff1.condition), get_literals(eff2.condition), [eff1.literal.negate()], [eff2.literal.negate()]) if system.is_solvable(): return True return False
def operator_too_heavy(self, h_action): inv_vars = find_unique_variables(h_action, self) for time in xrange(2): cond_time = 2 * time add_effects = [eff for eff in h_action.effects[time] if isinstance(eff.peffect, pddl.Literal) and not eff.peffect.negated and self.predicate_to_part.get(eff.peffect.predicate)] if len(add_effects) <= 1: continue for eff1, eff2 in itertools.combinations(add_effects, 2): system = constraints.ConstraintSystem() ensure_inequality(system, eff1.peffect, eff2.peffect) ensure_cover(system, eff1.peffect, self, inv_vars) ensure_cover(system, eff2.peffect, self, inv_vars) ensure_conjunction_sat(system, get_literals(h_action.condition[cond_time]), get_literals(eff1.condition[cond_time]), get_literals(eff2.condition[cond_time]), [eff1.peffect.negate()], [eff2.peffect.negate()]) if system.is_solvable(): return True return False
def unbalanced_renamings(self, del_effect, add_effect, inv_vars, lhs_by_pred, unbalanced_renamings): """returns the renamings from unbalanced renamings for which the del_effect does not balance the add_effect.""" system = constraints.ConstraintSystem() ensure_cover(system, del_effect.literal, self, inv_vars) # Since we may only rename the quantified variables of the delete effect # we need to check that "renamings" of constants are already implied by # the unbalanced_renaming (of the of the operator parameters). The # following system is used as a helper for this. It builds a conjunction # that formulates that the constants are NOT renamed accordingly. We # below check that this is impossible with each unbalanced renaming. check_constants = False constant_test_system = constraints.ConstraintSystem() for a, b in system.combinatorial_assignments[0][0].equalities: # first 0 because the system was empty before we called ensure_cover # second 0 because ensure_cover only adds assignments with one entry if b[0] != "?": check_constants = True neg_clause = constraints.NegativeClause([(a, b)]) constant_test_system.add_negative_clause(neg_clause) ensure_inequality(system, add_effect.literal, del_effect.literal) still_unbalanced = [] for renaming in unbalanced_renamings: if check_constants: new_sys = constant_test_system.combine(renaming) if new_sys.is_solvable(): # it is possible that the operator arguments are not # mapped to constants as required for covering the delete # effect still_unbalanced.append(renaming) continue new_sys = system.combine(renaming) if self.lhs_satisfiable(renaming, lhs_by_pred): implies_system = self.imply_del_effect(del_effect, lhs_by_pred) if not implies_system: still_unbalanced.append(renaming) continue new_sys = new_sys.combine(implies_system) if not new_sys.is_solvable(): still_unbalanced.append(renaming) return still_unbalanced
def imply_del_effect(self, del_effect, lhs_by_pred): """returns a constraint system that is solvable if lhs implies the del effect (only if lhs is satisfiable). If a solvable lhs never implies the del effect, return None.""" # del_effect.cond and del_effect.atom must be implied by lhs implies_system = constraints.ConstraintSystem() for literal in itertools.chain(get_literals(del_effect.condition), [del_effect.literal.negate()]): poss_assignments = [] for match in lhs_by_pred[literal.predicate]: if match.negated != literal.negated: continue else: a = constraints.Assignment(list(zip(literal.args, match.args))) poss_assignments.append(a) if not poss_assignments: return None implies_system.add_assignment_disjunction(poss_assignments) return implies_system
def unbalanced_renamings(self, del_effect, add_effect, inv_vars, lhs_by_pred, unbalanced_renamings): """returns the renamings from unbalanced renamings for which the del_effect does not balance the add_effect.""" system = constraints.ConstraintSystem() ensure_inequality(system, add_effect.literal, del_effect.literal) ensure_cover(system, del_effect.literal, self, inv_vars) still_unbalanced = [] for renaming in unbalanced_renamings: new_sys = system.combine(renaming) if self.lhs_satisfiable(renaming, lhs_by_pred): implies_system = self.imply_del_effect(del_effect, lhs_by_pred) if not implies_system: still_unbalanced.append(renaming) continue new_sys = new_sys.combine(implies_system) if not new_sys.is_solvable(): still_unbalanced.append(renaming) return still_unbalanced