IBM ILOG Scheduler User's Manual > Integrated Applications > A Randomizing Algorithm: the Job-Shop Problem > Developing the Problem-Solving Algorithm > Optimizing the Makespan |
Optimizing the Makespan |
INDEX
![]() |
Inside the function MinimizeRandom
, the search goal SolveProblem
is limited with the function IloLimitSearch
. More precisely, the number of backtracks is limited to the value of numberOfFailsPerIteration
, a parameter of the function MinimizeRandom
.
ILCGOAL1(SolveProblemIlc, IloRandom, rand) { IloSolver s = getSolver(); IlcScheduler scheduler = IlcScheduler(s); IlcResourceConstraint constraint; if (SelectResourceConstraint(constraint, scheduler, rand)) { return IlcAnd(IlcTryRankFirst(constraint), this); } return 0; } ILOCPGOALWRAPPER1(SolveProblem, solver, IloRandom, rand) { return SolveProblemIlc(solver, rand); } void MinimizeRandom(IloSolver& solver, IloNumVar& makespan, IloSchedulerSolution& solution, IloInt numberOfIterations, IloInt numberOfFailsPerIteration) { IloEnv env = solver.getEnv(); IlcScheduler sched(solver); IloRandom randGen(env); IloGoal goal; /* GENERATE AN INITIAL SOLUTION. */ goal = IloGoalTrue(solver.getEnv()); solver.solve(goal); IloNum min = solver.getMin(makespan); makespan.setLB(min); goal = SolveProblem(env, randGen); solver.solve(goal); IloNum max = solver.getMin(makespan); /* OPTIMIZE. */ IloInt iteration = 0; goal = IloLimitSearch(env, SolveProblem(env, randGen), IloFailLimit(env, numberOfFailsPerIteration)); while ((min != max) && (iteration < numberOfIterations)) { iteration++; IloNum value = IloTrunc((min + iteration * max) / (iteration + 1)); makespan.setUB(value); solver.out() << "Trying makespan: " << value << endl; if (solver.solve(goal)) { max = solver.getMin(makespan); solver.out() << "Solution with makespan " << max << endl; solution.store(sched); } else /* ... */ } /* ... */ }
Remembering our experience with the dichotomizing binary search (in Chapter 16), at each iteration, we use a weighted sum of the minimal value min
and maximal value max
of the makespan
variable as a new tentative bound for this constrained variable. Here, it would not be a good idea to systematically take the average of these two values as a new tentative makespan. In fact, it could be that no solution exists with a makespan of (min+max)/2
, so taking the same tentative makespan at each iteration could lead to ignoring many good solutions to the scheduling problem.
Each iteration may fail either because there is no solution with a given makespan, or because the algorithm could not find such a solution in the given number of backtracks. By testing the number of failures (the value of solver.getNumberOfFails()
) at the end of the iteration, we know whether the numberOfFailsPerIteration
backtracks have been consumed or not. If not, the algorithm has proven that no solution exists with a makespan of at most the given value
. Hence, it is correct to write the following code.
if (solver.solve(goal)) { max = solver.getMin(makespan); solver.out() << "Solution with makespan " << max << endl; solution.store(sched); } else if (solver.getNumberOfFails() < numberOfFailsPerIteration) { /* ACTUAL FAILURE NOT DUE TO THE LIMITED NUMBER OF FAILS. */ solver.out() << "Failure with makespan " << value << endl; min = value + 1; } else solver.out() << "Failure from fail limit" << endl; }
Notice that the best solution is stored in an instance of the class IloSchedulerSolution
.
© Copyright IBM Corp. 1987, 2009. Legal terms. | PREVIOUS NEXT |