Beispiel #1
0
    def _convert_action_instance(
        self, msg: proto.ActionInstance, problem: Problem
    ) -> Union[Tuple[model.timing.Timing, unified_planning.plan.ActionInstance,
                     model.timing.Duration],
               unified_planning.plan.ActionInstance]:
        # action instance paramaters are atoms but in UP they are FNodes
        # converting to up.model.FNode
        parameters = tuple(
            [self.convert(param, problem) for param in msg.parameters])

        action_instance = unified_planning.plan.ActionInstance(
            problem.action(msg.action_name),
            parameters,
        )

        start_time = (self.convert(msg.start_time)
                      if msg.HasField("start_time") else None)
        end_time = self.convert(
            msg.end_time) if msg.HasField("end_time") else None
        if start_time is not None:
            return (
                start_time,  # Absolute Start Time
                action_instance,
                end_time - start_time if end_time else None,  # Duration
            )
        else:
            return action_instance
Beispiel #2
0
    def _convert_metric(
        self, msg: proto.Metric, problem: Problem
    ) -> Union[metrics.MinimizeActionCosts,
               metrics.MinimizeSequentialPlanLength, metrics.MinimizeMakespan,
               metrics.MinimizeExpressionOnFinalState,
               metrics.MaximizeExpressionOnFinalState]:
        if msg.kind == proto.Metric.MINIMIZE_ACTION_COSTS:
            costs = {}
            for a, cost in msg.action_costs.items():
                costs[problem.action(a)] = self.convert(cost, problem)
            return metrics.MinimizeActionCosts(
                costs=costs,
                default=self.convert(msg.default_action_cost, problem)
                if msg.HasField("default_action_cost") else None,
            )

        elif msg.kind == proto.Metric.MINIMIZE_SEQUENTIAL_PLAN_LENGTH:
            return metrics.MinimizeSequentialPlanLength()

        elif msg.kind == proto.Metric.MINIMIZE_MAKESPAN:
            return metrics.MinimizeMakespan()

        elif msg.kind == proto.Metric.MINIMIZE_EXPRESSION_ON_FINAL_STATE:
            return metrics.MinimizeExpressionOnFinalState(
                expression=self.convert(msg.expression, problem))

        elif msg.kind == proto.Metric.MAXIMIZE_EXPRESSION_ON_FINAL_STATE:
            return metrics.MaximizeExpressionOnFinalState(
                expression=self.convert(msg.expression, problem))
        else:
            raise UPException(f"Unknown metric kind `{msg.kind}`")
Beispiel #3
0
    def _convert_atom(
            self, msg: proto.Atom, problem: Problem
    ) -> Union[model.FNode, model.Fluent, model.Object]:
        field = msg.WhichOneof("content")

        value = getattr(msg, field)
        if field == "int":
            return problem.env.expression_manager.Int(value)
        elif field == "real":
            return problem.env.expression_manager.Real(
                fractions.Fraction(value.numerator, value.denominator))
        elif field == "boolean":
            return problem.env.expression_manager.Bool(value)
        else:
            # If atom symbols, return the equivalent UP alternative
            # Note that parameters are directly handled at expression level
            if problem.has_object(value):
                return problem.env.expression_manager.ObjectExp(
                    obj=problem.object(value))
            else:
                return problem.fluent(value)
Beispiel #4
0
def convert_type_str(s: str, problem: Problem) -> model.types.Type:
    if s == "bool":
        return problem.env.type_manager.BoolType()
    elif s == "integer":
        return problem.env.type_manager.IntType()
    elif "integer[" in s:
        lb = int(s.split("[")[1].split(",")[0])
        ub = int(s.split(",")[1].split("]")[0])
        return problem.env.type_manager.IntType(lb, ub)
    elif s == "real":
        return problem.env.type_manager.RealType()
    elif "real[" in s:
        return problem.env.type_manager.RealType(
            lower_bound=fractions.Fraction(s.split("[")[1].split(",")[0]),
            upper_bound=fractions.Fraction(s.split(",")[1].split("]")[0]),
        )
    else:
        if " - " in s:
            return problem.user_type(s.split(" - ")[0])
        else:
            return problem.env.type_manager.UserType(s)
