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); }
static void MarkBorderPoints(int CurrentSubproblem, LKH::LKHAlg * Alg) { double Min[3], Max[3]; int dMin, dMax, d, i, axis, ActualSubproblemSize = 0, Size = 0; LKH::LKHAlg::Node **A, *N; assert(A = (LKH::LKHAlg::Node **) malloc(Alg->DimensionSaved * sizeof(LKH::LKHAlg::Node *))); Min[0] = Min[1] = Min[2] = DBL_MAX; Max[0] = Max[1] = Max[2] = -DBL_MAX; if (Alg->WeightType == LKH::GEO || Alg->WeightType == LKH::GEOM || Alg->WeightType == LKH::GEO_MEEUS || Alg->WeightType == LKH::GEOM_MEEUS) { N = Alg->FirstNode; do { N->Xc = N->X; N->Yc = N->Y; N->Zc = N->Z; if (Alg->WeightType == LKH::GEO || Alg->WeightType == LKH::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) != Alg->FirstNode); Alg->CoordType = LKH::THREED_COORDS; } N = Alg->FirstNode; do { if (N->Subproblem == CurrentSubproblem) { for (i = Alg->CoordType == LKH::THREED_COORDS ? 2 : 1; i >= 0; i--) { if (Coord(N, i) < Min[i]) Min[i] = Coord(N, i); if (Coord(N, i) > Max[i]) Max[i] = Coord(N, i); } ActualSubproblemSize++; } } while ((N = N->SubproblemSuc) != Alg->FirstNode); do { if (N->Subproblem == CurrentSubproblem || (N->X >= Min[0] && N->X <= Max[0] && N->Y >= Min[1] && N->Y <= Max[1] && (Alg->CoordType == LKH::TWOD_COORDS || (N->Z >= Min[2] && N->Z <= Max[2])))) { N->Rank = INT_MAX; for (i = Alg->CoordType == LKH::THREED_COORDS ? 2 : 1; i >= 0; i--) { dMin = (int) (fabs(Coord(N, i) - Min[i]) + 0.5); dMax = (int) (fabs(Coord(N, i) - Max[i]) + 0.5); d = dMin < dMax ? dMin : dMax; if (d < N->Rank) N->Rank = d; } } else { axis = -1; if (Alg->CoordType == LKH::TWOD_COORDS) { if (N->X >= Min[0] && N->X <= Max[0]) axis = 1; else if (N->Y >= Min[1] && N->Y <= Max[1]) axis = 0; } else if (N->X >= Min[0] && N->X <= Max[0]) { if (N->Y >= Min[1] && N->Y <= Max[1]) axis = 2; else if (N->Z >= Min[2] && N->Z <= Max[2]) axis = 1; } else if (N->Y >= Min[1] && N->Y <= Max[1] && N->Z >= Min[2] && N->Z <= Max[2]) axis = 0; if (axis != -1) { dMin = (int) (fabs(Coord(N, axis) - Min[axis]) + 0.5); dMax = (int) (fabs(Coord(N, axis) - Max[axis]) + 0.5); N->Rank = dMin < dMax ? dMin : dMax; } else { N->Rank = 0; for (i = Alg->CoordType == LKH::THREED_COORDS ? 2 : 1; i >= 0; i--) { dMin = (int) (fabs(Coord(N, i) - Min[i]) + 0.5); dMax = (int) (fabs(Coord(N, i) - Max[i]) + 0.5); d = dMin < dMax ? dMin : dMax; if (d > N->Rank) N->Rank = d; } } } N->Subproblem = 0; if (!Alg->SubproblemsCompressed || ((N->SubproblemPred != N->SubBestPred || N->SubproblemSuc != N->SubBestSuc) && (N->SubproblemPred != N->SubBestSuc || N->SubproblemSuc != N->SubBestPred))) A[Size++] = N; } while ((N = N->SubproblemSuc) != Alg->FirstNode); if (ActualSubproblemSize > Size) ActualSubproblemSize = Size; else QuickSelect(A, Size, ActualSubproblemSize); for (Size = 0; Size < ActualSubproblemSize; Size++) A[Size]->Subproblem = CurrentSubproblem; free(A); if (Alg->WeightType == LKH::GEO || Alg->WeightType == LKH::GEOM || Alg-> WeightType == LKH::GEO_MEEUS || Alg->WeightType == LKH::GEOM_MEEUS) { N = Alg->FirstNode; do { N->X = N->Xc; N->Y = N->Yc; N->Z = N->Zc; } while ((N = N->SubproblemSuc) != Alg->FirstNode); Alg->CoordType = LKH::TWOD_COORDS; } }
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); }