void SolveKCenterSubproblems() { Node *N; GainType GlobalBestCost, OldGlobalBestCost; double EntryTime = GetTime(); int CurrentSubproblem, Subproblems; AllocateStructures(); ReadPenalties(); /* Compute upper bound for the original problem */ GlobalBestCost = 0; N = FirstNode; do { if (!Fixed(N, N->SubproblemSuc)) GlobalBestCost += Distance(N, N->SubproblemSuc); N->Subproblem = 0; } while ((N = N->SubproblemSuc) != FirstNode); if (TraceLevel >= 1) { if (TraceLevel >= 2) printff("\n"); printff("*** K-center partitioning *** [Cost = " GainFormat "]\n", GlobalBestCost); } Subproblems = (int) ceil((double) Dimension / SubproblemSize); KCenterClustering(Subproblems); for (CurrentSubproblem = 1; CurrentSubproblem <= Subproblems; CurrentSubproblem++) { OldGlobalBestCost = GlobalBestCost; SolveSubproblem(CurrentSubproblem, Subproblems, &GlobalBestCost); if (SubproblemsCompressed && GlobalBestCost == OldGlobalBestCost) SolveCompressedSubproblem(CurrentSubproblem, Subproblems, &GlobalBestCost); } printff("\nCost = " GainFormat, GlobalBestCost); if (Optimum != MINUS_INFINITY && Optimum != 0) printff(", Gap = %0.4f%%", 100.0 * (GlobalBestCost - Optimum) / Optimum); printff(", Time = %0.2f sec. %s\n", fabs(GetTime() - EntryTime), GlobalBestCost < Optimum ? "<" : GlobalBestCost == Optimum ? "=" : ""); if (SubproblemBorders && Subproblems > 1) SolveSubproblemBorderProblems(Subproblems, &GlobalBestCost); }
void LKH::LKHAlg::CreateCandidateSet() { GainType Cost, MaxAlpha, A; Node *Na; int CandidatesRead = 0, i; double EntryTime = GetTime(); Norm = 9999; if (C == &LKH::LKHAlg::C_EXPLICIT) { Na = FirstNode; do { for (i = 1; i < Na->Id; i++) Na->C[i] *= Precision; } while ((Na = Na->Suc) != FirstNode); } if (Distance == &LKH::LKHAlg::Distance_1 || (MaxTrials == 0 && (FirstNode->InitialSuc || InitialTourAlgorithm == SIERPINSKI || InitialTourAlgorithm == MOORE))) { ReadCandidates(MaxCandidates); AddTourCandidates(); if (ProblemType == HCP || ProblemType == HPP) Ascent(); goto End_CreateCandidateSet; } if (TraceLevel >= 2) printff("Creating candidates ...\n"); if (MaxCandidates > 0 && (CandidateSetType == QUADRANT || CandidateSetType == NN)) { ReadPenalties(); if (!(CandidatesRead = ReadCandidates(MaxCandidates)) && MaxCandidates > 0) { if (CandidateSetType == QUADRANT) CreateQuadrantCandidateSet(MaxCandidates); else if (CandidateSetType == NN) CreateNearestNeighborCandidateSet(MaxCandidates); } else { AddTourCandidates(); if (CandidateSetSymmetric) SymmetrizeCandidateSet(); } goto End_CreateCandidateSet; } if (!ReadPenalties()) { /* No PiFile specified or available */ Na = FirstNode; do Na->Pi = 0; while ((Na = Na->Suc) != FirstNode); CandidatesRead = ReadCandidates(MaxCandidates); Cost = Ascent(); if (Subgradient && SubproblemSize == 0) { WritePenalties(); PiFile = 0; } } else if ((CandidatesRead = ReadCandidates(MaxCandidates)) || MaxCandidates == 0) { AddTourCandidates(); if (CandidateSetSymmetric) SymmetrizeCandidateSet(); goto End_CreateCandidateSet; } else { if (CandidateSetType != DELAUNAY && MaxCandidates > 0) { if (TraceLevel >= 2) printff("Computing lower bound ... "); Cost = Minimum1TreeCost(0); if (TraceLevel >= 2) printff("done\n"); } else { CreateDelaunayCandidateSet(); Na = FirstNode; do { Na->BestPi = Na->Pi; Na->Pi = 0; } while ((Na = Na->Suc) != FirstNode); if (TraceLevel >= 2) printff("Computing lower bound ... "); Cost = Minimum1TreeCost(1); if (TraceLevel >= 2) printff("done\n"); Na = FirstNode; do { Na->Pi = Na->BestPi; Cost -= 2 * Na->Pi; } while ((Na = Na->Suc) != FirstNode); } } LowerBound = (double) Cost / Precision; if (TraceLevel >= 1) { /* printff("Lower bound = %0.1f", LowerBound); if (Optimum != MINUS_INFINITY && Optimum != 0) printff(", Gap = %0.2f%%", 100.0 * (Optimum - LowerBound) / Optimum); if (!PiFile) printff(", Ascent time = %0.2f sec.", fabs(GetTime() - EntryTime)); printff("\n"); */ if (Optimum != MINUS_INFINITY && Optimum != 0) m_Gap=100.0 * (Optimum - LowerBound) / Optimum; if (!PiFile) m_AscentTime=fabs(GetTime() - EntryTime); } MaxAlpha = (GainType) fabs(Excess * Cost); if ((A = Optimum * Precision - Cost) > 0 && A < MaxAlpha) MaxAlpha = A; if (CandidateSetType == DELAUNAY || MaxCandidates == 0) OrderCandidateSet(MaxCandidates, MaxAlpha, CandidateSetSymmetric); else GenerateCandidates(MaxCandidates, MaxAlpha, CandidateSetSymmetric); End_CreateCandidateSet: if (ExtraCandidates > 0) { AddExtraCandidates(ExtraCandidates, ExtraCandidateSetType, ExtraCandidateSetSymmetric); AddTourCandidates(); } ResetCandidateSet(); Na = FirstNode; do { if (!Na->CandidateSet || !Na->CandidateSet[0].To) { if (MaxCandidates == 0) eprintf("MAX_CANDIDATES = 0: Node %d has no candidates", Na->Id); else eprintf("Node %d has no candidates", Na->Id); } } while ((Na = Na->Suc) != FirstNode); if (!CandidatesRead && SubproblemSize == 0) WriteCandidates(); if (C == &LKH::LKHAlg::C_EXPLICIT) { Na = FirstNode; do for (i = 1; i < Na->Id; i++) Na->C[i] += Na->Pi + NodeSet[i].Pi; while ((Na = Na->Suc) != FirstNode); } if (TraceLevel >= 1) { CandidateReport(); // printff("Preprocessing time = %0.2f sec.\n", // fabs(GetTime() - EntryTime)); } }
void SolveKarpSubproblems() { Node *N; int i; double EntryTime = GetTime(); AllocateStructures(); ReadPenalties(); /* Compute upper bound for the original problem */ GlobalBestCost = 0; N = FirstNode; do { if (!Fixed(N, N->SubproblemSuc)) GlobalBestCost += Distance(N, N->SubproblemSuc); N->Subproblem = 0; } while ((N = N->BestSuc = N->SubproblemSuc) != FirstNode); if (TraceLevel >= 1) { if (TraceLevel >= 2) printff("\n"); printff("*** Karp partitioning *** [Cost = " GainFormat "]\n", GlobalBestCost); } if (WeightType == GEO || WeightType == GEOM || WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) { N = FirstNode; do { N->Xc = N->X; N->Yc = N->Y; N->Zc = N->Z; if (WeightType == GEO || WeightType == GEO_MEEUS) GEO2XYZ(N->Xc, N->Yc, &N->X, &N->Y, &N->Z); else GEOM2XYZ(N->Xc, N->Yc, &N->X, &N->Y, &N->Z); } while ((N = N->SubproblemSuc) != FirstNode); CoordType = THREED_COORDS; } KDTree = BuildKDTree(); if (WeightType == GEO || WeightType == GEOM || WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) { N = FirstNode; do { N->X = N->Xc; N->Y = N->Yc; N->Z = N->Zc; } while ((N = N->SubproblemSuc) != FirstNode); CoordType = TWOD_COORDS; } CurrentSubproblem = 0; Subproblems = 1; for (i = Dimension - 1; i > SubproblemSize; i /= 2) Subproblems *= 2; RestrictedSearchSaved = RestrictedSearch; KarpPartition(0, Dimension - 1, 0); free(KDTree); printff("\nCost = " GainFormat, GlobalBestCost); if (Optimum != MINUS_INFINITY && Optimum != 0) printff(", Gap = %0.3f%%", 100.0 * (GlobalBestCost - Optimum) / Optimum); printff(", Time = %0.1f sec. %s\n", fabs(GetTime() - EntryTime), GlobalBestCost < Optimum ? "<" : GlobalBestCost == Optimum ? "=" : ""); if (SubproblemBorders && Subproblems > 1) SolveSubproblemBorderProblems(Subproblems); }
void SolveRoheSubproblems() { Node *N; int CurrentSubproblem, Subproblems, Remaining, i; GainType GlobalBestCost, OldGlobalBestCost; double XMin, XMax, YMin, YMax, ZMin, ZMax, DX, DY, DZ, CLow, CMid, CHigh; double EntryTime = GetTime(); AllocateStructures(); ReadPenalties(); Subproblems = 0; /* Compute upper bound for the original problem */ GlobalBestCost = 0; N = FirstNode; do { if (!Fixed(N, N->SubproblemSuc)) GlobalBestCost += Distance(N, N->SubproblemSuc); N->Subproblem = 0; } while ((N = N->SubproblemSuc) != FirstNode); if (TraceLevel >= 1) { if (TraceLevel >= 2) printff("\n"); printff("*** Rohe partitioning *** [Cost = " GainFormat "]\n", GlobalBestCost); } if (WeightType == GEO || WeightType == GEOM || WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) { N = FirstNode; do { N->Xc = N->X; N->Yc = N->Y; N->Zc = N->Z; if (WeightType == GEO || WeightType == GEO_MEEUS) GEO2XYZ(N->Xc, N->Yc, &N->X, &N->Y, &N->Z); else GEOM2XYZ(N->Xc, N->Yc, &N->X, &N->Y, &N->Z); } while ((N = N->SubproblemSuc) != FirstNode); CoordType = THREED_COORDS; } N = FirstNode; XMin = XMax = N->X; YMin = YMax = N->Y; ZMin = ZMax = N->Z; while ((N = N->SubproblemSuc) != FirstNode) { if (N->X < XMin) XMin = N->X; else if (N->X > XMax) XMax = N->X; if (N->Y < YMin) YMin = N->Y; else if (N->Y > YMax) YMax = N->Y; if (N->Z < ZMin) ZMin = N->Z; else if (N->Z > ZMax) ZMax = N->Z; } KDTree = BuildKDTree(SubproblemSize); Remaining = Dimension; while (Remaining > SubproblemSize) { N = FirstNode; i = Random() % Remaining; while (i--) N = N->Suc; DX = (0.5 + 0.5 * Random() / (PRANDMAX - 1)) * (XMax - XMin); DY = (0.5 + 0.5 * Random() / (PRANDMAX - 1)) * (YMax - YMin); DZ = (0.5 + 0.5 * Random() / (PRANDMAX - 1)) * (ZMax - ZMin); CLow = 0; CHigh = 2; /* Binary search */ do { CMid = (CLow + CHigh) / 2; Size = 0; WindowSize(N->X - CMid * DX, N->X + CMid * DX, N->Y - CMid * DY, N->Y + CMid * DY, N->Z - CMid * DZ, N->Z + CMid * DZ, 0, Dimension - 1); if (Size >= 2.0 / 3 * SubproblemSize && Size <= SubproblemSize) break; if (Size < 2.0 / 3 * SubproblemSize) CLow = CMid; else CHigh = CMid; } while (CHigh - CLow > DBL_EPSILON); MakeSubproblem(N->X - CMid * DX, N->X + CMid * DX, N->Y - CMid * DY, N->Y + CMid * DY, N->Z - CMid * DZ, N->Z + CMid * DZ, ++Subproblems, 0, Dimension - 1); Remaining -= Size; } if (Remaining > 3) { Subproblems++; N = FirstNode; do N->Subproblem = Subproblems; while ((N = N->Suc) != FirstNode); } if (WeightType == GEO || WeightType == GEOM || WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) { N = FirstNode; do { N->X = N->Xc; N->Y = N->Yc; N->Z = N->Zc; } while ((N = N->SubproblemSuc) != FirstNode); CoordType = TWOD_COORDS; } free(KDTree); for (CurrentSubproblem = 1; CurrentSubproblem <= Subproblems; CurrentSubproblem++) { OldGlobalBestCost = GlobalBestCost; SolveSubproblem(CurrentSubproblem, Subproblems, &GlobalBestCost); if (SubproblemsCompressed && GlobalBestCost == OldGlobalBestCost) SolveCompressedSubproblem(CurrentSubproblem, Subproblems, &GlobalBestCost); } printff("\nCost = " GainFormat, GlobalBestCost); if (Optimum != MINUS_INFINITY && Optimum != 0) printff(", Gap = %0.4f%%", 100.0 * (GlobalBestCost - Optimum) / Optimum); printff(", Time = %0.1f sec. %s\n", fabs(GetTime() - EntryTime), GlobalBestCost < Optimum ? "<" : GlobalBestCost == Optimum ? "=" : ""); if (SubproblemBorders && Subproblems > 1) SolveSubproblemBorderProblems(Subproblems, &GlobalBestCost); }