Beispiel #5
0
 def _convert_type_declaration(self, msg: proto.TypeDeclaration,
                               problem: Problem) -> model.Type:
     if msg.type_name == "bool":
         return problem.env.type_manager.BoolType()
     elif msg.type_name.startswith("integer["):
         tmp = msg.type_name.split("[")[1].split("]")[0].split(", ")
         return problem.env.type_manager.IntType(
             lower_bound=int(tmp[0]) if tmp[0] != "-inf" else None,
             upper_bound=int(tmp[1]) if tmp[1] != "inf" else None,
         )
     elif msg.type_name.startswith("real["):
         tmp = msg.type_name.split("[")[1].split("]")[0].split(", ")
         lower_bound = fractions.Fraction(
             tmp[0]) if tmp[0] != "-inf" else None
         upper_bound = fractions.Fraction(
             tmp[1]) if tmp[1] != "inf" else None
         return problem.env.type_manager.RealType(lower_bound=lower_bound,
                                                  upper_bound=upper_bound)
     else:
         parent = None
         if msg.parent_type != "":
             parent = problem.user_type(msg.parent_type)
         return problem.env.type_manager.UserType(msg.type_name, parent)
    def get_rewritten_problem(self) -> Problem:
        '''Creates a problem that is a copy of the original problem
        but every ngeative fluent into action preconditions or overall
        goal is replaced by the fluent representing his negative.'''
        if self._new_problem is not None:
            return self._new_problem

        if self._problem.kind.has_simulated_effects():  # type: ignore
            raise up.exceptions.UPUsageError(
                'NegativeConditionsRemover does not work with simulated effects'
            )

        #NOTE that a different environment might be needed when multi-threading
        self._new_problem = Problem(f'{self._name}_{self._problem.name}',
                                    self._env)
        for o in self._problem.all_objects:
            self._new_problem.add_object(o)
        assert self._new_problem is not None

        name_action_map: Dict[str, Union[InstantaneousAction,
                                         DurativeAction]] = {}
        for action in self._problem.actions:
            if isinstance(action, InstantaneousAction):
                new_action = action.clone()
                new_action.name = self.get_fresh_name(action.name)
                new_action.clear_preconditions()
                for p in action.preconditions:
                    np = self._fluent_remover.remove_negative_fluents(p)
                    new_action.add_precondition(np)
                for ce in new_action.conditional_effects:
                    ce.set_condition(
                        self._fluent_remover.remove_negative_fluents(
                            ce.condition))
                name_action_map[action.name] = new_action
            elif isinstance(action, DurativeAction):
                new_durative_action = action.clone()
                new_durative_action.name = self.get_fresh_name(action.name)
                new_durative_action.clear_conditions()
                for i, cl in action.conditions.items():
                    for c in cl:
                        nc = self._fluent_remover.remove_negative_fluents(c)
                        new_durative_action.add_condition(i, nc)
                for t, cel in new_durative_action.conditional_effects.items():
                    for ce in cel:
                        ce.set_condition(
                            self._fluent_remover.remove_negative_fluents(
                                ce.condition))
                name_action_map[action.name] = new_durative_action
            else:
                raise NotImplementedError

        for t, el in self._problem.timed_effects.items():
            for e in el:
                self._new_problem._add_effect_instance(t, e.clone())

        for t, el in self._new_problem.timed_effects.items():
            for e in el:
                if e.is_conditional():
                    e.set_condition(
                        self._fluent_remover.remove_negative_fluents(
                            e.condition))

        for i, gl in self._problem.timed_goals.items():
            for g in gl:
                ng = self._fluent_remover.remove_negative_fluents(g)
                self._new_problem.add_timed_goal(i, ng)

        for g in self._problem.goals:
            ng = self._fluent_remover.remove_negative_fluents(g)
            self._new_problem.add_goal(ng)

        #fluent_mapping is the map between a fluent and it's negation, when the
        # negation is None it means the fluent is never found in a negation into
        # every condititon analized before; therefore it does not need to exist.
        fluent_mapping = self._fluent_remover.fluent_mapping
        for f in self._problem.fluents:
            self._new_problem.add_fluent(f)
            fneg = fluent_mapping.get(f, None)
            if fneg is not None:
                self._new_problem.add_fluent(fneg)

        for fl, v in self._problem.initial_values.items():
            fneg = fluent_mapping.get(fl.fluent(), None)
            self._new_problem.set_initial_value(fl, v)
            if fneg is not None:
                if v.bool_constant_value():
                    self._new_problem.set_initial_value(
                        self._env.expression_manager.FluentExp(
                            fneg, tuple(fl.args)),
                        self._env.expression_manager.FALSE())
                else:
                    self._new_problem.set_initial_value(
                        self._env.expression_manager.FluentExp(
                            fneg, tuple(fl.args)),
                        self._env.expression_manager.TRUE())

        for action in self._problem.actions:
            if isinstance(action, InstantaneousAction):
                new_action = name_action_map[action.name]
                new_effects: List[Effect] = []
                for e in new_action.effects:
                    fl, v = e.fluent, e.value
                    fneg = fluent_mapping.get(fl.fluent(), None)
                    if fneg is not None:
                        simplified_not_v = self._simplifier.simplify(
                            self._env.expression_manager.Not(v))
                        new_effects.append(
                            Effect(
                                self._env.expression_manager.FluentExp(
                                    fneg, tuple(fl.args)), simplified_not_v,
                                e.condition, e.kind))
                for ne in new_effects:
                    new_action._add_effect_instance(ne)
                self._new_problem.add_action(new_action)
                self._old_to_new[action] = [new_action]
                self._new_to_old[new_action] = action
            elif isinstance(action, DurativeAction):
                new_durative_action = name_action_map[action.name]
                new_durative_action.set_duration_constraint(action.duration)

                for t, el in new_durative_action.effects.items():
                    for e in el:
                        fl, v = e.fluent, e.value
                        fneg = fluent_mapping.get(fl.fluent(), None)
                        if fneg is not None:
                            simplified_not_v = self._simplifier.simplify(
                                self._env.expression_manager.Not(v))
                            new_durative_action._add_effect_instance(
                                t,
                                Effect(
                                    self._env.expression_manager.FluentExp(
                                        fneg, tuple(fl.args)),
                                    simplified_not_v, e.condition, e.kind))
                self._new_problem.add_action(new_durative_action)
                self._old_to_new[action] = [new_durative_action]
                self._new_to_old[new_durative_action] = action
            else:
                raise NotImplementedError

        for t, el in self._new_problem.timed_effects.items():
            for e in el:
                fl, v = e.fluent, e.value
                fneg = fluent_mapping.get(fl.fluent(), None)
                if fneg is not None:
                    simplified_not_v = self._simplifier.simplify(
                        self._env.expression_manager.Not(v))
                    self._new_problem._add_effect_instance(
                        t,
                        Effect(
                            self._env.expression_manager.FluentExp(
                                fneg, tuple(fl.args)), simplified_not_v,
                            e.condition, e.kind))

        return self._new_problem
