Source code for unified_planning.model.motion.scheduling_motion_problem

# Copyright 2021-2023 AIPlan4EU project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from typing import Optional, List, Dict, Tuple

import unified_planning as up
from unified_planning.model.expression import ConstantExpression
from unified_planning.model.scheduling import SchedulingProblem
from unified_planning.model.motion import MotionActivity
from unified_planning.exceptions import UPTypeError
from unified_planning.model.mixins import (
    UserTypesSetMixin,
    TimeModelMixin,
    FluentsSetMixin,
    ObjectsSetMixin,
    InitialStateMixin,
    MetricsMixin,
)


[docs] class SchedulingMotionProblem(SchedulingProblem): """ This class represents a scheduling and motion planning problem (`SAMP`). It extends a `SchedulingProblem` with `MotionActivity` objects and with the initial configuration of the movable objects, so that the schedule of the activities is constrained by the geometric motions the movable objects must perform. """ def __init__( self, name: Optional[str] = None, environment: Optional["up.environment.Environment"] = None, *, initial_defaults: Dict["up.model.types.Type", "ConstantExpression"] = {}, ): SchedulingProblem.__init__( self, name, environment, initial_defaults=initial_defaults ) self._motion_activities: List[MotionActivity] = [] self._initial_configuration: List[ Tuple["up.model.FNode", "up.model.FNode"] ] = [] def __repr__(self) -> str: s = [super().__repr__()] s.append("initial configuration:") for movable, config in self._initial_configuration: s.append(f" {movable}: {config}") return "\n".join(s) def __eq__(self, oth: object) -> bool: if not isinstance(oth, SchedulingMotionProblem): return False return super().__eq__(oth) and self._motion_activities == oth._motion_activities def __hash__(self) -> int: return super().__hash__() @property def kind(self) -> "up.model.problem_kind.ProblemKind": problem_kind = super().kind problem_kind.set_problem_class("SAMP") return problem_kind
[docs] def clone(self): """Returns an equivalent problem.""" new_p = SchedulingMotionProblem(self._name, self._env) UserTypesSetMixin._clone_to(self, new_p) ObjectsSetMixin._clone_to(self, new_p) FluentsSetMixin._clone_to(self, new_p) TimeModelMixin._clone_to(self, new_p) InitialStateMixin._clone_to(self, new_p) MetricsMixin._clone_to(self, new_p, new_actions=None) new_p._base = self._base.clone() new_p._activities = [a.clone() for a in self._activities] new_p._motion_activities = [ a for a in new_p._activities if isinstance(a, MotionActivity) ] new_p._initial_configuration = list(self.initial_configuration) return new_p
[docs] def add_motion_activity( self, name: str, duration: int = 0, optional: bool = False ) -> "MotionActivity": """Adds a motion activity to the problem.""" act = MotionActivity(name, duration, optional) self._activities.append(act) self._motion_activities.append(act) return act
@property def motion_activities(self) -> List["MotionActivity"]: """Returns the list of motion activities in this problem.""" return self._motion_activities
[docs] def set_initial_configuration( self, movable: "up.model.expression.Expression", config: "up.model.expression.Expression", ): """Sets the initial configuration of the given movable object to the given configuration.""" (movable_exp, config_exp) = self.environment.expression_manager.auto_promote( movable, config ) if not self.environment.type_checker.get_type(movable_exp).is_movable_type(): raise UPTypeError("movable parameter must be of movable type!") if not self.environment.type_checker.get_type( config_exp ).is_configuration_type(): raise UPTypeError("config parameter must be of configuration type!") self._initial_configuration.append((movable_exp, config_exp))
@property def initial_configuration(self) -> List[Tuple["up.model.FNode", "up.model.FNode"]]: """Returns the list of `(movable, configuration)` pairs defining the initial configuration of the movable objects.""" return self._initial_configuration