Source code for discrete_optimization.jsp.solvers.optal

#  Copyright (c) 2025 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.
#  JSP solver using OptalCp solver, see installation instruction on their
import datetime
import os
from typing import Any, Optional

from discrete_optimization.generic_tools.cp_tools import ParametersCp
from discrete_optimization.generic_tools.do_problem import (
    ParamsObjectiveFunction,
    Solution,
)
from discrete_optimization.generic_tools.hub_solver.optal.generic_optal import (
    OptalSolver,
)
from discrete_optimization.generic_tools.hub_solver.optal.model_collections import (
    DoProblemEnum,
    problem_to_script_path,
)
from discrete_optimization.jsp.problem import JobShopProblem, JobShopSolution

script = problem_to_script_path[DoProblemEnum.JSP]


[docs] def from_jsp_to_jsplib(problem: JobShopProblem) -> str: output = "" # --- Header line: number of jobs and machines --- output += f"{problem.n_jobs} {problem.n_machines}\n" # --- Job lines --- for job in problem.list_jobs: line_items = [] for subjob in job: line_items.append(str(subjob.machine_id)) line_items.append(str(subjob.processing_time)) output += " ".join(line_items) + "\n" return output
[docs] class OptalJspSolver(OptalSolver): problem: JobShopProblem def __init__( self, problem: JobShopProblem, params_objective_function: Optional[ParamsObjectiveFunction] = None, **kwargs: Any, ): super().__init__(problem, params_objective_function, **kwargs) self._script_model = script
[docs] def retrieve_current_solution(self, dict_results: dict) -> Solution: sched = [[] for _ in range(self.problem.n_jobs)] for i in range(len(dict_results["startTimes"])): for j in range(len(dict_results["startTimes"][i])): sched[i].append( (dict_results["startTimes"][i][j], dict_results["endTimes"][i][j]) ) sol = JobShopSolution(problem=self.problem, schedule=sched) return sol
[docs] def build_command( self, parameters_cp: Optional[ParametersCp] = None, time_limit: int = 10, **args: Any, ): command_list = super().build_command( parameters_cp=parameters_cp, time_limit=time_limit, **args ) command_list += ["--outputjsp", self._result_path] return command_list
[docs] def init_model(self, **args: Any) -> None: output = from_jsp_to_jsplib(self.problem) d = datetime.datetime.now().timestamp() file_input_path = os.path.join(self.temp_directory, f"tmp-{d}.txt") logs_path = os.path.join(self.temp_directory, f"tmp-stats-{d}.json") result_path = os.path.join(self.temp_directory, f"solution-{d}.json") self._logs_path = logs_path self._result_path = result_path with open(file_input_path, "w") as f: f.write(output) self._file_input = file_input_path