class NegativeConditionsRemover(Transformer):
    '''Negative conditions remover class:
    this class requires a problem and offers the capability
    to transform a problem with negative conditions into one
    without negative conditions.

    This is done by substituting every fluent that appears with a Not into the conditions
    with different fluent representing  his negation.'''
    def __init__(self, problem: Problem, name: str = 'ncrm'):
        Transformer.__init__(self, problem, name)
        #NOTE no simplification are made. But it's possible to add them in key points
        self._fluent_remover = NegativeFluentRemover(self, self._env)
        #Represents the map from the new action to the old action
        self._new_to_old: Dict[Action, Action] = {}
        #represents a mapping from the action of the original problem to action of the new one.
        self._old_to_new: Dict[Action, List[Action]] = {}

    def get_rewritten_problem(self) -> Problem:
        '''Creates a problem that is a copy of the original problem
        but every ngeative fluent into action preconditions or overall
        goal is replaced by the fluent representing his negative.'''
        if self._new_problem is not None:
            return self._new_problem

        if self._problem.kind.has_simulated_effects():  # type: ignore
            raise up.exceptions.UPUsageError(
                'NegativeConditionsRemover does not work with simulated effects'
            )

        #NOTE that a different environment might be needed when multi-threading
        self._new_problem = Problem(f'{self._name}_{self._problem.name}',
                                    self._env)
        for o in self._problem.all_objects:
            self._new_problem.add_object(o)
        assert self._new_problem is not None

        name_action_map: Dict[str, Union[InstantaneousAction,
                                         DurativeAction]] = {}
        for action in self._problem.actions:
            if isinstance(action, InstantaneousAction):
                new_action = action.clone()
                new_action.name = self.get_fresh_name(action.name)
                new_action.clear_preconditions()
                for p in action.preconditions:
                    np = self._fluent_remover.remove_negative_fluents(p)
                    new_action.add_precondition(np)
                for ce in new_action.conditional_effects:
                    ce.set_condition(
                        self._fluent_remover.remove_negative_fluents(
                            ce.condition))
                name_action_map[action.name] = new_action
            elif isinstance(action, DurativeAction):
                new_durative_action = action.clone()
                new_durative_action.name = self.get_fresh_name(action.name)
                new_durative_action.clear_conditions()
                for i, cl in action.conditions.items():
                    for c in cl:
                        nc = self._fluent_remover.remove_negative_fluents(c)
                        new_durative_action.add_condition(i, nc)
                for t, cel in new_durative_action.conditional_effects.items():
                    for ce in cel:
                        ce.set_condition(
                            self._fluent_remover.remove_negative_fluents(
                                ce.condition))
                name_action_map[action.name] = new_durative_action
            else:
                raise NotImplementedError

        for t, el in self._problem.timed_effects.items():
            for e in el:
                self._new_problem._add_effect_instance(t, e.clone())

        for t, el in self._new_problem.timed_effects.items():
            for e in el:
                if e.is_conditional():
                    e.set_condition(
                        self._fluent_remover.remove_negative_fluents(
                            e.condition))

        for i, gl in self._problem.timed_goals.items():
            for g in gl:
                ng = self._fluent_remover.remove_negative_fluents(g)
                self._new_problem.add_timed_goal(i, ng)

        for g in self._problem.goals:
            ng = self._fluent_remover.remove_negative_fluents(g)
            self._new_problem.add_goal(ng)

        #fluent_mapping is the map between a fluent and it's negation, when the
        # negation is None it means the fluent is never found in a negation into
        # every condititon analized before; therefore it does not need to exist.
        fluent_mapping = self._fluent_remover.fluent_mapping
        for f in self._problem.fluents:
            self._new_problem.add_fluent(f)
            fneg = fluent_mapping.get(f, None)
            if fneg is not None:
                self._new_problem.add_fluent(fneg)

        for fl, v in self._problem.initial_values.items():
            fneg = fluent_mapping.get(fl.fluent(), None)
            self._new_problem.set_initial_value(fl, v)
            if fneg is not None:
                if v.bool_constant_value():
                    self._new_problem.set_initial_value(
                        self._env.expression_manager.FluentExp(
                            fneg, tuple(fl.args)),
                        self._env.expression_manager.FALSE())
                else:
                    self._new_problem.set_initial_value(
                        self._env.expression_manager.FluentExp(
                            fneg, tuple(fl.args)),
                        self._env.expression_manager.TRUE())

        for action in self._problem.actions:
            if isinstance(action, InstantaneousAction):
                new_action = name_action_map[action.name]
                new_effects: List[Effect] = []
                for e in new_action.effects:
                    fl, v = e.fluent, e.value
                    fneg = fluent_mapping.get(fl.fluent(), None)
                    if fneg is not None:
                        simplified_not_v = self._simplifier.simplify(
                            self._env.expression_manager.Not(v))
                        new_effects.append(
                            Effect(
                                self._env.expression_manager.FluentExp(
                                    fneg, tuple(fl.args)), simplified_not_v,
                                e.condition, e.kind))
                for ne in new_effects:
                    new_action._add_effect_instance(ne)
                self._new_problem.add_action(new_action)
                self._old_to_new[action] = [new_action]
                self._new_to_old[new_action] = action
            elif isinstance(action, DurativeAction):
                new_durative_action = name_action_map[action.name]
                new_durative_action.set_duration_constraint(action.duration)

                for t, el in new_durative_action.effects.items():
                    for e in el:
                        fl, v = e.fluent, e.value
                        fneg = fluent_mapping.get(fl.fluent(), None)
                        if fneg is not None:
                            simplified_not_v = self._simplifier.simplify(
                                self._env.expression_manager.Not(v))
                            new_durative_action._add_effect_instance(
                                t,
                                Effect(
                                    self._env.expression_manager.FluentExp(
                                        fneg, tuple(fl.args)),
                                    simplified_not_v, e.condition, e.kind))
                self._new_problem.add_action(new_durative_action)
                self._old_to_new[action] = [new_durative_action]
                self._new_to_old[new_durative_action] = action
            else:
                raise NotImplementedError

        for t, el in self._new_problem.timed_effects.items():
            for e in el:
                fl, v = e.fluent, e.value
                fneg = fluent_mapping.get(fl.fluent(), None)
                if fneg is not None:
                    simplified_not_v = self._simplifier.simplify(
                        self._env.expression_manager.Not(v))
                    self._new_problem._add_effect_instance(
                        t,
                        Effect(
                            self._env.expression_manager.FluentExp(
                                fneg, tuple(fl.args)), simplified_not_v,
                            e.condition, e.kind))

        return self._new_problem

    def get_original_action(self, action: Action) -> Action:
        '''After the method get_rewritten_problem is called, this function maps
        the actions of the transformed problem into the actions of the original problem.'''
        return self._new_to_old[action]

    def get_transformed_actions(self, action: Action) -> List[Action]:
        '''After the method get_rewritten_problem is called, this function maps
        the actions of the original problem into the actions of the transformed problem.'''
        return self._old_to_new[action]
