Skip to content

Commit e525d3f

Browse files
feat: p4 perturbation
1 parent bd68d5c commit e525d3f

3 files changed

Lines changed: 302 additions & 3 deletions

File tree

include/ASP.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class ASP {
1818

1919
public:
2020
enum class Neighborhood : uint8_t { IntraSwap, InterSwap, IntraMove, InterMove, WorstFlight };
21+
enum class Perturbation : uint8_t { IntraSwap, InterSwap, IntraMove, InterMove };
2122
std::vector<Flight> flights;
2223
std::vector<Flight> flights_perturbation;
2324

@@ -49,9 +50,14 @@ class ASP {
4950
Solution GILS_RVND(size_t max_iterations, size_t max_ils_iterations, double alpha); // NOLINT
5051

5152
// Perturbations
53+
void P4(Solution &solution); // NOLINT
5254

5355
void random_inter_block_swap(Solution &solution);
5456
bool best_improvement_free_space(Solution &solution);
57+
void intra_swap(Solution &solution);
58+
void inter_swap(Solution &solution);
59+
void intra_move(Solution &solution);
60+
void inter_move(Solution &solution);
5561

5662

5763
ASP(Instance &instance);

src/GILS.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,15 @@ Solution ASP::GILS_RVND(const size_t max_iterations, const size_t max_ils_iterat
151151

152152
for (size_t perturbation_iteration = 1; perturbation_iteration < max_pertubation_iters;
153153
++perturbation_iteration) {
154-
155-
random_inter_block_swap(solution);
154+
155+
if (ils_iteration > 400) P4(solution);
156+
else random_inter_block_swap(solution);
156157
}
157158

158159
RVND(solution);
159160

160161
if (solution.objective < local_best.objective) {
161-
// std::cout << "ils = " << ils_iteration << '\n';
162+
std::cout << "ils = " << ils_iteration << '\n';
162163

163164
// local_best <= solution ////////////////////////////////////////
164165
local_best.objective = solution.objective;

src/perturbation.cpp

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,31 @@
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+
1237
void 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 &current_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 &current_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 &current_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 &current_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 &current_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 &current_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 &current_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 &current_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 &current_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 &current_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

Comments
 (0)