@@ -200,7 +200,7 @@ std::vector<int> solve_impl(
200200 // New edges after reversal: (i+1)→j and i→(j-1)
201201 // Add epsilon to prevent cycles from floating point errors
202202 double newLen = dist (pts[route[i + 1 ]], pts[route[j]])
203- + dist (pts[route[i]], pts[route[j - 1 ]]) + 1e-5 ;
203+ + dist (pts[route[i]], pts[route[j - 1 ]]) + Base::Precision::Confusion () ;
204204
205205 if (newLen < curLen) {
206206 // Reverse the segment between i+1 and j (exclusive)
@@ -230,7 +230,7 @@ std::vector<int> solve_impl(
230230 // New cost: bypass i, insert i after j
231231 double newLen = dist (pts[route[i - 1 ]], pts[route[i + 1 ]])
232232 + dist (pts[route[j]], pts[route[i]])
233- + dist (pts[route[i]], pts[route[j + 1 ]]) + 1e-5 ;
233+ + dist (pts[route[i]], pts[route[j + 1 ]]) + Base::Precision::Confusion () ;
234234
235235 if (newLen < curLen) {
236236 // Move point i to position after j
@@ -250,7 +250,7 @@ std::vector<int> solve_impl(
250250
251251 double newLen = dist (pts[route[i - 1 ]], pts[route[i + 1 ]])
252252 + dist (pts[route[j]], pts[route[i]])
253- + dist (pts[route[i]], pts[route[j + 1 ]]) + 1e-5 ;
253+ + dist (pts[route[i]], pts[route[j + 1 ]]) + Base::Precision::Confusion () ;
254254
255255 if (newLen < curLen) {
256256 int node = route[i];
@@ -402,26 +402,37 @@ std::vector<TSPTunnel> TSPSolver::solveTunnels(
402402 }
403403
404404 // STEP 4: Additional improvement of the route
405- bool improvementFound = true ;
406- while (improvementFound) {
407- improvementFound = false ;
405+ size_t limitReorderI = route.size () - 2 ;
406+ if (routeEndPoint) {
407+ limitReorderI -= 1 ;
408+ }
409+ size_t limitReorderJ = route.size ();
410+ size_t limitFlipI = route.size () - 1 ;
411+ size_t limitRelocationI = route.size () - 1 ;
412+ size_t limitRelocationJ = route.size () - 1 ;
413+ int lastImprovementAtStep = 0 ;
414+
415+ while (true ) {
408416
409417 if (allowFlipping) {
410418 // STEP 4.1: Apply 2-opt
411- bool improvementReorderFound = true ;
412- while (improvementReorderFound) {
413- improvementReorderFound = false ;
414- for (size_t i = 0 ; i + 3 < route.size (); ++i) {
415- for (size_t j = i + 3 ; j < route.size (); ++j) {
416- double subRouteLengthCurrent = std::sqrt (
417- std::pow (route[i].endX - route[i + 1 ].startX , 2 )
418- + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
419- );
419+ if (lastImprovementAtStep == 1 ) {
420+ break ;
421+ }
422+ bool improvementFound = true ;
423+ while (improvementFound) {
424+ improvementFound = false ;
425+ for (size_t i = 0 ; i < limitReorderI; ++i) {
426+ double subRouteLengthCurrentPart = std::sqrt (
427+ std::pow (route[i].endX - route[i + 1 ].startX , 2 )
428+ + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
429+ );
430+ for (size_t j = i + 3 ; j < limitReorderJ; ++j) {
431+ double subRouteLengthCurrent = subRouteLengthCurrentPart;
420432 subRouteLengthCurrent += std::sqrt (
421433 std::pow (route[j - 1 ].endX - route[j].startX , 2 )
422434 + std::pow (route[j - 1 ].endY - route[j].startY , 2 )
423435 );
424-
425436 double subRouteLengthNew = std::sqrt (
426437 std::pow (route[i + 1 ].startX - route[j].startX , 2 )
427438 + std::pow (route[i + 1 ].startY - route[j].startY , 2 )
@@ -430,31 +441,63 @@ std::vector<TSPTunnel> TSPSolver::solveTunnels(
430441 std::pow (route[i].endX - route[j - 1 ].endX , 2 )
431442 + std::pow (route[i].endY - route[j - 1 ].endY , 2 )
432443 );
433- subRouteLengthNew += 1e-6 ;
444+ subRouteLengthNew += Base::Precision::Confusion () ;
434445
435446 if (subRouteLengthNew < subRouteLengthCurrent) {
436- // Flip direction of each tunnel between i-th and j-th element
447+ // Flip direction of each tunnel between i-th and j-th tunnel
437448 for (size_t k = i + 1 ; k < j; ++k) {
438449 if (route[k].isOpen ) {
439450 route[k].flipped = !route[k].flipped ;
440451 std::swap (route[k].startX , route[k].endX );
441452 std::swap (route[k].startY , route[k].endY );
442453 }
443454 }
444- // Reverse the order of tunnels between i-th and j-th element
455+ // Reverse the order of tunnels between i-th and j-th tunnel
445456 std::reverse (route.begin () + i + 1 , route.begin () + j);
446- improvementReorderFound = true ;
457+ subRouteLengthCurrentPart = std::sqrt (
458+ std::pow (route[i].endX - route[i + 1 ].startX , 2 )
459+ + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
460+ );
461+ improvementFound = true ;
462+ lastImprovementAtStep = 1 ;
463+ }
464+ }
465+ if (!routeEndPoint) {
466+ double subRouteLengthCurrent = std::sqrt (
467+ std::pow (route[i].endX - route[i + 1 ].startX , 2 )
468+ + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
469+ );
470+ double subRouteLengthNew = std::sqrt (
471+ std::pow (route[i].endX - route[route.size () - 1 ].endX , 2 )
472+ + std::pow (route[i].endY - route[route.size () - 1 ].endY , 2 )
473+ );
474+ subRouteLengthNew += Base::Precision::Confusion ();
475+ if (subRouteLengthNew < subRouteLengthCurrent) {
476+ // Flip direction of each tunnel after i-th to the last tunnel
477+ for (size_t k = i + 1 ; k < limitReorderJ; ++k) {
478+ if (route[k].isOpen ) {
479+ route[k].flipped = !route[k].flipped ;
480+ std::swap (route[k].startX , route[k].endX );
481+ std::swap (route[k].startY , route[k].endY );
482+ }
483+ }
484+ // Reverse the order of tunnels after i-th to the last tunnel
485+ std::reverse (route.begin () + i + 1 , route.begin () + limitReorderJ);
447486 improvementFound = true ;
487+ lastImprovementAtStep = 1 ;
448488 }
449489 }
450490 }
451491 }
452492
453493 // STEP 4.2: Apply flipping
454- bool improvementFlipFound = true ;
455- while (improvementFlipFound) {
456- improvementFlipFound = false ;
457- for (size_t i = 1 ; i + 1 < route.size (); ++i) {
494+ if (lastImprovementAtStep == 2 ) {
495+ break ;
496+ }
497+ improvementFound = true ;
498+ while (improvementFound) {
499+ improvementFound = false ;
500+ for (size_t i = 1 ; i < limitFlipI; ++i) {
458501 if (route[i].isOpen ) {
459502 double subRouteLengthCurrent = std::sqrt (
460503 std::pow (route[i - 1 ].endX - route[i].startX , 2 )
@@ -473,45 +516,72 @@ std::vector<TSPTunnel> TSPSolver::solveTunnels(
473516 std::pow (route[i].startX - route[i + 1 ].startX , 2 )
474517 + std::pow (route[i].startY - route[i + 1 ].startY , 2 )
475518 );
476- subRouteLengthNew += 1e-6 ;
519+ subRouteLengthNew += Base::Precision::Confusion () ;
477520
478521 if (subRouteLengthNew < subRouteLengthCurrent) {
479522 // Flip direction of i-th tunnel
480523 route[i].flipped = !route[i].flipped ;
481524 std::swap (route[i].startX , route[i].endX );
482525 std::swap (route[i].startY , route[i].endY );
483- improvementFlipFound = true ;
484526 improvementFound = true ;
527+ lastImprovementAtStep = 2 ;
528+ }
529+ }
530+ }
531+ if (!routeEndPoint) {
532+ if (route[route.size () - 1 ].isOpen ) {
533+ double subRouteLengthCurrent = std::sqrt (
534+ std::pow (route[route.size () - 2 ].endX - route[route.size () - 1 ].startX , 2 )
535+ + std::pow (route[route.size () - 2 ].endY - route[route.size () - 1 ].startY , 2 )
536+ );
537+ double subRouteLengthNew = std::sqrt (
538+ std::pow (route[route.size () - 2 ].endX - route[route.size () - 1 ].endX , 2 )
539+ + std::pow (route[route.size () - 2 ].endY - route[route.size () - 1 ].endY , 2 )
540+ );
541+ subRouteLengthNew += Base::Precision::Confusion ();
542+ if (subRouteLengthNew < subRouteLengthCurrent) {
543+ // Flip direction of the last tunnel
544+ route[route.size () - 1 ].flipped = !route[route.size () - 1 ].flipped ;
545+ std::swap (route[route.size () - 1 ].startX , route[route.size () - 1 ].endX );
546+ std::swap (route[route.size () - 1 ].startY , route[route.size () - 1 ].endY );
547+ improvementFound = true ;
548+ lastImprovementAtStep = 2 ;
485549 }
486550 }
487551 }
488552 }
489553 }
490554
491555 // STEP 4.3: Apply relocation
492- bool improvementRelocateFound = true ;
493- while (improvementRelocateFound) {
494- improvementRelocateFound = false ;
495- for (size_t i = 1 ; i + 1 < route.size (); ++i) {
556+ if (lastImprovementAtStep == 3 ) {
557+ break ;
558+ }
559+ bool improvementFound = true ;
560+ while (improvementFound) {
561+ improvementFound = false ;
562+ for (size_t i = 1 ; i < limitRelocationI; ++i) {
563+ double subRouteLengthCurrentPart = std::sqrt (
564+ std::pow (route[i - 1 ].endX - route[i].startX , 2 )
565+ + std::pow (route[i - 1 ].endY - route[i].startY , 2 )
566+ );
567+ subRouteLengthCurrentPart += std::sqrt (
568+ std::pow (route[i].endX - route[i + 1 ].startX , 2 )
569+ + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
570+ );
571+ double subRouteLengthNewPart = std::sqrt (
572+ std::pow (route[i - 1 ].endX - route[i + 1 ].startX , 2 )
573+ + std::pow (route[i - 1 ].endY - route[i + 1 ].startY , 2 )
574+ );
575+ subRouteLengthNewPart += Base::Precision::Confusion ();
576+
496577 // Try relocating backward
497- for (size_t j = 1 ; j + 2 < i; ++j) {
498- double subRouteLengthCurrent = std::sqrt (
499- std::pow (route[i - 1 ].endX - route[i].startX , 2 )
500- + std::pow (route[i - 1 ].endY - route[i].startY , 2 )
501- );
502- subRouteLengthCurrent += std::sqrt (
503- std::pow (route[i].endX - route[i + 1 ].startX , 2 )
504- + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
505- );
578+ for (size_t j = 0 ; j + 2 < i; ++j) {
579+ double subRouteLengthCurrent = subRouteLengthCurrentPart;
506580 subRouteLengthCurrent += std::sqrt (
507581 std::pow (route[j].endX - route[j + 1 ].startX , 2 )
508582 + std::pow (route[j].endY - route[j + 1 ].startY , 2 )
509583 );
510-
511- double subRouteLengthNew = std::sqrt (
512- std::pow (route[i - 1 ].endX - route[i + 1 ].startX , 2 )
513- + std::pow (route[i - 1 ].endY - route[i + 1 ].startY , 2 )
514- );
584+ double subRouteLengthNew = subRouteLengthNewPart;
515585 subRouteLengthNew += std::sqrt (
516586 std::pow (route[j].endX - route[i].startX , 2 )
517587 + std::pow (route[j].endY - route[i].startY , 2 )
@@ -520,37 +590,37 @@ std::vector<TSPTunnel> TSPSolver::solveTunnels(
520590 std::pow (route[i].endX - route[j + 1 ].startX , 2 )
521591 + std::pow (route[i].endY - route[j + 1 ].startY , 2 )
522592 );
523- subRouteLengthNew += 1e-6 ;
524-
525593 if (subRouteLengthNew < subRouteLengthCurrent) {
526- // Relocate the i-th tunnel backward (after j-th element )
594+ // Relocate the i-th tunnel backward (after j-th tunnel )
527595 TSPTunnel temp = route[i];
528596 route.erase (route.begin () + i);
529597 route.insert (route.begin () + j + 1 , temp);
530- improvementRelocateFound = true ;
598+ subRouteLengthCurrentPart = std::sqrt (
599+ std::pow (route[i - 1 ].endX - route[i].startX , 2 )
600+ + std::pow (route[i - 1 ].endY - route[i].startY , 2 )
601+ );
602+ subRouteLengthCurrentPart += std::sqrt (
603+ std::pow (route[i].endX - route[i + 1 ].startX , 2 )
604+ + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
605+ );
606+ subRouteLengthNewPart = std::sqrt (
607+ std::pow (route[i - 1 ].endX - route[i + 1 ].startX , 2 )
608+ + std::pow (route[i - 1 ].endY - route[i + 1 ].startY , 2 )
609+ );
610+ subRouteLengthNewPart += Base::Precision::Confusion ();
531611 improvementFound = true ;
612+ lastImprovementAtStep = 3 ;
532613 }
533614 }
534615
535616 // Try relocating forward
536- for (size_t j = i + 1 ; j + 1 < route.size (); ++j) {
537- double subRouteLengthCurrent = std::sqrt (
538- std::pow (route[i - 1 ].endX - route[i].startX , 2 )
539- + std::pow (route[i - 1 ].endY - route[i].startY , 2 )
540- );
541- subRouteLengthCurrent += std::sqrt (
542- std::pow (route[i].endX - route[i + 1 ].startX , 2 )
543- + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
544- );
617+ for (size_t j = i + 1 ; j < limitRelocationJ; ++j) {
618+ double subRouteLengthCurrent = subRouteLengthCurrentPart;
545619 subRouteLengthCurrent += std::sqrt (
546620 std::pow (route[j].endX - route[j + 1 ].startX , 2 )
547621 + std::pow (route[j].endY - route[j + 1 ].startY , 2 )
548622 );
549-
550- double subRouteLengthNew = std::sqrt (
551- std::pow (route[i - 1 ].endX - route[i + 1 ].startX , 2 )
552- + std::pow (route[i - 1 ].endY - route[i + 1 ].startY , 2 )
553- );
623+ double subRouteLengthNew = subRouteLengthNewPart;
554624 subRouteLengthNew += std::sqrt (
555625 std::pow (route[j].endX - route[i].startX , 2 )
556626 + std::pow (route[j].endY - route[i].startY , 2 )
@@ -559,18 +629,67 @@ std::vector<TSPTunnel> TSPSolver::solveTunnels(
559629 std::pow (route[i].endX - route[j + 1 ].startX , 2 )
560630 + std::pow (route[i].endY - route[j + 1 ].startY , 2 )
561631 );
562- subRouteLengthNew += 1e-6 ;
563-
564632 if (subRouteLengthNew < subRouteLengthCurrent) {
565- // Relocate the i-th tunnel forward (after j-th element )
633+ // Relocate the i-th tunnel forward (after j-th tunnel )
566634 TSPTunnel temp = route[i];
567635 route.erase (route.begin () + i);
568636 route.insert (route.begin () + j, temp);
569- improvementRelocateFound = true ;
637+ subRouteLengthCurrentPart = std::sqrt (
638+ std::pow (route[i - 1 ].endX - route[i].startX , 2 )
639+ + std::pow (route[i - 1 ].endY - route[i].startY , 2 )
640+ );
641+ subRouteLengthCurrentPart += std::sqrt (
642+ std::pow (route[i].endX - route[i + 1 ].startX , 2 )
643+ + std::pow (route[i].endY - route[i + 1 ].startY , 2 )
644+ );
645+ subRouteLengthNewPart = std::sqrt (
646+ std::pow (route[i - 1 ].endX - route[i + 1 ].startX , 2 )
647+ + std::pow (route[i - 1 ].endY - route[i + 1 ].startY , 2 )
648+ );
649+ subRouteLengthNewPart += Base::Precision::Confusion ();
570650 improvementFound = true ;
651+ lastImprovementAtStep = 3 ;
571652 }
572653 }
573654 }
655+ if (!routeEndPoint) {
656+ double subRouteLengthCurrentPart = std::sqrt (
657+ std::pow (route[route.size () - 2 ].endX - route[route.size () - 1 ].startX , 2 )
658+ + std::pow (route[route.size () - 2 ].endY - route[route.size () - 1 ].startY , 2 )
659+ );
660+ for (size_t j = 0 ; j + 2 < route.size (); ++j) {
661+ double subRouteLengthCurrent = subRouteLengthCurrentPart;
662+ subRouteLengthCurrent += std::sqrt (
663+ std::pow (route[j].endX - route[j + 1 ].startX , 2 )
664+ + std::pow (route[j].endY - route[j + 1 ].startY , 2 )
665+ );
666+ double subRouteLengthNew = std::sqrt (
667+ std::pow (route[j].endX - route[route.size () - 1 ].startX , 2 )
668+ + std::pow (route[j].endY - route[route.size () - 1 ].startY , 2 )
669+ );
670+ subRouteLengthNew += std::sqrt (
671+ std::pow (route[route.size () - 1 ].endX - route[j + 1 ].startX , 2 )
672+ + std::pow (route[route.size () - 1 ].endY - route[j + 1 ].startY , 2 )
673+ );
674+ subRouteLengthNew += Base::Precision::Confusion ();
675+ if (subRouteLengthNew < subRouteLengthCurrent) {
676+ // Relocate the last tunnel after j-th tunnel
677+ TSPTunnel temp = route[route.size () - 1 ];
678+ route.erase (route.begin () + route.size () - 1 );
679+ route.insert (route.begin () + j + 1 , temp);
680+ subRouteLengthCurrentPart = std::sqrt (
681+ std::pow (route[route.size () - 2 ].endX - route[route.size () - 1 ].startX , 2 )
682+ + std::pow (route[route.size () - 2 ].endY - route[route.size () - 1 ].startY , 2 )
683+ );
684+ improvementFound = true ;
685+ lastImprovementAtStep = 3 ;
686+ }
687+ }
688+ }
689+ }
690+
691+ if (lastImprovementAtStep == 0 ) {
692+ break ; // No additional improvements could be made
574693 }
575694 }
576695
0 commit comments