int main(int argc, char *argv[]) { GainType Cost; double Time, LastTime = GetTime(); /* Read the specification of the problem */ if (argc >= 2) ParameterFileName = argv[1]; ReadParameters(); MaxMatrixDimension = 10000; ReadProblem(); if (SubproblemSize > 0) { if (DelaunayPartitioning) SolveDelaunaySubproblems(); else if (KarpPartitioning) SolveKarpSubproblems(); else if (KMeansPartitioning) SolveKMeansSubproblems(); else if (RohePartitioning) SolveRoheSubproblems(); else if (SierpinskiPartitioning || MoorePartitioning) SolveSFCSubproblems(); else SolveTourSegmentSubproblems(); return EXIT_SUCCESS; } AllocateStructures(); CreateCandidateSet(); InitializeStatistics(); if (Norm != 0) BestCost = PLUS_INFINITY; else { /* The ascent has solved the problem! */ Optimum = BestCost = (GainType) LowerBound; UpdateStatistics(Optimum, GetTime() - LastTime); RecordBetterTour(); RecordBestTour(); WriteTour(OutputTourFileName, BestTour, BestCost); WriteTour(TourFileName, BestTour, BestCost); Runs = 0; } /* Find a specified number (Runs) of local optima */ for (Run = 1; Run <= Runs; Run++) { LastTime = GetTime(); Cost = FindTour(); /* using the Lin-Kernighan heuristic */ if (MaxPopulationSize > 0) { /* Genetic algorithm */ int i; for (i = 0; i < PopulationSize; i++) Cost = MergeTourWithIndividual(i); if (!HasFitness(Cost)) { if (PopulationSize < MaxPopulationSize) { AddToPopulation(Cost); if (TraceLevel >= 1) PrintPopulation(); } else if (Cost < Fitness[PopulationSize - 1]) { ReplaceIndividualWithTour(PopulationSize - 1, Cost); if (TraceLevel >= 1) PrintPopulation(); } } } else if (Run > 1) Cost = MergeBetterTourWithBestTour(); if (Cost < BestCost) { BestCost = Cost; RecordBetterTour(); RecordBestTour(); WriteTour(OutputTourFileName, BestTour, BestCost); WriteTour(TourFileName, BestTour, BestCost); } if (Cost < Optimum) { if (FirstNode->InputSuc) { Node *N = FirstNode; while ((N = N->InputSuc = N->Suc) != FirstNode); } Optimum = Cost; printff("*** New optimum = " GainFormat " ***\n\n", Optimum); } Time = fabs(GetTime() - LastTime); UpdateStatistics(Cost, Time); if (TraceLevel >= 1 && Cost != PLUS_INFINITY) { printff("Run %d: Cost = " GainFormat, Run, Cost); if (Optimum != MINUS_INFINITY && Optimum != 0) printff(", Gap = %0.3f%%", 100.0 * (Cost - Optimum) / Optimum); printff(", Time = %0.1f sec. %s\n\n", Time, Cost < Optimum ? "<" : Cost == Optimum ? "=" : ""); } if (PopulationSize >= 2 && Run >= MaxPopulationSize && Run < Runs) { Node *N; int Parent1, Parent2; Parent1 = LinearSelection(PopulationSize, 1.25); do Parent2 = LinearSelection(PopulationSize, 1.25); while (Parent1 == Parent2); ApplyCrossover(Parent1, Parent2); N = FirstNode; do { int d = C(N, N->Suc); AddCandidate(N, N->Suc, d, INT_MAX); AddCandidate(N->Suc, N, d, INT_MAX); N = N->InitialSuc = N->Suc; } while (N != FirstNode); } SRandom(++Seed); } PrintStatistics(); return EXIT_SUCCESS; }
void CreateDelaunayCandidateSet() { Node *From, *To; point *u, *v; edge *e_start, *e; int d, i; if (TraceLevel >= 2) printff("Creating Delaunay candidate set ... "); if (Level == 0 && MaxCandidates == 0) { AddTourCandidates(); From = FirstNode; do { if (!From->CandidateSet) eprintf("MAX_CANDIDATES = 0: No candidates"); } while ((From = From->Suc) != FirstNode); if (TraceLevel >= 2) printff("done\n"); return; } /* Find the Delaunay edges */ delaunay(Dimension); /* Add the Delaunay edges to the candidate set */ for (i = 0; i < Dimension; i++) { u = &p_array[i]; From = &NodeSet[u->id]; e_start = e = u->entry_pt; do { v = Other_point(e, u); if (u < v) { To = &NodeSet[v->id]; d = D(From, To); AddCandidate(From, To, d, 1); AddCandidate(To, From, d, 1); } } while ((e = Next(e, u)) != e_start); } free_memory(); if (Level == 0 && (WeightType == GEO || WeightType == GEOM || WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS)) { if (TraceLevel >= 2) printff("done\n"); From = FirstNode; while ((From = From->Suc) != FirstNode) if ((From->Y > 0) != (FirstNode->Y > 0)) break; if (From != FirstNode) { /* Transform longitude (180 and -180 map to 0) */ From = FirstNode; do { From->Zc = From->Y; if (WeightType == GEO || WeightType == GEO_MEEUS) From->Y = (int) From->Y + 5.0 * (From->Y - (int) From->Y) / 3.0; From->Y += From->Y > 0 ? -180 : 180; if (WeightType == GEO || WeightType == GEO_MEEUS) From->Y = (int) From->Y + 3.0 * (From->Y - (int) From->Y) / 5.0; } while ((From = From->Suc) != FirstNode); Level++; CreateDelaunayCandidateSet(); Level--; From = FirstNode; do From->Y = From->Zc; while ((From = From->Suc) != FirstNode); } } if (Level == 0) { AddTourCandidates(); /* Add quadrant neighbors if any node has less than two candidates. That is, if it should happen that delaunay_edges fails. */ From = FirstNode; do { if (From->CandidateSet == 0 || From->CandidateSet[0].To == 0 || From->CandidateSet[1].To == 0) { if (TraceLevel >= 2) printff("*** Not complete ***\n"); AddExtraCandidates(CoordType == THREED_COORDS ? 8 : 4, QUADRANT, 1); break; } } while ((From = From->Suc) != FirstNode); if (TraceLevel >= 2) printff("done\n"); } }
ReturnFlag LKH::LKHAlg::run_() { GainType Cost, OldOptimum; double Time, LastTime = GetTime(); if (SubproblemSize > 0) { if (DelaunayPartitioning) SolveDelaunaySubproblems(); else if (KarpPartitioning) SolveKarpSubproblems(); else if (KCenterPartitioning) SolveKCenterSubproblems(); else if (KMeansPartitioning) SolveKMeansSubproblems(); else if (RohePartitioning) SolveRoheSubproblems(); else if (MoorePartitioning || SierpinskiPartitioning) SolveSFCSubproblems(); else SolveTourSegmentSubproblems(); } AllocateStructures(); CreateCandidateSet(); InitializeStatistics(); if (Norm != 0) BestCost = PLUS_INFINITY; else { /* The ascent has solved the problem! */ Optimum = BestCost = (GainType) LowerBound; UpdateStatistics(Optimum, GetTime() - LastTime); RecordBetterTour(); RecordBestTour(); WriteTour(OutputTourFileName, BestTour, BestCost); WriteTour(TourFileName, BestTour, BestCost); Runs = 0; } /* Find a specified number (Runs) of local optima */ for (Run = 1; Run <= Runs; Run++) { LastTime = GetTime(); Cost = FindTour(); /* using the Lin-Kernighan heuristic */ if (*MaxPopulationSize > 1) { /* Genetic algorithm */ int i; for (i = 0; i < *PopulationSize; i++) { GainType OldCost = Cost; Cost = MergeTourWithIndividual(i,this); if (TraceLevel >= 1 && Cost < OldCost) { printff(" Merged with %d: Cost = " GainFormat, i + 1, Cost); if (Optimum != MINUS_INFINITY && Optimum != 0) printff(", Gap = %0.4f%%", 100.0 * (Cost - Optimum) / Optimum); printff("\n"); } } if (!HasFitness(Cost)) { if (*PopulationSize < *MaxPopulationSize) { AddToPopulation(Cost,this); if (TraceLevel >= 1) PrintPopulation(this); } else if (Cost < Fitness.get()[*PopulationSize - 1]) { i = ReplacementIndividual(Cost,this); ReplaceIndividualWithTour(i, Cost,this); if (TraceLevel >= 1) PrintPopulation(this); } } } else if (Run > 1) Cost = MergeBetterTourWithBestTour(); if (Cost < BestCost) { BestCost = Cost; RecordBetterTour(); RecordBestTour(); WriteTour(OutputTourFileName, BestTour, BestCost); WriteTour(TourFileName, BestTour, BestCost); } OldOptimum = Optimum; if (Cost < Optimum) { if (FirstNode->InputSuc) { Node *N = FirstNode; while ((N = N->InputSuc = N->Suc) != FirstNode); } Optimum = Cost; printff("*** New optimum = " GainFormat " ***\n\n", Optimum); } Time = fabs(GetTime() - LastTime); UpdateStatistics(Cost, Time); if (TraceLevel >= 1 && Cost != PLUS_INFINITY) { printff("Run %d: Cost = " GainFormat, Global::msp_global->m_runId, Cost); if (Optimum != MINUS_INFINITY && Optimum != 0) printff(", Gap = %0.4f%%", 100.0 * (Cost - Optimum) / Optimum); // printff(", Time = %0.2f sec. %s\n\n", Time, // Cost < Optimum ? "<" : Cost == Optimum ? "=" : ""); printff(", Time = %0.2f sec. \n", Time); } if (StopAtOptimum && Cost == OldOptimum && *MaxPopulationSize >= 1) { Runs = Run; break; } if (*PopulationSize >= 2 && (*PopulationSize == *MaxPopulationSize || Run >= 2 * *MaxPopulationSize) && Run < Runs) { Node *N; int Parent1, Parent2; Parent1 = LinearSelection(*PopulationSize, 1.25,this); do Parent2 = LinearSelection(*PopulationSize, 1.25,this); while (Parent2 == Parent1); ApplyCrossover(Parent1, Parent2,this); N = FirstNode; do { int d = (this->*C)(N, N->Suc); AddCandidate(N, N->Suc, d, INT_MAX); AddCandidate(N->Suc, N, d, INT_MAX); N = N->InitialSuc = N->Suc; } while (N != FirstNode); } mv_cost[Global::msp_global->m_runId]=Cost; SRandom(++Seed); } // PrintStatistics(); freeAll(); FreeStructures(); return Return_Terminate; }