99#include < random>
1010#include < utility>
1111
12+ void ASP::P4 (Solution &solution) { // NOLINT
13+
14+ std::vector<Perturbation> perturbations{Perturbation::IntraSwap, Perturbation::InterSwap, /* Perturbation::IntraMove, */
15+ Perturbation::InterMove};
16+
17+ size_t current_perturbation = rand () % perturbations.size ();
18+
19+ switch (perturbations[current_perturbation]) {
20+ case Perturbation::IntraSwap:
21+ intra_swap (solution);
22+ break ;
23+ case Perturbation::InterSwap:
24+ inter_swap (solution);
25+ break ;
26+ // case Perturbation::IntraMove:
27+ // intra_move(solution);
28+ // break;
29+ case Perturbation::InterMove:
30+ inter_move (solution);
31+ break ;
32+ }
33+
34+ assert (solution.test_feasibility (m_instance));
35+ }
36+
1237void ASP::random_inter_block_swap (Solution &solution) {
1338 if (solution.runways .size () < 2 ) {
1439 return ;
@@ -276,3 +301,270 @@ bool ASP::best_improvement_free_space(Solution &solution) {
276301 }
277302 return false ;
278303}
304+
305+ void ASP::intra_swap (Solution &solution) {
306+ size_t best_runway_i = 0 ;
307+
308+ do {
309+ best_runway_i = rand () % solution.runways .size ();
310+ } while (solution.runways [best_runway_i].sequence .size () < 2 );
311+
312+ size_t best_flight_i = 0 ;
313+ size_t best_flight_j = 0 ;
314+
315+ best_flight_i = rand () % solution.runways [best_runway_i].sequence .size ();
316+
317+ do {
318+ best_flight_j = rand () % solution.runways [best_runway_i].sequence .size ();
319+ } while (best_flight_i == best_flight_j);
320+
321+ if (best_flight_i > best_flight_j) {
322+ std::swap (best_flight_i, best_flight_j);
323+ }
324+
325+ Runway &best_runway = solution.runways [best_runway_i];
326+ uint32_t original_penalty = best_runway.penalty ;;
327+
328+ best_runway.sequence [best_flight_i].get ().position = best_flight_j;
329+ best_runway.sequence [best_flight_j].get ().position = best_flight_i;
330+ std::swap (solution.runways [best_runway_i].sequence [best_flight_i], solution.runways [best_runway_i].sequence [best_flight_j]);
331+
332+ if (best_flight_i == 0 ) {
333+ Flight ¤t_flight = best_runway.sequence .front ().get ();
334+ current_flight.start_time = current_flight.get_release_time ();
335+ best_runway.prefix_penalty [1 ] = 0 ;
336+ best_flight_i++;
337+ }
338+
339+ for (size_t flight_i = best_flight_i; flight_i < best_runway.sequence .size (); flight_i++) {
340+ Flight ¤t_flight = best_runway.sequence [flight_i].get ();
341+ Flight &prev_flight = best_runway.sequence [flight_i - 1 ].get ();
342+
343+ current_flight.start_time =
344+ std::max (current_flight.get_release_time (),
345+ prev_flight.start_time + prev_flight.get_runway_occupancy_time () +
346+ m_instance.get_separation_time (prev_flight.get_id (), current_flight.get_id ()));
347+
348+ best_runway.prefix_penalty [flight_i + 1 ] =
349+ best_runway.prefix_penalty [flight_i] +
350+ (current_flight.start_time - current_flight.get_release_time ()) * current_flight.get_delay_penalty ();
351+ }
352+
353+ uint32_t delta = 0 ;
354+ if (best_runway.prefix_penalty .back () < original_penalty) {
355+ delta = original_penalty - best_runway.prefix_penalty .back ();
356+ best_runway.penalty -= delta;
357+ solution.objective -= delta;
358+ } else {
359+ delta = best_runway.prefix_penalty .back () - original_penalty;
360+ best_runway.penalty += delta;
361+ solution.objective += delta;
362+ }
363+
364+ assert (solution.test_feasibility (m_instance));
365+ }
366+
367+ void ASP::inter_swap (Solution &solution) {
368+ size_t best_runway_i = 0 ;
369+ size_t best_runway_j = 0 ;
370+
371+ best_runway_i = rand () % solution.runways .size ();
372+
373+ do {
374+ best_runway_j = rand () % solution.runways .size ();
375+ } while (best_runway_i == best_runway_j);
376+
377+ size_t best_flight_i = 0 ;
378+ size_t best_flight_j = 0 ;
379+
380+ best_flight_i = rand () % solution.runways [best_runway_i].sequence .size ();
381+
382+ do {
383+ best_flight_j = rand () % solution.runways [best_runway_j].sequence .size ();
384+ } while (best_flight_i == best_flight_j);
385+
386+ uint32_t original_penalty_i = solution.runways [best_runway_i].penalty ;
387+ uint32_t original_penalty_j = solution.runways [best_runway_j].penalty ;
388+
389+
390+ solution.runways [best_runway_i].sequence [best_flight_i].get ().position = best_flight_j;
391+ solution.runways [best_runway_i].sequence [best_flight_i].get ().runway = best_runway_j;
392+
393+ solution.runways [best_runway_j].sequence [best_flight_j].get ().position = best_flight_i;
394+ solution.runways [best_runway_j].sequence [best_flight_j].get ().runway = best_runway_i;
395+
396+ std::swap (solution.runways [best_runway_i].sequence [best_flight_i],
397+ solution.runways [best_runway_j].sequence [best_flight_j]);
398+
399+ // Update prefix best_runway_i
400+ if (best_flight_i == 0 ) {
401+ Flight ¤t_flight = solution.runways [best_runway_i].sequence [0 ].get ();
402+ current_flight.start_time = current_flight.get_release_time ();
403+ solution.runways [best_runway_i].prefix_penalty [1 ] = 0 ;
404+ best_flight_i++;
405+ }
406+
407+ for (size_t i = best_flight_i; i < solution.runways [best_runway_i].sequence .size (); i++) {
408+ Flight ¤t_flight = solution.runways [best_runway_i].sequence [i].get ();
409+ Flight &prev_flight = solution.runways [best_runway_i].sequence [i - 1 ].get ();
410+
411+ current_flight.start_time =
412+ std::max (current_flight.get_release_time (),
413+ prev_flight.start_time + prev_flight.get_runway_occupancy_time () +
414+ m_instance.get_separation_time (prev_flight.get_id (), current_flight.get_id ()));
415+
416+ solution.runways [best_runway_i].prefix_penalty [i + 1 ] =
417+ solution.runways [best_runway_i].prefix_penalty [i] +
418+ (current_flight.start_time - current_flight.get_release_time ()) * current_flight.get_delay_penalty ();
419+ }
420+
421+ // Update prefix best_runway_j
422+ if (best_flight_j == 0 ) {
423+ Flight ¤t_flight = solution.runways [best_runway_j].sequence [0 ].get ();
424+ current_flight.start_time = current_flight.get_release_time ();
425+ solution.runways [best_runway_j].prefix_penalty [1 ] = 0 ;
426+ best_flight_j++;
427+ }
428+
429+ for (size_t j = best_flight_j; j < solution.runways [best_runway_j].sequence .size (); j++) {
430+ Flight ¤t_flight = solution.runways [best_runway_j].sequence [j].get ();
431+ Flight &prev_flight = solution.runways [best_runway_j].sequence [j - 1 ].get ();
432+
433+ current_flight.start_time =
434+ std::max (current_flight.get_release_time (),
435+ prev_flight.start_time + prev_flight.get_runway_occupancy_time () +
436+ m_instance.get_separation_time (prev_flight.get_id (), current_flight.get_id ()));
437+
438+ solution.runways [best_runway_j].prefix_penalty [j + 1 ] =
439+ solution.runways [best_runway_j].prefix_penalty [j] +
440+ (current_flight.start_time - current_flight.get_release_time ()) * current_flight.get_delay_penalty ();
441+ }
442+
443+ // Update penaltys
444+ solution.runways [best_runway_i].penalty = solution.runways [best_runway_i].prefix_penalty .back ();
445+ solution.runways [best_runway_j].penalty = solution.runways [best_runway_j].prefix_penalty .back ();
446+
447+ uint32_t delta = 0 ;
448+
449+ if (solution.runways [best_runway_i].penalty + solution.runways [best_runway_j].penalty < original_penalty_i + original_penalty_j) {
450+ delta = original_penalty_i + original_penalty_j - (solution.runways [best_runway_i].penalty + solution.runways [best_runway_j].penalty );
451+ solution.objective -= delta;
452+ } else {
453+ delta = (solution.runways [best_runway_i].penalty + solution.runways [best_runway_j].penalty ) - (original_penalty_i + original_penalty_j);
454+ solution.objective += delta;
455+ }
456+
457+ assert (solution.test_feasibility (m_instance));
458+ }
459+
460+ void ASP::intra_move (Solution &solution) {
461+
462+ }
463+
464+ void ASP::inter_move (Solution &solution) {
465+ size_t best_runway_i = 0 ;
466+ size_t best_runway_j = 0 ;
467+
468+ do {
469+ best_runway_i = rand () % solution.runways .size ();
470+ } while (solution.runways [best_runway_i].sequence .size () < 2 );
471+
472+ do {
473+ best_runway_j = rand () % solution.runways .size ();
474+ } while (best_runway_i == best_runway_j);
475+
476+ size_t best_flight_i = 0 ;
477+ size_t best_flight_j = 0 ;
478+
479+ best_flight_i = rand () % solution.runways [best_runway_i].sequence .size ();
480+ best_flight_j = rand () % (solution.runways [best_runway_j].sequence .size () + 1 );
481+
482+ uint32_t original_penalty_i = solution.runways [best_runway_i].penalty ;
483+ uint32_t original_penalty_j = solution.runways [best_runway_j].penalty ;
484+
485+ solution.runways [best_runway_i].sequence [best_flight_i].get ().position = best_flight_j;
486+ solution.runways [best_runway_i].sequence [best_flight_i].get ().runway = best_runway_j;
487+ solution.runways [best_runway_i].prefix_penalty .pop_back ();
488+ solution.runways [best_runway_j].prefix_penalty .push_back (0 );
489+
490+ // Add to best_runway_j
491+ if (best_flight_j == solution.runways [best_runway_j].sequence .size ()) {
492+ solution.runways [best_runway_j].sequence .push_back (solution.runways [best_runway_i].sequence [best_flight_i]);
493+ } else {
494+ solution.runways [best_runway_j].sequence .push_back (m_dummy_flight);
495+
496+ for (size_t k = solution.runways [best_runway_j].sequence .size () - 1 ; k > best_flight_j; k--) {
497+ solution.runways [best_runway_j].sequence [k] = solution.runways [best_runway_j].sequence [k - 1 ];
498+ solution.runways [best_runway_j].sequence [k].get ().position = k;
499+ }
500+
501+ solution.runways [best_runway_j].sequence [best_flight_j] = solution.runways [best_runway_i].sequence [best_flight_i];
502+ }
503+
504+ // Remove from best_runway_i
505+ for (size_t k = best_flight_i; k + 1 < solution.runways [best_runway_i].sequence .size (); k++) {
506+ solution.runways [best_runway_i].sequence [k] = solution.runways [best_runway_i].sequence [k + 1 ];
507+ solution.runways [best_runway_i].sequence [k].get ().position = k;
508+ }
509+ solution.runways [best_runway_i].sequence .pop_back ();
510+
511+ // Update prefix best_runway_i
512+ if (best_flight_i == 0 ) {
513+ Flight ¤t_flight = solution.runways [best_runway_i].sequence [0 ].get ();
514+ current_flight.start_time = current_flight.get_release_time ();
515+ solution.runways [best_runway_i].prefix_penalty [1 ] = 0 ;
516+ best_flight_i++;
517+ }
518+
519+ for (size_t i = best_flight_i; i < solution.runways [best_runway_i].sequence .size (); i++) {
520+ Flight ¤t_flight = solution.runways [best_runway_i].sequence [i].get ();
521+ Flight &prev_flight = solution.runways [best_runway_i].sequence [i - 1 ].get ();
522+
523+ current_flight.start_time =
524+ std::max (current_flight.get_release_time (),
525+ prev_flight.start_time + prev_flight.get_runway_occupancy_time () +
526+ m_instance.get_separation_time (prev_flight.get_id (), current_flight.get_id ()));
527+
528+ solution.runways [best_runway_i].prefix_penalty [i + 1 ] =
529+ solution.runways [best_runway_i].prefix_penalty [i] +
530+ (current_flight.start_time - current_flight.get_release_time ()) * current_flight.get_delay_penalty ();
531+ }
532+
533+ // Update prefix best_runway_j
534+ if (best_flight_j == 0 ) {
535+ Flight ¤t_flight = solution.runways [best_runway_j].sequence [0 ].get ();
536+ current_flight.start_time = current_flight.get_release_time ();
537+ solution.runways [best_runway_j].prefix_penalty [1 ] = 0 ;
538+ best_flight_j++;
539+ }
540+
541+ for (size_t j = best_flight_j; j < solution.runways [best_runway_j].sequence .size (); j++) {
542+ Flight ¤t_flight = solution.runways [best_runway_j].sequence [j].get ();
543+ Flight &prev_flight = solution.runways [best_runway_j].sequence [j - 1 ].get ();
544+
545+ current_flight.start_time =
546+ std::max (current_flight.get_release_time (),
547+ prev_flight.start_time + prev_flight.get_runway_occupancy_time () +
548+ m_instance.get_separation_time (prev_flight.get_id (), current_flight.get_id ()));
549+
550+ solution.runways [best_runway_j].prefix_penalty [j + 1 ] =
551+ solution.runways [best_runway_j].prefix_penalty [j] +
552+ (current_flight.start_time - current_flight.get_release_time ()) * current_flight.get_delay_penalty ();
553+ }
554+
555+ // Update penaltys
556+ solution.runways [best_runway_i].penalty = solution.runways [best_runway_i].prefix_penalty .back ();
557+ solution.runways [best_runway_j].penalty = solution.runways [best_runway_j].prefix_penalty .back ();
558+
559+ uint32_t delta = 0 ;
560+
561+ if (solution.runways [best_runway_i].penalty + solution.runways [best_runway_j].penalty < original_penalty_i + original_penalty_j) {
562+ delta = original_penalty_i + original_penalty_j - (solution.runways [best_runway_i].penalty + solution.runways [best_runway_j].penalty );
563+ solution.objective -= delta;
564+ } else {
565+ delta = (solution.runways [best_runway_i].penalty + solution.runways [best_runway_j].penalty ) - (original_penalty_i + original_penalty_j);
566+ solution.objective += delta;
567+ }
568+
569+ assert (solution.test_feasibility (m_instance));
570+ }
0 commit comments