Algorithm 3 The search procedure and meta-heuristic while(it<maxIter){
call(step); if (oldViol == S.violations()) steady++; else steady = 0; if (S.violations() == 0){
maxDiverse=largeSteps; state := 1; forall(f in RWF) tabu[f] = 0; if (obj < bestSolution){
bestSolution = obj; sol = new Solution(m);
}
}
else {
maxDiverse = smallSteps; if (S.violations() <= 5) state := 3; else if (S.violations() <= 300) state := 2;
}
if (steady == diversifyLevel){
with atomic(m){
forall(i in 0..maxDiverse){
selectPr(i in 1..12)(pr2[i]){
select(f in RWF: deltaT[f] > ((i-1)*10) && deltaT[f] <= (i*10)){
deltaT[f] := 0;
}}}} steady = 0;
} oldViol = S.violations();
} sol.restore();
increasing.

Finally, Table 2 gives for both intervals the run-time, the actual number of iterations, the numbers of relevant waiting flights (that is the number of decision variables) and relevant airborne flights (which cannot be ground-held) at moment now, the total and average amounts of ground holding for all relevant flights, the change in standard deviation of the demands over all cells, and the initial number of constraint violations. It is very important to observe that, although the aim was only to minimise the total delay, there also is a 35% (respectively 43%) improvement in the standard deviation of the cell demands. About 70% (respectively 50%) of the relevant *waiting* flights need not be ground-held at all; note that this percentage does not include the relevant airborne flights, nor the many flights that could possibly be ground-held so as to be airborne within the interval for re-planning.

Among the parameters of our model (see Section 2.1), the maximum amount of ground holding per flight (currently set to g = 120 minutes) is the most interesting one to play with. Our first experiments