void CreateQuadrantCandidateSet(int K) { Node *From, *To; Candidate *NFrom; int L, Q, CandPerQ, Added, Count, i; if (K <= 0) return; if (TraceLevel >= 2) printff("Creating quadrant candidate set ... "); KDTree = BuildKDTree(1); assert(XMin = (double *) malloc((1 + DimensionSaved) * sizeof(double))); assert(XMax = (double *) malloc((1 + DimensionSaved) * sizeof(double))); assert(YMin = (double *) malloc((1 + DimensionSaved) * sizeof(double))); assert(YMax = (double *) malloc((1 + DimensionSaved) * sizeof(double))); if (CoordType == THREED_COORDS) { assert(ZMin = (double *) malloc((1 + DimensionSaved) * sizeof(double))); assert(ZMax = (double *) malloc((1 + DimensionSaved) * sizeof(double))); } ComputeBounds(0, Dimension - 1); Contains = CoordType == THREED_COORDS ? Contains3D : Contains2D; BoxOverlaps = CoordType == THREED_COORDS ? BoxOverlaps3D : BoxOverlaps2D; L = CoordType == THREED_COORDS ? 8 : 4; CandPerQ = K / L; assert(CandidateSet = (Candidate *) malloc((K + 1) * sizeof(Candidate))); From = FirstNode; do { Count = 0; for (NFrom = From->CandidateSet; NFrom && NFrom->To; NFrom++) if (FixedOrCommon(From, NFrom->To) && ++Count == 2) break; if (Count == 2) continue; Added = 0; for (Q = 1; Q <= L; Q++) { NearestQuadrantNeighbors(From, Q, CandPerQ); for (i = 0; i < Candidates; i++) { To = CandidateSet[i].To; if (AddCandidate(From, To, D(From, To), 1)) Added++; } } if (K > Added) { NearestQuadrantNeighbors(From, 0, K - Added); for (i = 0; i < Candidates; i++) { To = CandidateSet[i].To; AddCandidate(From, To, D(From, To), 2); } } } while ((From = From->Suc) != FirstNode); free(CandidateSet); free(KDTree); free(XMin); free(XMax); free(YMin); free(YMax); if (CoordType == THREED_COORDS) { free(ZMin); free(ZMax); } if (Level == 0 && (WeightType == GEO || WeightType == GEOM || WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS)) { Candidate **SavedCandidateSet; assert(SavedCandidateSet = (Candidate **) malloc((1 + DimensionSaved) * sizeof(Candidate *))); 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 { SavedCandidateSet[From->Id] = From->CandidateSet; From->CandidateSet = 0; 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++; CreateQuadrantCandidateSet(K); Level--; From = FirstNode; do From->Y = From->Zc; while ((From = From->Suc) != FirstNode); do { Candidate *QCandidateSet = From->CandidateSet; From->CandidateSet = SavedCandidateSet[From->Id]; for (NFrom = QCandidateSet; (To = NFrom->To); NFrom++) AddCandidate(From, To, NFrom->Cost, NFrom->Alpha); free(QCandidateSet); } while ((From = From->Suc) != FirstNode); free(SavedCandidateSet); } } if (Level == 0) { ResetCandidateSet(); AddTourCandidates(); if (CandidateSetSymmetric) SymmetrizeCandidateSet(); if (TraceLevel >= 2) printff("done\n"); } }
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 CreateNearestNeighborCandidateSet(int K) { Node *From, *To; int i; if (TraceLevel >= 2) printff("Creating nearest neighbor candidate set ... "); KDTree = BuildKDTree(1); assert(XMin = (double *) malloc((1 + DimensionSaved) * sizeof(double))); assert(XMax = (double *) malloc((1 + DimensionSaved) * sizeof(double))); assert(YMin = (double *) malloc((1 + DimensionSaved) * sizeof(double))); assert(YMax = (double *) malloc((1 + DimensionSaved) * sizeof(double))); if (CoordType == THREED_COORDS) { assert(ZMin = (double *) malloc((1 + DimensionSaved) * sizeof(double))); assert(ZMax = (double *) malloc((1 + DimensionSaved) * sizeof(double))); } ComputeBounds(0, Dimension - 1); Contains = CoordType == THREED_COORDS ? Contains3D : Contains2D; BoxOverlaps = CoordType == THREED_COORDS ? BoxOverlaps3D : BoxOverlaps2D; assert(CandidateSet = (Candidate *) malloc((K + 1) * sizeof(Candidate))); From = FirstNode; do { NearestQuadrantNeighbors(From, 0, K); for (i = 0; i < Candidates; i++) { To = CandidateSet[i].To; AddCandidate(From, To, D(From, To), 1); } } while ((From = From->Suc) != FirstNode); free(CandidateSet); free(KDTree); free(XMin); free(XMax); free(YMin); free(YMax); if (CoordType == THREED_COORDS) { free(ZMin); free(ZMax); } if (Level == 0 && (WeightType == GEOM || WeightType == GEOM_MEEUS)) { Candidate **SavedCandidateSet; assert(SavedCandidateSet = (Candidate **) malloc((1 + DimensionSaved) * sizeof(Candidate *))); if (TraceLevel >= 2) printff("done\n"); /* Transform longitude (180 and -180 map to 0) */ From = FirstNode; do { SavedCandidateSet[From->Id] = From->CandidateSet; From->CandidateSet = 0; From->Yc = From->Y; From->Y += From->Y > 0 ? -180 : 180; } while ((From = From->Suc) != FirstNode); Level++; CreateNearestNeighborCandidateSet(K); Level--; From = FirstNode; do From->Y = From->Yc; while ((From = From->Suc) != FirstNode); do { Candidate *QCandidateSet = From->CandidateSet; Candidate *NFrom; From->CandidateSet = SavedCandidateSet[From->Id]; for (NFrom = QCandidateSet; (To = NFrom->To); NFrom++) AddCandidate(From, To, NFrom->Cost, NFrom->Alpha); free(QCandidateSet); } while ((From = From->Suc) != FirstNode); free(SavedCandidateSet); } if (Level == 0) { ResetCandidateSet(); AddTourCandidates(); if (CandidateSetSymmetric) SymmetrizeCandidateSet(); if (TraceLevel >= 2) printff("done\n"); } }
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); }