Beispiel #8
0
    def _convert_problem(self,
                         msg: proto.Problem,
                         env: Optional[Environment] = None) -> Problem:
        problem = Problem(name=msg.problem_name, env=env)

        for t in msg.types:
            problem._add_user_type(self.convert(t, problem))
        for obj in msg.objects:
            problem.add_object(self.convert(obj, problem))
        for f in msg.fluents:
            problem.add_fluent(
                self.convert(f, problem),
                default_initial_value=self.convert(f.default_value, problem)
                if f.HasField("default_value") else None,
            )
        for f in msg.actions:
            problem.add_action(self.convert(f, problem))
        for eff in msg.timed_effects:
            ot = self.convert(eff.occurrence_time, problem)
            effect = self.convert(eff.effect, problem)
            problem.add_timed_effect(
                timing=ot,
                fluent=effect.fluent,
                value=effect.value,
                condition=effect.condition,
            )

        for assign in msg.initial_state:
            problem.set_initial_value(
                fluent=self.convert(assign.fluent, problem),
                value=self.convert(assign.value, problem),
            )

        for g in msg.goals:
            goal = self.convert(g.goal, problem)
            if str(g.timing) == "":
                problem.add_goal(goal)
            else:
                timing = self.convert(g.timing)
                problem.add_timed_goal(interval=timing, goal=goal)

        for metric in msg.metrics:
            problem.add_quality_metric(self.convert(metric, problem))

        return problem