void LKH::LKHAlg::GenerateCandidates(int MaxCandidates, GainType MaxAlpha, int Symmetric) { Node *From, *To; Candidate *NFrom, *NN; int a, d, Count; if (TraceLevel >= 2) printff("Generating candidates ... "); if (MaxAlpha < 0 || MaxAlpha > INT_MAX) MaxAlpha = INT_MAX; /* Initialize CandidateSet for each node */ FreeCandidateSets(); From = FirstNode; do From->Mark = 0; while ((From = From->Suc) != FirstNode); if (MaxCandidates > 0) { do { assert(From->CandidateSet = (Candidate *) malloc((MaxCandidates + 1) * sizeof(Candidate))); From->CandidateSet[0].To = 0; } while ((From = From->Suc) != FirstNode); } else { AddTourCandidates(); do { if (!From->CandidateSet) eprintf("MAX_CANDIDATES = 0: No candidates"); } while ((From = From->Suc) != FirstNode); return; } /* Loop for each node, From */ do { NFrom = From->CandidateSet; if (From != FirstNode) { From->Beta = INT_MIN; for (To = From; To->Dad != 0; To = To->Dad) { To->Dad->Beta = !FixedOrCommon(To, To->Dad) ? Max(To->Beta, To->Cost) : To->Beta; To->Dad->Mark = From; } } Count = 0; /* Loop for each node, To */ To = FirstNode; do { if (To == From) continue; d = c && !FixedOrCommon(From, To) ? (this->*c)(From, To) : (this->*D)(From, To); if (From == FirstNode) a = To == From->Dad ? 0 : d - From->NextCost; else if (To == FirstNode) a = From == To->Dad ? 0 : d - To->NextCost; else { if (To->Mark != From) To->Beta = !FixedOrCommon(To, To->Dad) ? Max(To->Dad->Beta, To->Cost) : To->Dad->Beta; a = d - To->Beta; } if (FixedOrCommon(From, To)) a = INT_MIN; else { if (From->FixedTo2 || To->FixedTo2 || Forbidden(From, To)) continue; if (InInputTour(From, To)) { a = 0; if (c) d = (this->*D)(From, To); } else if (c) { if (a > MaxAlpha || (Count == MaxCandidates && (a > (NFrom - 1)->Alpha || (a == (NFrom - 1)->Alpha && d >= (NFrom - 1)->Cost)))) continue; if (To == From->Dad) { d = From->Cost; a = 0; } else if (From == To->Dad) { d = To->Cost; a = 0; } else { a -= d; a += (d = (this->*D)(From, To)); } } } if (a <= MaxAlpha && IsPossibleCandidate(From, To)) { /* Insert new candidate edge in From->CandidateSet */ NN = NFrom; while (--NN >= From->CandidateSet) { if (a > NN->Alpha || (a == NN->Alpha && d >= NN->Cost)) break; *(NN + 1) = *NN; } NN++; NN->To = To; NN->Cost = d; NN->Alpha = a; if (Count < MaxCandidates) { Count++; NFrom++; } NFrom->To = 0; } } while ((To = To->Suc) != FirstNode); } while ((From = From->Suc) != FirstNode); AddTourCandidates(); if (Symmetric) SymmetrizeCandidateSet(); if (TraceLevel >= 2) printff("done\n"); }
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 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 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)); } }