airbus / scikit-decide

AI framework for Reinforcement Learning, Automated Planning and Scheduling
https://airbus.github.io/scikit-decide
MIT License
141 stars 27 forks source link

RCPSP DOSolver Error during solve #64

Closed elcombato closed 11 months ago

elcombato commented 3 years ago

The following minimal reproducible example always throws an error. Varying the domain setup slightly, will result in a successful solution. Either it is a bug or the error message should be more telling and explain why this cannot be solved.

from skdecide.hub.domain.rcpsp.rcpsp_sk import RCPSP
from skdecide.hub.solver.do_solver.do_solver_scheduling import DOSolver, SolvingMethod
from skdecide.hub.solver.sgs_policies.sgs_policies import PolicyMethodParams, BasePolicyMethod

domain = RCPSP(
    resource_names={'R1'},
    task_ids=[1, 2, 3],
    tasks_mode={
        1: {1: {'duration': 1, 'R1': 0}},
        2: {1: {'duration': 2, 'R1': 1}},
        3: {1: {'duration': 1, 'R1': 0}}
    },
    successors={1: [], 2: [], 3: []},
    resource_availability={'R1': 4},
    resource_renewable={'R1': True},
    max_horizon=100
)

state = domain.get_initial_state()

solver = DOSolver(
    policy_method_params=PolicyMethodParams(
        base_policy_method=BasePolicyMethod.SGS_PRECEDENCE
    ),
    method=SolvingMethod.CP
)
solver.solve(domain_factory=lambda: domain)

This line triggers the following error https://github.com/airbus/scikit-decide/blob/d4c5ae70cbe8b4c943eafa8439348291ed07dec1/skdecide/discrete_optimization/rcpsp/rcpsp_model.py#L139

Traceback of error message:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.8/site-packages/skdecide/solvers.py", line 163, in solve
    return self._solve(domain_factory)
  File "/usr/local/lib/python3.8/site-packages/skdecide/solvers.py", line 184, in _solve
    return self._solve_domain(cast_domain_factory)
  File "/usr/local/lib/python3.8/site-packages/skdecide/hub/solver/do_solver/do_solver_scheduling.py", line 163, in _solve_domain
    result_storage = self.solver.solve(**self.dict_params)
  File "/usr/local/lib/python3.8/site-packages/skdecide/discrete_optimization/rcpsp/solver/cp_solvers.py", line 434, in solve
    return self.retrieve_solutions(result=result, parameters_cp=parameters_cp)
  File "/usr/local/lib/python3.8/site-packages/skdecide/discrete_optimization/rcpsp/solver/cp_solvers.py", line 413, in retrieve_solutions
    objective = self.aggreg_from_dict_values(self.rcpsp_model.evaluate(sol))
  File "/usr/local/lib/python3.8/site-packages/skdecide/discrete_optimization/rcpsp/rcpsp_model.py", line 520, in evaluate
    obj_makespan, obj_mean_resource_reserve = self.evaluate_function(rcpsp_sol)
  File "/usr/local/lib/python3.8/site-packages/skdecide/discrete_optimization/rcpsp/rcpsp_model.py", line 512, in evaluate_function
    obj_mean_resource_reserve = rcpsp_sol.compute_mean_resource_reserve()
  File "/usr/local/lib/python3.8/site-packages/skdecide/discrete_optimization/rcpsp/rcpsp_model.py", line 139, in compute_mean_resource_reserve
    resource_avail_in_time[res][t] -= self.problem.mode_details[act_id][mode][res]  # 17
IndexError: list index out of range
elcombato commented 3 years ago

This error is independent of the resources. Even if the tasks have no resource requirements the error is thrown.

It depends on the duration of the tasks:

# this results in error
tasks_mode = {
    1: {1: {'duration': 1, 'R1': 0}},
    2: {1: {'duration': 2, 'R1': 0}},
    3: {1: {'duration': 1, 'R1': 0}}
}

# this runs successfully
tasks_mode = {
    1: {1: {'duration': 1, 'R1': 0}},
    2: {1: {'duration': 1, 'R1': 0}},
    3: {1: {'duration': 2, 'R1': 0}}
}
elcombato commented 3 years ago

@galleon @fteicht can you take a look at this issue, time allowing. Thanks!

POPOGO commented 3 years ago

Hello @elcombato so i found a way of circumvent your issue. The code is only validated at the moment when there are clear source and sink task , and with the current implementation, task 1 will be the source and N will be the sink. It is indeed not specified anywhere and is a silent issue.

for your specific issue :

from skdecide.hub.domain.rcpsp.rcpsp_sk import RCPSP
from skdecide.hub.solver.do_solver.do_solver_scheduling import DOSolver, SolvingMethod
from skdecide.hub.solver.sgs_policies.sgs_policies import PolicyMethodParams, BasePolicyMethod

domain = RCPSP(
    resource_names={'R1'},
    task_ids=[1, 2, 3, 4, 5],
    tasks_mode={
        1: {1: {"duration": 0, "R1": 0}},
        2: {1: {'duration': 1, 'R1': 0}},
        3: {1: {'duration': 2, 'R1': 1}},
        4: {1: {'duration': 1, 'R1': 0}},
        5: {1: {"duration": 0, "R1": 0}}
    },
    successors={1: [2, 3, 4, 5], 2: [5], 3: [5], 4: [5], 5: []},
    resource_availability={'R1': 4},
    resource_renewable={'R1': True},
    max_horizon=100
)

state = domain.get_initial_state()

solver = DOSolver(
    policy_method_params=PolicyMethodParams(
        base_policy_method=BasePolicyMethod.SGS_PRECEDENCE
    ),
    method=SolvingMethod.CP
)
solver.solve(domain_factory=lambda: domain)

is a fix

nhuet commented 1 year ago

@g-poveda : we could close this issue, according to my understanding, couldn't we?