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 (KCenterPartitioning) SolveKCenterSubproblems(); else if (KMeansPartitioning) SolveKMeansSubproblems(); else if (RohePartitioning) SolveRoheSubproblems(); else if (MoorePartitioning || SierpinskiPartitioning) 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 > 1) { /* Genetic algorithm */ int i; for (i = 0; i < PopulationSize; i++) { GainType OldCost = Cost; Cost = MergeTourWithIndividual(i); 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); if (TraceLevel >= 1) PrintPopulation(); } else if (Cost < Fitness[PopulationSize - 1]) { i = ReplacementIndividual(Cost); ReplaceIndividualWithTour(i, 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.4f%%", 100.0 * (Cost - Optimum) / Optimum); printff(", Time = %0.2f sec. %s\n\n", Time, Cost < Optimum ? "<" : Cost == Optimum ? "=" : ""); } if (PopulationSize >= 2 && (PopulationSize == MaxPopulationSize || Run >= 2 * MaxPopulationSize) && Run < Runs) { Node *N; int Parent1, Parent2; Parent1 = LinearSelection(PopulationSize, 1.25); do Parent2 = LinearSelection(PopulationSize, 1.25); while (Parent2 == Parent1); 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 ChooseInitialTour() { Node *N, *NextN, *FirstAlternative, *Last; Candidate *NN; int Alternatives, Count, i; if (KickType > 0 && Kicks > 0 && Trial > 1) { for (Last = FirstNode; (N = Last->BestSuc) != FirstNode; Last = N) Follow(N, Last); for (i = 1; i <= Kicks; i++) KSwapKick(KickType); return; } if (Trial == 1 && (!FirstNode->InitialSuc || InitialTourFraction < 1)) { if (InitialTourAlgorithm == BORUVKA || InitialTourAlgorithm == GREEDY || InitialTourAlgorithm == MOORE || InitialTourAlgorithm == NEAREST_NEIGHBOR || InitialTourAlgorithm == QUICK_BORUVKA || InitialTourAlgorithm == SIERPINSKI) { GainType Cost = InitialTourAlgorithm == MOORE || InitialTourAlgorithm == SIERPINSKI ? SFCTour(InitialTourAlgorithm) : GreedyTour(); if (MaxTrials == 0) { BetterCost = Cost; RecordBetterTour(); } if (!FirstNode->InitialSuc) return; } } Start: /* Mark all nodes as "not chosen" by setting their V field to zero */ N = FirstNode; do N->V = 0; while ((N = N->Suc) != FirstNode); Count = 0; /* Choose FirstNode without two incident fixed or common candidate edges */ do { if (FixedOrCommonCandidates(N) < 2) break; } while ((N = N->Suc) != FirstNode); if (ProblemType == ATSP && N->Id <= DimensionSaved) N += DimensionSaved; FirstNode = N; /* Move nodes with two incident fixed or common candidate edges in front of FirstNode */ for (Last = FirstNode->Pred; N != Last; N = NextN) { NextN = N->Suc; if (FixedOrCommonCandidates(N) == 2) Follow(N, Last); } /* Mark FirstNode as chosen */ FirstNode->V = 1; N = FirstNode; /* Loop as long as not all nodes have been chosen */ while (N->Suc != FirstNode) { FirstAlternative = 0; Alternatives = 0; Count++; /* Case A */ for (NN = N->CandidateSet; (NextN = NN->To); NN++) { if (!NextN->V && Fixed(N, NextN)) { Alternatives++; NextN->Next = FirstAlternative; FirstAlternative = NextN; } } if (Alternatives == 0 && MergeTourFiles > 1) { for (NN = N->CandidateSet; (NextN = NN->To); NN++) { if (!NextN->V && IsCommonEdge(N, NextN)) { Alternatives++; NextN->Next = FirstAlternative; FirstAlternative = NextN; } } } if (Alternatives == 0 && FirstNode->InitialSuc && Trial == 1 && Count <= InitialTourFraction * Dimension) { /* Case B */ for (NN = N->CandidateSet; (NextN = NN->To); NN++) { if (!NextN->V && InInitialTour(N, NextN)) { Alternatives++; NextN->Next = FirstAlternative; FirstAlternative = NextN; } } } if (Alternatives == 0 && Trial > 1 && ProblemType != HCP && ProblemType != HPP) { /* Case C */ for (NN = N->CandidateSet; (NextN = NN->To); NN++) { if (!NextN->V && FixedOrCommonCandidates(NextN) < 2 && NN->Alpha == 0 && (InBestTour(N, NextN) || InNextBestTour(N, NextN))) { Alternatives++; NextN->Next = FirstAlternative; FirstAlternative = NextN; } } } if (Alternatives == 0) { /* Case D */ for (NN = N->CandidateSet; (NextN = NN->To); NN++) { if (!NextN->V && FixedOrCommonCandidates(NextN) < 2) { Alternatives++; NextN->Next = FirstAlternative; FirstAlternative = NextN; } } } if (Alternatives == 0) { /* Case E (actually not really a random choice) */ NextN = N->Suc; while ((FixedOrCommonCandidates(NextN) == 2 || Forbidden(N, NextN)) && NextN->Suc != FirstNode) NextN = NextN->Suc; if (FixedOrCommonCandidates(NextN) == 2 || Forbidden(N, NextN)) { FirstNode = FirstNode->Suc; goto Start; } } else { NextN = FirstAlternative; if (Alternatives > 1) { /* Select NextN at random among the alternatives */ i = Random() % Alternatives; while (i--) NextN = NextN->Next; } } /* Include NextN as the successor of N */ Follow(NextN, N); N = NextN; N->V = 1; } if (Forbidden(N, N->Suc)) { FirstNode = FirstNode->Suc; goto Start; } if (MaxTrials == 0) { GainType Cost = 0; N = FirstNode; do Cost += C(N, N->Suc) - N->Pi - N->Suc->Pi; while ((N = N->Suc) != FirstNode); Cost /= Precision; if (Cost < BetterCost) { BetterCost = Cost; RecordBetterTour(); } } }
GainType LKH::LKHAlg::FindTour() { GainType Cost; Node *t; int i; double EntryTime = GetTime(); if(!OrdinalTourCost.get()) OrdinalTourCost.reset(new GainType(0)); t = FirstNode; do t->OldPred = t->OldSuc = t->NextBestSuc = t->BestSuc = 0; while ((t = t->Suc) != FirstNode); if (Run == 1 && Dimension == DimensionSaved) { *OrdinalTourCost = 0; for (i = 1; i < Dimension; i++) *OrdinalTourCost += (this->*C)(&NodeSet[i], &NodeSet[i + 1]) - NodeSet[i].Pi - NodeSet[i + 1].Pi; *OrdinalTourCost += (this->*C)(&NodeSet[Dimension], &NodeSet[1]) - NodeSet[Dimension].Pi - NodeSet[1].Pi; *OrdinalTourCost /= Precision; } BetterCost = PLUS_INFINITY; if (MaxTrials > 0) HashInitialize(HTable); else { Trial = 1; ChooseInitialTour(); } for (Trial = 1; Trial <= MaxTrials; Trial++) { if (GetTime() - EntryTime >= TimeLimit) { if (TraceLevel >= 1) printff("*** Time limit exceeded ***\n"); break; } /* Choose FirstNode at random */ if (Dimension == DimensionSaved) FirstNode = &NodeSet[1 + Random() % Dimension]; else for (i = Random() % Dimension; i > 0; i--) FirstNode = FirstNode->Suc; ChooseInitialTour(); Cost = LinKernighan(); if (FirstNode->BestSuc) { /* Merge tour with current best tour */ t = FirstNode; while ((t = t->Next = t->BestSuc) != FirstNode); Cost = MergeWithTour(); } if (Dimension == DimensionSaved && Cost >= *OrdinalTourCost && BetterCost > *OrdinalTourCost) { /* Merge tour with ordinal tour */ for (i = 1; i < Dimension; i++) NodeSet[i].Next = &NodeSet[i + 1]; NodeSet[Dimension].Next = &NodeSet[1]; Cost = MergeWithTour(); } if (Cost < BetterCost) { if (TraceLevel >= 1) { /* printff("* %d: Cost = " GainFormat, Trial, Cost); if (Optimum != MINUS_INFINITY && Optimum != 0) printff(", Gap = %0.4f%%", 100.0 * (Cost - Optimum) / Optimum); printff(", Time = %0.2f sec. %s\n", fabs(GetTime() - EntryTime), Cost < Optimum ? "<" : Cost == Optimum ? "=" : ""); */ } BetterCost = Cost; RecordBetterTour(); if (Dimension == DimensionSaved && BetterCost < BestCost) WriteTour(OutputTourFileName, BetterTour, BetterCost); if (StopAtOptimum && BetterCost == Optimum) break; AdjustCandidateSet(); HashInitialize(HTable); HashInsert(HTable, Hash, Cost); } else if (TraceLevel >= 2) printff(" %d: Cost = " GainFormat ", Time = %0.2f sec.\n", Trial, Cost, fabs(GetTime() - EntryTime)); /* Record backbones if wanted */ if (Trial <= BackboneTrials && BackboneTrials < MaxTrials) { SwapCandidateSets(this); AdjustCandidateSet(); if (Trial == BackboneTrials) { if (TraceLevel >= 1) { printff("# %d: Backbone candidates ->\n", Trial); CandidateReport(); } } else SwapCandidateSets(this); } } if (BackboneTrials > 0 && BackboneTrials < MaxTrials) { if (Trial > BackboneTrials || (Trial == BackboneTrials && (!StopAtOptimum || BetterCost != Optimum))) SwapCandidateSets(this); t = FirstNode; do { free(t->BackboneCandidateSet); t->BackboneCandidateSet = 0; } while ((t = t->Suc) != FirstNode); } t = FirstNode; if (Norm == 0) { do t = t->BestSuc = t->Suc; while (t != FirstNode); } do (t->Suc = t->BestSuc)->Pred = t; while ((t = t->BestSuc) != FirstNode); if (Trial > MaxTrials) Trial = MaxTrials; ResetCandidateSet(); return BetterCost; }
int tsp_lkh() { GainType Cost, OldOptimum; double Time, LastTime = GetTime(); /* Read the specification of the problem */ ReadParameters(); MaxMatrixDimension = 10000; init(); AllocateStructures(); CreateCandidateSet(); InitializeStatistics(); BestCost = PLUS_INFINITY; 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); 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); if (TraceLevel >= 1) PrintPopulation(); } else if (Cost < Fitness[PopulationSize - 1]) { i = ReplacementIndividual(Cost); ReplaceIndividualWithTour(i, Cost); if (TraceLevel >= 1) PrintPopulation(); } } } else if (Run > 1) Cost = MergeTourWithBestTour(); if (Cost < BestCost) { BestCost = Cost; RecordBetterTour(); RecordBestTour(); } 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, Run, 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 ? "=" : ""); }*/ 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); do Parent2 = LinearSelection(PopulationSize, 1.25); while (Parent2 == Parent1); ApplyCrossover(Parent1, Parent2); N = FirstNode; do { if (ProblemType != HCP && ProblemType != HPP) { 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(); for (int i = 0; i < TSP_N; i++) { TSP_RESULT[i] = BestTour[i] - 1; } // printf("%d -¡·",BestTour[i]-1); return BestCost; }
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; }