Source code for discrete_optimization.generic_tasks_tools.multimode_scheduling

#  Copyright (c) 2026 AIRBUS and its affiliates.
#  This source code is licensed under the MIT license found in the
#  LICENSE file in the root directory of this source tree.
import logging
from abc import abstractmethod
from typing import Generic

from discrete_optimization.generic_tasks_tools.base import Task
from discrete_optimization.generic_tasks_tools.multimode import (
    MultimodeProblem,
    MultimodeSolution,
    SinglemodeProblem,
    SinglemodeSolution,
)
from discrete_optimization.generic_tasks_tools.scheduling import (
    SchedulingProblem,
    SchedulingSolution,
)

logger = logging.getLogger(__name__)


[docs] class MultimodeSchedulingProblem( SchedulingProblem[Task], MultimodeProblem[Task], Generic[Task], ): """Scheduling problem whose tasks durations depend only on mode."""
[docs] @abstractmethod def get_task_mode_duration(self, task: Task, mode: int) -> int: """Get task duration according to mode. Args: task: mode: not used for single-mode problems Returns: """ ...
[docs] class SinglemodeSchedulingProblem( SinglemodeProblem[Task], MultimodeSchedulingProblem[Task], ): """Single mode scheduling problems with fixed task durations. Utility class simplifying MultimodeSchedulingProblem when single mode only. """
[docs] @abstractmethod def get_task_duration(self, task: Task) -> int: """Get task duration according to mode. Args: task: Returns: """ ...
[docs] def get_task_mode_duration(self, task: Task, mode: int) -> int: return self.get_task_duration(task=task)
[docs] class MultimodeSchedulingSolution( SchedulingSolution[Task], MultimodeSolution[Task], Generic[Task], ): """Solution type associated to MultimodeSchedulingProblem.""" problem: MultimodeSchedulingProblem[Task]
[docs] def check_task_duration_constraint(self, task: Task) -> bool: return self.problem.get_task_mode_duration( task=task, mode=self.get_mode(task=task) ) == self.get_duration(task=task)
[docs] def check_duration_constraints(self) -> bool: check = all( self.check_task_duration_constraint(task=task) for task in self.problem.tasks_list ) if not check: for task in self.problem.tasks_list: if not self.check_task_duration_constraint(task=task): logger.debug( f"Duration of task {task} not consistent with the mode choice." ) break return check
[docs] class SinglemodeSchedulingSolution( SinglemodeSolution[Task], MultimodeSchedulingSolution[Task], ): """Solution for single mode scheduling problem with fixed task durations. Utility class useful when needing to derive from GenericSchedulingSolution without multi mode to be able to use cpsat auto solver. """