The Doctor Rostering Problem - Asser Fahrenholz

The Doctor Rostering Problem - Asser Fahrenholz The Doctor Rostering Problem - Asser Fahrenholz

asser.fahrenholz.dk
from asser.fahrenholz.dk More from this publisher
27.07.2013 Views

Chapter 4. Solving the DRP 29 As there are between two and four shifts on a given day, with six doctors to choose from, we get between: n! (n−k)! = 6! (6−2)! = 30 and 6! (6−4)! = 360 possible combinations, which is, at maximum, an increase of 6000% in combinations to explore. On a 1 GHz computer, this results in a solution generation taking several minutes as opposed to no enumeration solutions taking mere seconds. The increase in time when using enumeration makes fur- ther enumeration, a whole week for instance (332640 possible combinations), undesirable to the end user. Testing of this function proved useful as shall be shown in chapter 7. 4.4.3 Construction heuristic The implementation of the greedy algorithm is, given the data structure, straight for- ward. The implementation can be found in appendix A.2, and in short, loops through each day, each shift and requests the best doctor for either the shift or the set of best doctors for the whole day (depending on whether the enumeration is used) and then performs the assignments that are returned. 4.4.4 Metaheuristics For the implementation of the two metaheuristics, it applies that a neighborhood is investigated by the following procedure: 1. Find neighborhood n 2. Apply neighborhood n 3. Calculate objective function value and feasibility 4. Decide whether: (a) To keep the new solution (b) To undo neighborhood n When applying the neighborhood-transformation to a solution, the information con- tained in the neighborhood is saved, such that the search procedure can quickly revert the transformation if the new solution should turn out inferior. GRASP My implementation of the GRASP framework is based, to the letter, on the algorithms describing the adaptive greedy algorithm (algorithm 4.1 on page 19) and Local Search (algorithm 4.2 on page 22). The entire GRASP class is found in appendix A.3.

Chapter 4. Solving the DRP 30 Simulated Annealing The Simulated Annealing implementation is based on algorithm 4.4 on page 26 and is included in appendix A.4. 4.4.5 Implementation optimisations As noted above, the two heuristics calculate the objective function value and feasibility every time a neighborhood transformation has been applied. This presents an obvious area for optimisation. One optimisation that did not make it into the implementation is that of a delta function, which I describe in detail in chapter 8. As one of the questions that spring to mind when developing an application could be: What operations of this implementation are taking the most time?, I was fortunate to be in possession of a tool to investigate this exact area. The Netbeans IDE 6.1 allows profiling of the program, enabling the developer to investigate which methods are taking the most time. When doing so, I found that the operation requiring the most time are Hash Code checks. Hash Codes are 32 bit signed integers identifying objects by a single value, found by the use of prime numbers and the values of the class-fields. The new (optimised) hash code this lead to, can be seen in listing 4.1, where several lines, now commented out, were previously calculated. Only the ID-number is really needed to uniquely identify the doctor. 1 public class Doctor implements Comparable < Doctor >, Serializable { 2 . 3 @Override 4 public int hashCode () { 5 // final int prime = 31; 6 // int result = 1; 7 // result = prime * result + IDnumber ; 8 // result = prime * result + (( name == null ) ? 0 : name . hashCode ()); 9 // result = prime * result + numberOfShifts ; 10 // result = prime * result + (( shifts == null ) ? 0 : shifts . hashCode ()); 11 return IDnumber ; 12 } 13 . 14 } Listing 4.1: The new hashcode method The optimisation may not seem that big, but when the calculation of this hash code is done once per doctor per shift per constraint, every time we need to calculate the objective function value, it adds up!

Chapter 4. Solving the DRP 30<br />

Simulated Annealing<br />

<strong>The</strong> Simulated Annealing implementation is based on algorithm 4.4 on page 26 and is<br />

included in appendix A.4.<br />

4.4.5 Implementation optimisations<br />

As noted above, the two heuristics calculate the objective function value and feasibility<br />

every time a neighborhood transformation has been applied. This presents an obvious<br />

area for optimisation. One optimisation that did not make it into the implementation<br />

is that of a delta function, which I describe in detail in chapter 8.<br />

As one of the questions that spring to mind when developing an application could be:<br />

What operations of this implementation are taking the most time?, I was fortunate to<br />

be in possession of a tool to investigate this exact area. <strong>The</strong> Netbeans IDE 6.1 allows<br />

profiling of the program, enabling the developer to investigate which methods are taking<br />

the most time. When doing so, I found that the operation requiring the most time are<br />

Hash Code checks. Hash Codes are 32 bit signed integers identifying objects by a single<br />

value, found by the use of prime numbers and the values of the class-fields.<br />

<strong>The</strong> new (optimised) hash code this lead to, can be seen in listing 4.1, where several<br />

lines, now commented out, were previously calculated. Only the ID-number is really<br />

needed to uniquely identify the doctor.<br />

1 public class <strong>Doctor</strong> implements Comparable < <strong>Doctor</strong> >, Serializable {<br />

2<br />

.<br />

3 @Override<br />

4 public int hashCode () {<br />

5 // final int prime = 31;<br />

6 // int result = 1;<br />

7 // result = prime * result + IDnumber ;<br />

8 // result = prime * result + (( name == null ) ? 0 : name . hashCode ());<br />

9 // result = prime * result + numberOfShifts ;<br />

10 // result = prime * result + (( shifts == null ) ? 0 : shifts . hashCode ());<br />

11 return IDnumber ;<br />

12 }<br />

13<br />

.<br />

14 }<br />

Listing 4.1: <strong>The</strong> new hashcode method<br />

<strong>The</strong> optimisation may not seem that big, but when the calculation of this hash code<br />

is done once per doctor per shift per constraint, every time we need to calculate the<br />

objective function value, it adds up!

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!