void AdjustCandidateSet() { Candidate *NFrom, *NN, Temp; Node *From = FirstNode, *To; /* Extend and reorder candidate sets */ do { if (!From->CandidateSet) assert(From->CandidateSet = (Candidate *) calloc(3, sizeof(Candidate))); /* Extend */ for (To = From->Pred; To; To = To == From->Pred ? From->Suc : 0) { int Count = 0; if ((ProblemType == HCP || ProblemType == HPP) && !IsBackboneCandidate(From, To)) continue; for (NFrom = From->CandidateSet; NFrom->To && NFrom->To != To; NFrom++) Count++; if (!NFrom->To) { /* Add new candidate edge */ NFrom->Cost = C(From, To); NFrom->To = To; NFrom->Alpha = INT_MAX; assert(From->CandidateSet = (Candidate *) realloc(From->CandidateSet, (Count + 2) * sizeof(Candidate))); From->CandidateSet[Count + 1].To = 0; } } /* Reorder */ for (NFrom = From->CandidateSet + 1; (To = NFrom->To); NFrom++) if (InBestTour(From, To) && (InNextBestTour(From, To) || InInitialTour(From, To))) { /* Move the edge to the start of the candidate table */ Temp = *NFrom; for (NN = NFrom - 1; NN >= From->CandidateSet; NN--) *(NN + 1) = *NN; *(NN + 1) = Temp; } } while ((From = From->Suc) != FirstNode); }
int IsPossibleCandidate(Node * From, Node * To) { Node *Na, *Nb, *Nc, *N; if (InInitialTour(From, To) || From->SubproblemSuc == To || To->SubproblemSuc == From || FixedOrCommon(From, To)) return 1; if (From->FixedTo2 || To->FixedTo2) return 0; if (MergeTourFiles < 2) return 1; if (!From->Head) { Nb = FirstNode; do { Na = Nb; Nb = Na->MergeSuc[0]; } while (Nb != FirstNode && FixedOrCommon(Na, Nb)); if (Nb != FirstNode) { N = Nb; do { Nc = Nb; do { Na = Nb; Na->Head = Nc; Nb = Na->MergeSuc[0]; } while (FixedOrCommon(Na, Nb)); do Nc->Tail = Na; while ((Nc = Nc->MergeSuc[0]) != Nb); } while (Nb != N); } else { do Nb->Head = Nb->Tail = FirstNode; while ((Nb = Nb->Suc) != FirstNode); } } if (From->Head == To->Head || (From->Head != From && From->Tail != From) || (To->Head != To && To->Tail != To)) return 0; return 1; }
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(); } } }