int FixedOrCommonCandidates(Node * N) { int Count = 0; Count = N->FixedTo2 ? 2 : N->FixedTo1 ? 1 : 0; if (MergeTourFiles >= 2) { if (!Fixed(N, N->MergeSuc[0]) && IsCommonEdge(N, N->MergeSuc[0])) Count++; if (!Fixed(N->MergePred, N) && IsCommonEdge(N->MergePred, N)) Count++; } if (Count > 2) eprintf("Node %d has more than two required candidate edges", N->Id); return Count; }
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(); } } }