diff --git a/input/gtsp-m10-n100-s181.in b/input/gtsp-m10-n100-s181.in new file mode 100644 index 0000000..f540e7f --- /dev/null +++ b/input/gtsp-m10-n100-s181.in @@ -0,0 +1,101 @@ +100 10 +83.00 34.00 0 +84.00 64.00 1 +77.00 65.00 2 +54.00 15.00 3 +46.00 4.00 4 +20.00 18.00 5 +73.00 40.00 6 +88.00 70.00 7 +95.00 17.00 8 +38.00 55.00 9 +89.00 75.00 7 +7.00 0.00 5 +58.00 61.00 2 +32.00 53.00 9 +63.00 83.00 2 +84.00 98.00 7 +17.00 68.00 9 +63.00 47.00 6 +86.00 69.00 7 +62.00 32.00 6 +26.00 34.00 5 +2.00 99.00 9 +74.00 42.00 6 +21.00 69.00 9 +59.00 59.00 2 +24.00 48.00 9 +86.00 84.00 7 +48.00 45.00 9 +45.00 81.00 9 +50.00 8.00 4 +16.00 35.00 5 +6.00 86.00 9 +55.00 21.00 3 +85.00 41.00 0 +43.00 47.00 9 +73.00 69.00 2 +82.00 75.00 7 +68.00 8.00 3 +17.00 41.00 5 +30.00 29.00 5 +1.00 6.00 5 +77.00 39.00 6 +90.00 78.00 7 +84.00 35.00 0 +11.00 35.00 5 +95.00 27.00 8 +70.00 54.00 2 +65.00 77.00 2 +27.00 50.00 9 +19.00 70.00 9 +50.00 44.00 9 +39.00 84.00 9 +20.00 59.00 9 +92.00 89.00 7 +1.00 22.00 5 +29.00 48.00 9 +93.00 19.00 8 +78.00 30.00 0 +7.00 89.00 9 +65.00 2.00 3 +16.00 87.00 9 +8.00 34.00 5 +64.00 36.00 6 +6.00 34.00 5 +80.00 98.00 7 +70.00 52.00 6 +9.00 63.00 9 +93.00 62.00 1 +37.00 64.00 9 +68.00 18.00 3 +64.00 62.00 2 +90.00 42.00 0 +44.00 97.00 9 +31.00 61.00 9 +51.00 99.00 2 +48.00 60.00 9 +33.00 64.00 9 +96.00 18.00 8 +52.00 54.00 9 +4.00 32.00 5 +4.00 27.00 5 +84.00 14.00 8 +90.00 77.00 7 +76.00 79.00 2 +93.00 45.00 0 +98.00 57.00 1 +59.00 88.00 2 +99.00 55.00 1 +37.00 30.00 5 +16.00 88.00 9 +30.00 16.00 5 +48.00 15.00 3 +32.00 44.00 9 +85.00 84.00 7 +51.00 42.00 9 +16.00 55.00 9 +69.00 52.00 6 +21.00 11.00 5 +82.00 50.00 6 +90.00 75.00 7 diff --git a/input/gtsp-m100-n100-s183.in b/input/gtsp-m100-n100-s183.in new file mode 100644 index 0000000..44fe77c --- /dev/null +++ b/input/gtsp-m100-n100-s183.in @@ -0,0 +1,101 @@ +100 100 +42.00 20.00 0 +43.00 99.00 1 +79.00 2.00 2 +54.00 38.00 3 +13.00 52.00 4 +74.00 49.00 5 +79.00 21.00 6 +0.00 33.00 7 +76.00 26.00 8 +66.00 37.00 9 +32.00 11.00 10 +56.00 84.00 11 +20.00 20.00 12 +33.00 55.00 13 +46.00 95.00 14 +72.00 40.00 15 +16.00 67.00 16 +39.00 47.00 17 +69.00 45.00 18 +85.00 34.00 19 +49.00 11.00 20 +36.00 28.00 21 +32.00 88.00 22 +14.00 60.00 23 +14.00 80.00 24 +98.00 46.00 25 +92.00 54.00 26 +82.00 64.00 27 +74.00 68.00 28 +71.00 72.00 29 +63.00 44.00 30 +12.00 31.00 31 +63.00 3.00 32 +79.00 85.00 33 +48.00 16.00 34 +71.00 97.00 35 +28.00 7.00 36 +26.00 60.00 37 +47.00 40.00 38 +73.00 61.00 39 +72.00 71.00 40 +59.00 16.00 41 +25.00 42.00 42 +81.00 51.00 43 +10.00 52.00 44 +23.00 25.00 45 +48.00 87.00 46 +57.00 64.00 47 +90.00 88.00 48 +49.00 38.00 49 +4.00 20.00 50 +87.00 84.00 51 +80.00 65.00 52 +97.00 27.00 53 +5.00 70.00 54 +41.00 78.00 55 +93.00 0.00 56 +46.00 18.00 57 +94.00 27.00 58 +69.00 56.00 59 +32.00 44.00 60 +82.00 32.00 61 +31.00 91.00 62 +96.00 73.00 63 +79.00 45.00 64 +11.00 35.00 65 +18.00 50.00 66 +72.00 98.00 67 +16.00 69.00 68 +77.00 21.00 69 +91.00 18.00 70 +51.00 84.00 71 +71.00 98.00 72 +54.00 65.00 73 +77.00 75.00 74 +74.00 61.00 75 +19.00 56.00 76 +94.00 50.00 77 +99.00 90.00 78 +23.00 30.00 79 +88.00 86.00 80 +17.00 6.00 81 +88.00 89.00 82 +56.00 4.00 83 +10.00 33.00 84 +78.00 53.00 85 +4.00 81.00 86 +37.00 75.00 87 +31.00 43.00 88 +92.00 9.00 89 +18.00 66.00 90 +70.00 37.00 91 +74.00 64.00 92 +39.00 73.00 93 +7.00 14.00 94 +55.00 95.00 95 +52.00 73.00 96 +1.00 41.00 97 +14.00 9.00 98 +45.00 77.00 99 diff --git a/input/gtsp-m20-n100-s155.in b/input/gtsp-m20-n100-s155.in new file mode 100644 index 0000000..08798eb --- /dev/null +++ b/input/gtsp-m20-n100-s155.in @@ -0,0 +1,101 @@ +100 20 +96.00 27.00 0 +11.00 45.00 1 +42.00 17.00 2 +76.00 35.00 3 +95.00 13.00 4 +18.00 42.00 5 +78.00 92.00 6 +35.00 29.00 7 +50.00 29.00 8 +90.00 32.00 9 +25.00 66.00 10 +19.00 78.00 11 +71.00 99.00 12 +79.00 83.00 13 +30.00 34.00 14 +62.00 26.00 15 +13.00 26.00 16 +71.00 56.00 17 +43.00 99.00 18 +91.00 38.00 19 +65.00 61.00 17 +32.00 43.00 14 +5.00 67.00 11 +72.00 7.00 15 +48.00 14.00 2 +39.00 73.00 10 +32.00 10.00 2 +4.00 4.00 16 +10.00 83.00 11 +39.00 40.00 14 +69.00 2.00 15 +18.00 83.00 11 +28.00 41.00 14 +39.00 23.00 2 +92.00 82.00 13 +13.00 57.00 1 +43.00 45.00 8 +52.00 0.00 2 +64.00 76.00 13 +7.00 12.00 16 +91.00 46.00 19 +86.00 75.00 13 +57.00 90.00 12 +79.00 19.00 3 +25.00 19.00 7 +59.00 94.00 12 +73.00 29.00 3 +77.00 53.00 17 +70.00 68.00 17 +76.00 62.00 17 +50.00 89.00 18 +72.00 45.00 3 +86.00 24.00 9 +45.00 50.00 8 +1.00 52.00 1 +14.00 92.00 11 +51.00 0.00 2 +19.00 8.00 16 +42.00 99.00 18 +79.00 67.00 17 +70.00 38.00 3 +14.00 43.00 1 +67.00 91.00 12 +96.00 37.00 19 +12.00 24.00 16 +51.00 62.00 17 +65.00 23.00 15 +8.00 3.00 16 +48.00 53.00 17 +5.00 49.00 1 +6.00 19.00 16 +93.00 57.00 19 +72.00 12.00 15 +17.00 14.00 16 +63.00 96.00 12 +34.00 85.00 11 +86.00 48.00 19 +28.00 5.00 2 +91.00 76.00 13 +94.00 3.00 4 +52.00 45.00 8 +66.00 17.00 15 +21.00 26.00 16 +20.00 69.00 10 +79.00 77.00 13 +70.00 37.00 3 +97.00 15.00 4 +46.00 69.00 10 +79.00 15.00 4 +35.00 43.00 14 +11.00 69.00 11 +28.00 49.00 5 +69.00 9.00 15 +54.00 61.00 17 +37.00 48.00 14 +64.00 90.00 12 +46.00 82.00 18 +59.00 67.00 17 +8.00 32.00 16 +88.00 40.00 19 diff --git a/input/gtsp-m50-n100-s193.in b/input/gtsp-m50-n100-s193.in new file mode 100644 index 0000000..878bd5b --- /dev/null +++ b/input/gtsp-m50-n100-s193.in @@ -0,0 +1,101 @@ +100 50 +52.00 71.00 0 +4.00 46.00 1 +89.00 23.00 2 +82.00 9.00 3 +56.00 41.00 4 +55.00 21.00 5 +37.00 22.00 6 +85.00 4.00 7 +38.00 37.00 8 +66.00 5.00 9 +20.00 80.00 10 +25.00 47.00 11 +10.00 7.00 12 +15.00 55.00 13 +29.00 73.00 14 +37.00 82.00 15 +97.00 93.00 16 +80.00 86.00 17 +68.00 62.00 18 +95.00 76.00 19 +56.00 2.00 20 +97.00 45.00 21 +76.00 34.00 22 +50.00 14.00 23 +24.00 68.00 24 +19.00 44.00 25 +0.00 96.00 26 +92.00 10.00 27 +55.00 59.00 28 +66.00 85.00 29 +85.00 55.00 30 +19.00 82.00 31 +1.00 51.00 32 +68.00 69.00 33 +66.00 15.00 34 +46.00 22.00 35 +17.00 95.00 36 +19.00 93.00 37 +82.00 21.00 38 +59.00 6.00 39 +89.00 30.00 40 +2.00 90.00 41 +26.00 46.00 42 +52.00 34.00 43 +58.00 70.00 44 +19.00 43.00 45 +26.00 90.00 46 +25.00 27.00 47 +41.00 45.00 48 +48.00 7.00 49 +12.00 46.00 25 +81.00 29.00 22 +42.00 53.00 48 +74.00 76.00 33 +74.00 85.00 17 +34.00 16.00 6 +15.00 88.00 37 +58.00 93.00 29 +35.00 10.00 6 +27.00 93.00 46 +81.00 98.00 17 +36.00 59.00 24 +88.00 13.00 27 +86.00 82.00 17 +58.00 86.00 29 +41.00 70.00 0 +33.00 75.00 14 +51.00 27.00 5 +28.00 77.00 14 +3.00 2.00 12 +62.00 89.00 29 +18.00 77.00 10 +77.00 76.00 17 +22.00 12.00 12 +39.00 50.00 48 +57.00 20.00 5 +0.00 93.00 26 +31.00 89.00 46 +6.00 17.00 12 +23.00 16.00 47 +55.00 64.00 28 +86.00 88.00 17 +39.00 89.00 15 +67.00 67.00 33 +66.00 22.00 34 +22.00 28.00 47 +11.00 92.00 36 +57.00 41.00 4 +21.00 32.00 47 +53.00 60.00 28 +82.00 63.00 30 +32.00 34.00 8 +56.00 63.00 28 +75.00 15.00 3 +32.00 98.00 46 +83.00 87.00 17 +15.00 22.00 47 +28.00 6.00 6 +11.00 95.00 36 +26.00 78.00 10 diff --git a/input/gtsp-m50-n250-s164.in b/input/gtsp-m50-n250-s164.in new file mode 100644 index 0000000..ff05f9b --- /dev/null +++ b/input/gtsp-m50-n250-s164.in @@ -0,0 +1,251 @@ +250 50 +52.00 66.00 0 +3.00 76.00 1 +5.00 56.00 2 +15.00 8.00 3 +11.00 3.00 4 +99.00 46.00 5 +67.00 0.00 6 +59.00 25.00 7 +97.00 95.00 8 +61.00 90.00 9 +0.00 74.00 10 +66.00 53.00 11 +88.00 65.00 12 +84.00 76.00 13 +36.00 83.00 14 +30.00 89.00 15 +2.00 34.00 16 +17.00 7.00 17 +90.00 32.00 18 +67.00 53.00 19 +87.00 66.00 20 +0.00 7.00 21 +19.00 59.00 22 +32.00 68.00 23 +6.00 45.00 24 +58.00 6.00 25 +19.00 24.00 26 +11.00 59.00 27 +41.00 48.00 28 +35.00 29.00 29 +31.00 18.00 30 +18.00 85.00 31 +52.00 88.00 32 +93.00 94.00 33 +72.00 60.00 34 +99.00 12.00 35 +79.00 99.00 36 +19.00 50.00 37 +10.00 3.00 38 +18.00 16.00 39 +48.00 28.00 40 +23.00 19.00 41 +4.00 86.00 42 +78.00 45.00 43 +34.00 66.00 44 +74.00 18.00 45 +84.00 45.00 46 +3.00 88.00 47 +85.00 48.00 48 +34.00 9.00 49 +9.00 33.00 16 +21.00 40.00 37 +33.00 92.00 15 +90.00 43.00 46 +95.00 8.00 35 +12.00 43.00 24 +36.00 87.00 14 +62.00 92.00 9 +73.00 41.00 43 +37.00 8.00 49 +59.00 63.00 0 +26.00 43.00 37 +8.00 81.00 42 +83.00 45.00 46 +30.00 17.00 30 +55.00 91.00 32 +50.00 28.00 40 +31.00 35.00 29 +21.00 21.00 41 +31.00 16.00 30 +81.00 43.00 43 +12.00 69.00 27 +30.00 26.00 29 +61.00 55.00 11 +63.00 78.00 9 +13.00 41.00 24 +73.00 74.00 13 +23.00 56.00 22 +19.00 53.00 37 +73.00 26.00 45 +96.00 76.00 13 +55.00 27.00 7 +63.00 76.00 9 +0.00 94.00 47 +44.00 33.00 40 +54.00 19.00 7 +35.00 15.00 30 +75.00 6.00 6 +17.00 90.00 31 +85.00 30.00 18 +84.00 58.00 12 +56.00 59.00 0 +67.00 28.00 7 +64.00 92.00 9 +54.00 60.00 0 +68.00 9.00 6 +87.00 32.00 18 +37.00 39.00 28 +78.00 34.00 43 +72.00 68.00 34 +42.00 26.00 40 +87.00 29.00 18 +93.00 14.00 35 +36.00 10.00 49 +57.00 73.00 0 +92.00 41.00 5 +83.00 49.00 48 +0.00 50.00 2 +29.00 64.00 23 +95.00 83.00 33 +24.00 63.00 22 +45.00 63.00 0 +47.00 34.00 40 +54.00 26.00 7 +68.00 26.00 7 +94.00 63.00 12 +4.00 33.00 16 +44.00 49.00 28 +48.00 32.00 40 +11.00 57.00 27 +5.00 3.00 38 +98.00 41.00 5 +4.00 50.00 24 +43.00 33.00 40 +14.00 38.00 24 +54.00 14.00 25 +5.00 53.00 2 +48.00 59.00 0 +79.00 17.00 45 +37.00 25.00 29 +32.00 41.00 28 +59.00 76.00 0 +42.00 59.00 28 +9.00 53.00 2 +16.00 66.00 22 +56.00 66.00 0 +7.00 61.00 27 +16.00 3.00 17 +46.00 82.00 32 +41.00 15.00 49 +24.00 47.00 37 +29.00 29.00 29 +1.00 78.00 1 +40.00 80.00 14 +47.00 77.00 0 +58.00 79.00 9 +70.00 69.00 34 +55.00 12.00 25 +28.00 16.00 30 +65.00 96.00 9 +83.00 73.00 13 +14.00 90.00 31 +86.00 82.00 13 +45.00 33.00 40 +64.00 87.00 9 +0.00 40.00 16 +86.00 30.00 18 +21.00 87.00 31 +60.00 61.00 0 +20.00 7.00 17 +90.00 78.00 13 +86.00 12.00 35 +47.00 93.00 32 +24.00 27.00 26 +10.00 41.00 24 +75.00 93.00 36 +66.00 89.00 9 +35.00 5.00 49 +23.00 81.00 31 +38.00 87.00 14 +20.00 38.00 37 +79.00 6.00 6 +20.00 0.00 17 +94.00 80.00 13 +13.00 66.00 27 +87.00 55.00 48 +44.00 25.00 40 +67.00 43.00 11 +71.00 43.00 43 +70.00 33.00 7 +36.00 97.00 15 +26.00 2.00 17 +86.00 13.00 35 +7.00 9.00 4 +46.00 97.00 32 +48.00 18.00 40 +88.00 79.00 13 +25.00 8.00 17 +31.00 71.00 23 +41.00 44.00 28 +37.00 28.00 29 +51.00 33.00 40 +6.00 18.00 39 +76.00 77.00 13 +61.00 98.00 9 +10.00 49.00 24 +95.00 88.00 33 +53.00 11.00 25 +42.00 52.00 28 +60.00 42.00 11 +70.00 48.00 11 +21.00 47.00 37 +9.00 52.00 2 +18.00 50.00 37 +48.00 7.00 25 +30.00 99.00 15 +92.00 88.00 33 +69.00 68.00 34 +17.00 30.00 26 +18.00 79.00 31 +31.00 13.00 30 +19.00 34.00 26 +46.00 73.00 0 +45.00 40.00 28 +25.00 6.00 17 +82.00 47.00 46 +6.00 55.00 2 +95.00 67.00 12 +59.00 65.00 0 +73.00 0.00 6 +58.00 17.00 7 +40.00 27.00 29 +38.00 58.00 44 +9.00 56.00 2 +37.00 40.00 28 +70.00 9.00 6 +75.00 68.00 34 +34.00 72.00 23 +9.00 59.00 27 +30.00 43.00 28 +6.00 37.00 16 +99.00 53.00 5 +4.00 10.00 21 +19.00 74.00 31 +70.00 44.00 43 +26.00 28.00 26 +61.00 66.00 0 +56.00 99.00 9 +24.00 17.00 41 +8.00 14.00 3 +10.00 78.00 1 +23.00 85.00 31 +98.00 9.00 35 +9.00 7.00 4 +68.00 40.00 43 +51.00 26.00 40 +77.00 2.00 6 +80.00 33.00 18 +12.00 51.00 37 +7.00 82.00 42 diff --git a/src/gtsp.c b/src/gtsp.c index c8c89e4..6594238 100644 --- a/src/gtsp.c +++ b/src/gtsp.c @@ -10,7 +10,7 @@ #include "gtsp-subtour.h" #include "gtsp-comb.h" -int large_neighborhood_search(int *tour, struct GTSP *data, int *tour_cost); +int large_neighborhood_search(struct Tour *tour, struct GTSP *data, int *tour_cost); int build_edge_map(struct GTSP *gtsp, int *edge_map); @@ -497,16 +497,34 @@ int GTSP_solution_found(struct BNC *bnc, struct GTSP *data, double *x) UNUSED(bnc); int rval = 0; - + int tour_cost; char filename[100]; - + double *best_val = &bnc->best_obj_val; + + struct Tour* tour; + tour = (struct Tour*) malloc(data->cluster_count*sizeof(struct Tour)); + sprintf(filename, "tmp/gtsp-m%d-n%d-s%d.out", data->cluster_count, data->graph->node_count, SEED); log_info("Writting solution to file %s\n", filename); rval = GTSP_write_solution(data, filename, x); abort_if(rval, "GTSP_write_solution failed"); - + + + rval = build_tour_from_x(data,tour,x); + abort_if(rval, "build_tour_from_x failed"); + + rval = large_neighborhood_search(tour, data, &tour_cost); + abort_if(rval, "large_neighborhood_search failed"); + + if(tour_cost + LP_EPSILON < *best_val){ + log_info("Local search improve the integral solution\n"); + log_info(" obj val = %f\n",*best_val ); + log_info(" after LNS = %d\n",tour_cost ); + *best_val = tour_cost; + } + log_info("Checking solution...\n"); rval = GTSP_check_solution(data, x); abort_if(rval, "GTSP_check_solution failed"); @@ -807,7 +825,7 @@ int GTSP_main(int argc, char **argv) return rval; } -int build_x_from_tour(struct GTSP *data, int *tour, double *x) +int build_x_from_tour(struct GTSP *data, struct Tour *tour, double *x) { int rval = 0; int *edge_map = 0; @@ -824,10 +842,14 @@ int build_x_from_tour(struct GTSP *data, int *tour, double *x) for (int i = 0; i < node_count + edge_count; i++) x[i] = 0.0; + int next_vertex = tour[0].next; + int current_vertex = tour[0].vertex; for (int i = 0; i < data->cluster_count; i++) { - int from = tour[i]; - int to = tour[i + 1]; + int from = current_vertex; + int to = tour[next_vertex].vertex; + current_vertex = tour[next_vertex].vertex; + next_vertex = tour[next_vertex].next; x[from] = 1.0; x[to] = 1.0; @@ -842,14 +864,14 @@ int build_x_from_tour(struct GTSP *data, int *tour, double *x) int inital_tour_value(struct GTSP *data, int *tour_cost, double *x) { int rval = 0; - + int cluster_count = data->cluster_count; - int *tour = 0; + struct Tour *tour = 0; int *uncovered_sets = 0; int *cluster_in_tour = 0; - tour = (int *) malloc((cluster_count + 1) * sizeof(int)); + tour = (struct Tour *) malloc((cluster_count + 1) * sizeof(struct Tour)); uncovered_sets = (int *) malloc((cluster_count - 1) * sizeof(int)); cluster_in_tour = (int *) malloc(cluster_count * sizeof(int)); abort_if(!tour, "could not allocate tour"); @@ -863,49 +885,86 @@ int inital_tour_value(struct GTSP *data, int *tour_cost, double *x) if (data->node_to_cluster[0] != i) { uncovered_sets[cluster_num] = i; - cluster_num += 1; + cluster_num ++; } } - int new_vertex = 1; - tour[0] = 0; + int new_vertex = 1, cost; + + tour[0].vertex = 0; cluster_in_tour[0] = 1; - + while (new_vertex < data->cluster_count) { - int min_vertex = -1; + int min_dist_vertex = -1; int min_cost = INT_MAX; - + for (int i = 1; i < data->graph->node_count; i++) { - if (!cluster_in_tour[data->node_to_cluster[i]]) - { - for (int k = 0; k < new_vertex; k++) - { - int cost = data->dist_matrix[i][tour[k]]; - if (cost < min_cost) - { - min_cost = cost; - min_vertex = i; - } - } - } + if (cluster_in_tour[data->node_to_cluster[i]]) continue; + + for (int k = 0; k < new_vertex; k++) + { + cost = data->dist_matrix[i][tour[k].vertex]; + if (cost < min_cost) + { min_cost = cost; + min_dist_vertex = i; + } + } } - - assert(min_vertex >= 0); - - tour[new_vertex] = min_vertex; - cluster_in_tour[data->node_to_cluster[min_vertex]] = 1; + + assert(min_dist_vertex >= 0); + int cluster_to_insert = data->node_to_cluster[min_dist_vertex]; + cluster_in_tour[cluster_to_insert] = 1; + + min_cost = INT_MAX; + + int insertion_cost = -1, best_pose = -1, best_vertex = -1; + + for (int k=0 ; k < data->clusters[cluster_to_insert].size; k++){ + for(int j = 0; j < new_vertex; j++){ + int vertex_to_insert = data->clusters[cluster_to_insert].nodes[k]; + if (new_vertex ==1){ + int vertex1 = tour[0].vertex; + insertion_cost = data->dist_matrix[vertex_to_insert][vertex1] + + data->dist_matrix[vertex1][vertex_to_insert]; + }else{ + int vertex1 = tour[j].vertex; + int vertex2 = tour[tour[j].next].vertex; + insertion_cost = data->dist_matrix[vertex1][vertex_to_insert] + + data->dist_matrix[vertex_to_insert][vertex2] - + data->dist_matrix[vertex1][vertex2]; + } + if(insertion_cost < min_cost){ + min_cost = insertion_cost; + best_pose = j; + best_vertex = vertex_to_insert; + } + } + } + + tour[new_vertex].vertex = best_vertex; + tour[new_vertex].prev = best_pose; + + if (new_vertex ==1){ + tour[new_vertex].next = best_pose; + tour[best_pose].prev = new_vertex; + }else{ + int temp_vertex = tour[best_pose].next; + tour[new_vertex].next = temp_vertex; + tour[temp_vertex].prev = new_vertex; + } + tour[best_pose].next = new_vertex; + new_vertex += 1; } - tour[data->cluster_count] = 0; + tour[data->cluster_count].vertex = 0; + rval = large_neighborhood_search(tour, data, tour_cost); abort_if(rval, "large_neighborhood_search failed"); - //tour_cost = optimize_vertex_in_cluster(tour, data); - log_info("Initial upper-bound: %d \n", *tour_cost); rval = build_x_from_tour(data, tour, x); @@ -989,47 +1048,30 @@ int two_opt(struct Tour *tour, struct GTSP *data) return 0; } -int large_neighborhood_search(int *tour, struct GTSP *data, int *tour_cost) +int large_neighborhood_search(struct Tour *tour, struct GTSP *data, int *tour_cost) { int rval = 0; - struct Tour *vertex_seq = 0; int cluster_count = data->cluster_count; int *clusters = data->node_to_cluster; int **dist_matrix = data->dist_matrix; struct Cluster *vertex_set = data->clusters; - - vertex_seq = (struct Tour *) malloc(cluster_count * sizeof(struct Tour)); - abort_if(!vertex_seq, "could not allocate vertex_seq"); - - //Construct the list - for (int i = 0; i < cluster_count; i++) - { - vertex_seq[i].vertex = tour[i]; - if (i == 0) - vertex_seq[i].prev = cluster_count - 1; - else - vertex_seq[i].prev = i - 1; - - if (i == cluster_count - 1) - vertex_seq[i].next = 0; - else - vertex_seq[i].next = i + 1; - } - + //LNS starts - for (int iter = 0; iter < 1000; iter++) + for (int iter = 0; iter < 2000; iter++) { - //Delete a vertex + //Delete a random vertex + int delete_vertex = rand() % (cluster_count - 1) + 1; + + + int prev_vertex = tour[delete_vertex].prev; + int next_vertex = tour[delete_vertex].next; - int prev_vertex = vertex_seq[delete_vertex].prev; - int next_vertex = vertex_seq[delete_vertex].next; - - vertex_seq[prev_vertex].next = next_vertex; - vertex_seq[next_vertex].prev = prev_vertex; + tour[prev_vertex].next = next_vertex; + tour[next_vertex].prev = prev_vertex; - int cluster_to_insert = clusters[vertex_seq[delete_vertex].vertex]; + int cluster_to_insert = clusters[tour[delete_vertex].vertex]; int best_pose = -1; int best_vertex = -1; @@ -1039,11 +1081,11 @@ int large_neighborhood_search(int *tour, struct GTSP *data, int *tour_cost) { int vertex_to_insert = vertex_set[cluster_to_insert].nodes[i]; - int next_edge = vertex_seq[0].next; + int next_edge = tour[0].next; for (int j = 1; j < cluster_count; j++) { - int vertex1 = vertex_seq[next_edge].vertex; - int vertex2 = vertex_seq[vertex_seq[next_edge].next].vertex; + int vertex1 = tour[next_edge].vertex; + int vertex2 = tour[tour[next_edge].next].vertex; int insert_cost = dist_matrix[vertex1][vertex_to_insert] + dist_matrix[vertex_to_insert][vertex2] - @@ -1056,31 +1098,34 @@ int large_neighborhood_search(int *tour, struct GTSP *data, int *tour_cost) best_vertex = vertex_to_insert; } - next_edge = vertex_seq[next_edge].next; + next_edge = tour[next_edge].next; } } assert(best_pose >= 0); assert(best_vertex >= 0); - next_vertex = vertex_seq[best_pose].next; - vertex_seq[delete_vertex].prev = best_pose; - vertex_seq[delete_vertex].vertex = best_vertex; - vertex_seq[delete_vertex].next = next_vertex; - vertex_seq[best_pose].next = delete_vertex; - vertex_seq[next_vertex].prev = delete_vertex; - - rval = optimize_vertex_in_cluster(vertex_seq, data); + next_vertex = tour[best_pose].next; + tour[delete_vertex].prev = best_pose; + tour[delete_vertex].vertex = best_vertex; + tour[delete_vertex].next = next_vertex; + tour[best_pose].next = delete_vertex; + tour[next_vertex].prev = delete_vertex; + + rval = optimize_vertex_in_cluster(tour, data); abort_if(rval, "optimize_vertex_in_cluster failed"); } - - rval = two_opt(vertex_seq, data); + + rval = K_opt(tour, data); abort_if(rval, "two_opt failed"); - - *tour_cost = list_length(vertex_seq, data); - + + rval = two_opt(tour, data); + abort_if(rval, "two_opt failed"); + + *tour_cost = list_length(tour, data); + CLEANUP: - if (vertex_seq) free(vertex_seq); + //if (vertex_seq) free(vertex_seq); return rval; } @@ -1134,4 +1179,138 @@ void print_list(struct Tour *tour, struct GTSP *data) printf("\n"); } +int K_opt(struct Tour* tour, struct GTSP *data) +{ + + int cluster_count = data->cluster_count; + int l; + + for(int i = 0 ; i < cluster_count - 3; i++){ + int location_in_path = 0; + + for(int k = 0; k < i; k++) + location_in_path = tour[location_in_path].next; + + int current_vertex = tour[location_in_path].vertex; + + + for(int k = 3; k < cluster_count - i - 2; k++){ + int first_next_location = tour[location_in_path].next; + int first_next_vertex = tour[tour[location_in_path].next].vertex; + int next_location = tour[location_in_path].next; + for(l = 0; l < k; l++){ + next_location = tour[next_location].next; + } + int next_vertex = tour[next_location].vertex; + int next_next_location = tour[next_location].next; + + int next_next_vertex = tour[next_next_location].vertex; + + if(next_next_vertex == current_vertex) break; + + int cost1 = data->dist_matrix[current_vertex][first_next_vertex] + + data->dist_matrix[next_vertex][next_next_vertex]; + int cost2 = data->dist_matrix[current_vertex][next_vertex] + + data->dist_matrix[first_next_vertex][next_next_vertex]; + + if(cost2 < cost1) + { + int tmp_location = next_location; + for(int m =0 ; m < l + 1; m++) + { + int tmp_vertex = tour[tmp_location].next; + tour[tmp_location].next = tour[tmp_location].prev; + tour[tmp_location].prev = tmp_vertex; + tmp_location = tour[tmp_location].next; + } + + tour[location_in_path].next = next_location; + tour[next_location].prev = location_in_path; + + tour[first_next_location].next = next_next_location; + + tour[next_next_location].prev = first_next_location; + + } + } + } + return 0; +} + +int build_tour_from_x(struct GTSP *data, struct Tour *tour, double *x) +{ + + int rval = 0; + int *cluster_mark = 0; + + struct Node **stack = 0; + int stack_top = 0; + + struct Graph *graph = data->graph; + const int node_count = graph->node_count; + + cluster_mark = (int *) malloc(data->cluster_count * sizeof(int)); + abort_if(!cluster_mark, "could not allocate cluster_mark"); + + stack = (struct Node **) malloc(graph->node_count * sizeof(struct Node *)); + abort_if(!stack, "could not allocate stack"); + + for (int i = 0; i < node_count; i++) + graph->nodes[i].mark = 0; + + for (int i = 0; i < data->cluster_count; i++) + cluster_mark[i] = 0; + + int initial; + for (initial = 0; initial < node_count; initial++) + if (x[initial] > 1.0 - LP_EPSILON) break; + + abort_if(initial == node_count, "no initial node"); + + stack[stack_top++] = &graph->nodes[initial]; + graph->nodes[initial].mark = 1; + + tour[0].vertex = graph->nodes[initial].index; + int next_vertex = 1; + + while (stack_top > 0) + { + struct Node *n = stack[--stack_top]; + cluster_mark[data->node_to_cluster[n->index]]++; + + for (int i = 0; i < n->degree; i++) + { + struct Adjacency *adj = &n->adj[i]; + struct Node *neighbor = adj->neighbor; + + if (neighbor->mark) continue; + if (x[node_count + adj->edge->index] < LP_EPSILON) continue; + + stack[stack_top++] = neighbor; + tour[next_vertex].vertex = neighbor->index; + next_vertex++; + neighbor->mark = 1; + + } + } + + + for(int i =0; i < data->cluster_count; i++){ + if(i == 0){ + tour[i].prev = data->cluster_count - 1; + }else{ + tour[i].prev = i-1; + } + if(i == data->cluster_count - 1){ + tour[i].next = 0; + }else{ + tour[i].next = i+1; + } + } + + CLEANUP: + if (stack) free(stack); + if (cluster_mark) free(cluster_mark); + return rval; +} diff --git a/src/gtsp.h b/src/gtsp.h index f69f94d..efa34ba 100644 --- a/src/gtsp.h +++ b/src/gtsp.h @@ -52,7 +52,7 @@ int optimize_vertex_in_cluster(struct Tour * tour, struct GTSP *data); int two_opt(struct Tour * tour, struct GTSP *data); -int K_opt(int* tour, struct GTSP *data); +int K_opt(struct Tour* tour, struct GTSP *data); int tour_length(int* tour, struct GTSP* data); @@ -62,5 +62,6 @@ int list_length(struct Tour * tour, struct GTSP* data); void print_list(struct Tour * tour, struct GTSP* data); +int build_tour_from_x(struct GTSP *data, struct Tour *tour, double *x); #endif //_PROJECT_GTSP_H_ diff --git a/stats.tab b/stats.tab new file mode 100644 index 0000000..33580e9 --- /dev/null +++ b/stats.tab @@ -0,0 +1,5 @@ +instance time subt-t combs-t pool-t pool-m lp-count lp-time lp-rows lp-cols init-v opt-v root-v nodes subt-cc subt-nc subt-nn combs +gtsp-m20-n100-s155 0.48 0.00 0.00 0.13 11 9 0.26 760 4785 272 272 272 1 664 0 0 0 +gtsp-m10-n100-s181 0.27 0.00 0.00 0.04 4 12 0.19 392 4320 179 178 178 1 319 0 0 0 +gtsp-m100-n100-s183 0.91 0.28 0.00 0.03 3 7 0.04 415 5050 824 745 745 1 211 0 0 4 +gtsp-m50-n100-s193 3.85 0.48 0.00 1.37 18 29 0.84 1207 4958 561 538 536 11 1723 0 0 7