Esempio n. 1
0
void LKH::LKHAlg::Connect(Node * N1, int Max, int Sparse)
{
    Node *N;
    Candidate *NN1;
    int d;

    N1->Next = 0;
    N1->NextCost = INT_MAX;
    if (!Sparse || N1->CandidateSet == 0 ||
        N1->CandidateSet[0].To == 0 || N1->CandidateSet[1].To == 0) {
        /* Find the requested edge in a dense graph */
        N = FirstNode;
        do {
            if (N == N1 || N == N1->Dad || N1 == N->Dad)
                continue;
            if (FixedOrCommon(N1, N)) {
                N1->NextCost = (this->*D)(N1, N);
                N1->Next = N;
                return;
            }
            if (!N1->FixedTo2 && !N->FixedTo2 &&
                !Forbidden(N1, N) &&
                (!c || (this->*c)(N1, N) < N1->NextCost) &&
                (d = (this->*D)(N1, N)) < N1->NextCost) {
                N1->NextCost = d;
                if (d <= Max)
                    return;
                N1->Next = N;
            }
        }
        while ((N = N->Suc) != FirstNode);
    } else {
        /* Find the requested edge in a sparse graph */
        for (NN1 = N1->CandidateSet; (N = NN1->To); NN1++) {
            if (N == N1->Dad || N1 == N->Dad)
                continue;
            if (FixedOrCommon(N1, N)) {
                N1->NextCost = NN1->Cost + N1->Pi + N->Pi;
                N1->Next = N;
                return;
            }
            if (!N1->FixedTo2 && !N->FixedTo2 &&
                (d = NN1->Cost + N1->Pi + N->Pi) < N1->NextCost) {
                N1->NextCost = d;
                if (d <= Max)
                    return;
                N1->Next = N;
            }
        }
    }
}
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;
}
Esempio n. 3
0
static int FixedOrCommonCandidates(Node * N)
{
    int Count = 0;
    Candidate *NN;

    if (N->FixedTo2)
        return 2;
    if (!N->FixedTo1 && MergeTourFiles == 0)
        return 0;
    for (NN = N->CandidateSet; NN->To; NN++)
        if (FixedOrCommon(N, NN->To))
            Count++;
    return Count;
}
int FixedOrCommonCandidates(Node * N)
{
    int Count = 0;
    Candidate *NN;

    if (N->FixedTo2)
        return 2;
    if (!N->FixedTo1 && MergeTourFiles < 2)
        return 0;
    for (NN = N->CandidateSet; NN && NN->To; NN++)
        if (FixedOrCommon(N, NN->To))
            Count++;
    if (Count > 2)
        eprintf("Node %d has more than two required candidate edges", N->Id);
    return Count;
}
Esempio n. 5
0
GainType LKH::LKHAlg::PatchCycles(int k, GainType Gain)
{
    Node *s1, *s2, *sStart, *sStop;
    GainType NewGain;
    int M, i;

	if(!CurrentCycle.get())
	{
		CurrentCycle.reset(new int(0));
		Patchwork.reset(new int(0));
		RecLevel.reset(new int(0));
	}
	FindPermutation(k,this);
    M = Cycles(k);
    if (M == 1 && Gain > 0) {
        MakeKOptMove(k);
        return Gain;
    }
    if (M == 1 || M > PatchingC || k + M > NonsequentialMoveType)
        return 0;
    if (*RecLevel == 0)
        *Patchwork = 0;
    *CurrentCycle = ShortestCycle(M, k,this);
    for (i = 0; i < k; i++) {
        if ((*cycle.get())[(*p.get())[2 * i]] != *CurrentCycle)
            continue;
        sStart = (*t.get())[(*p.get())[2 * i]];
        sStop = (*t.get())[(*p.get())[2 * i + 1]];
        for (s1 = sStart; s1 != sStop; s1 = s2) {
            s2 = SUC(s1);
            if (FixedOrCommon(s1, s2))
                continue;
            if (++(*Patchwork) > Dimension)
                return 0;
            (*t.get())[2 * k + 1] = s1;
            (*t.get())[2 * k + 2] = s2;
            MarkDeleted(s1, s2);
            /* Find a set of gainful alternating cycles */
            NewGain = PatchCyclesRec(k, 2, M, Gain + (this->*C)(s1, s2),this);
            UnmarkDeleted(s1, s2);
            if (NewGain > 0)
                return NewGain;
        }
    }
    return 0;
}
Esempio n. 6
0
GainType SFCTour(int CurveType)
{
    double XMin, XMax, YMin, YMax;
    Node *N, **Perm;
    int i;
    IndexFunction Index;
    GainType Cost;
    double EntryTime = GetTime();

    if (CurveType == SIERPINSKI) {
        if (TraceLevel >= 1)
            printff("Sierpinski = ");
        Index = SierpinskiIndex;
    } else {
        if (TraceLevel >= 1)
            printff("Moore = ");
        Index = MooreIndex;
    }
    N = FirstNode;
    XMin = XMax = N->X;
    YMin = YMax = N->Y;
    N->V = 0;
    while ((N = N->Suc) != 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 (XMax == XMin)
        XMax = XMin + 1;
    if (YMax == YMin)
        YMax = YMin + 1;

    assert(Perm = (Node **) malloc(Dimension * sizeof(Node *)));
    for (i = 0, N = FirstNode; i < Dimension; i++, N = N->Suc)
        (Perm[i] = N)->V =
            Index((N->X - XMin) / (XMax - XMin),
                  (N->Y - YMin) / (YMax - YMin));
    qsort(Perm, Dimension, sizeof(Node *), compare);
    for (i = 1; i < Dimension; i++)
        Follow(Perm[i], Perm[i - 1]);
    free(Perm);

    /* Assure that all fixed or common edges belong to the tour */
    N = FirstNode;
    do {
        N->LastV = 1;
        if (!FixedOrCommon(N, N->Suc) && N->CandidateSet) {
            Candidate *NN;
            for (NN = N->CandidateSet; NN->To; NN++) {
                if (!NN->To->LastV && FixedOrCommon(N, NN->To)) {
                    Follow(NN->To, N);
                    break;
                }
            }
        }
    } while ((N = N->Suc) != FirstNode);

    Cost = 0;
    N = FirstNode;
    do
        if (!Fixed(N, N->Suc))
            Cost += Distance(N, N->Suc);
    while ((N = N->Suc) != FirstNode);
    if (TraceLevel >= 1) {
        printff(GainFormat, Cost);
        if (Optimum != MINUS_INFINITY && Optimum != 0)
            printff(", Gap = %0.1f%%", 100.0 * (Cost - Optimum) / Optimum);
        printff(", Time = %0.2f sec.\n", fabs(GetTime() - EntryTime));
    }
    return Cost;
}
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");
    }
}
Esempio n. 8
0
void LKH::LKHAlg::ChooseInitialTour()
{
    Node *N, *NextN, *FirstAlternative, *Last;
    Candidate *NN;
    int Alternatives, Count = 0, 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);

    /* Choose FirstNode without two incident fixed or common candidate edges */
    do {
        if (FixedOrCommonCandidates(N,this) < 2)
            break;
    }
    while ((N = N->Suc) != FirstNode);
    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,this) == 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 && FixedOrCommon(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,this) < 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,this) < 2) {
                    Alternatives++;
                    NextN->Next = FirstAlternative;
                    FirstAlternative = NextN;
                }
            }
        }
        if (Alternatives == 0) {
            /* Case E (actually not really a random choice) */
            NextN = N->Suc;
            while ((FixedOrCommonCandidates(NextN,this) == 2 || Forbidden(N, NextN))
                   && NextN->Suc != FirstNode)
                NextN = NextN->Suc;
            if (FixedOrCommonCandidates(NextN,this) == 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 += (this->*C)(N, N->Suc) - N->Pi - N->Suc->Pi;
        while ((N = N->Suc) != FirstNode);
        Cost /= Precision;
        if (Cost < BetterCost) {
            BetterCost = Cost;
            RecordBetterTour();
        }
    }
}
static int DelaunayClustering(int MaxClusterSize)
{
    int Count = 0, Count1, Count2 = 0, i, j = 0;
    Edge *EdgeSet, Key;
    Node *From, *To, *N, *F, *T;
    point *u, *v;
    edge *e_start, *e;

    delaunay(Dimension);
    for (i = 0; i < Dimension; i++) {
        u = &p_array[i];
        e_start = e = u->entry_pt;
        do {
            v = Other_point(e, u);
            if (u->id < v->id)
                Count++;
        } while ((e = Next(e, u)) != e_start);
    }
    assert(EdgeSet = (Edge *) malloc(Count * sizeof(Edge)));
    for (i = 0; i < Dimension; i++) {
        u = &p_array[i];
        e_start = e = u->entry_pt;
        do {
            v = Other_point(e, u);
            if (u->id < v->id) {
                EdgeSet[j].From = From = &NodeSet[u->id];
                EdgeSet[j].To = To = &NodeSet[v->id];
                EdgeSet[j++].Cost = FixedOrCommon(From, To) ? INT_MIN :
                    Distance(From, To) * Precision + From->Pi + To->Pi;
            }
        } while ((e = Next(e, u)) != e_start);
    }
    free_memory();
    if (WeightType == GEO || WeightType == GEOM ||
        WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) {
        N = FirstNode;
        while ((N = N->Suc) != FirstNode)
            if ((N->Y > 0) != (FirstNode->Y > 0))
                break;
        if (N != FirstNode) {
            N = FirstNode;
            do
                N->Zc = N->Y;
            while ((N = N->Suc) != FirstNode);
            /* Transform longitude (180 and -180 map to 0) */
            From = FirstNode;
            do {
                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);
            delaunay(Dimension);
            do
                From->Y = From->Zc;
            while ((From = From->Suc) != FirstNode);

            qsort(EdgeSet, Count, sizeof(Edge), compareFromTo);
            for (i = 0; i < Dimension; i++) {
                u = &p_array[i];
                e_start = e = u->entry_pt;
                do {
                    v = Other_point(e, u);
                    if (u->id < v->id)
                        Count2++;
                } while ((e = Next(e, u)) != e_start);
            }
            Count1 = Count;
            assert(EdgeSet =
                   (Edge *) realloc(EdgeSet,
                                    (Count1 + Count2) * sizeof(Edge)));
            for (i = 0; i < Dimension; i++) {
                u = &p_array[i];
                e_start = e = u->entry_pt;
                do {
                    v = Other_point(e, u);
                    if (u->id > v->id)
                        continue;
                    Key.From = From = &NodeSet[u->id];
                    Key.To = To = &NodeSet[v->id];
                    if (!bsearch
                        (&Key, EdgeSet, Count1, sizeof(Edge),
                         compareFromTo)) {
                        EdgeSet[Count].From = From;
                        EdgeSet[Count].To = To;
                        EdgeSet[Count].Cost =
                            FixedOrCommon(From, To) ? INT_MIN :
                            Distance(From,
                                     To) * Precision + From->Pi + To->Pi;
                        Count++;
                    }
                } while ((e = Next(e, u)) != e_start);
            }
            free_memory();
        }
    }
    qsort(EdgeSet, Count, sizeof(Edge), compareCost);

    /* Union-Find with path compression */
    N = FirstNode;
    do {
        N->Next = N;
        N->Size = 1;
    } while ((N = N->Suc) != FirstNode);
    for (i = 0; i < Count; i++) {
        for (F = EdgeSet[i].From; F != F->Next;)
            F = F->Next = F->Next->Next;
        for (T = EdgeSet[i].To; T != T->Next;)
            T = T->Next = T->Next->Next;
        if (F != T && F->Size + T->Size <= MaxClusterSize) {
            if (F->Size < T->Size) {
                F->Next = T;
                T->Size += F->Size;
            } else {
                T->Next = F;
                F->Size += T->Size;
            }
        }
    }
    free(EdgeSet);

    Count = 0;
    N = FirstNode;
    do {
        if (N->Next == N && N->Size > 3)
            N->Subproblem = ++Count;
    } while ((N = N->Suc) != FirstNode);
    do {
        for (T = N; T != T->Next;)
            T = T->Next = T->Next->Next;
        N->Subproblem = T->Subproblem;
    } while ((N = N->Suc) != FirstNode);
    return Count;
}
Esempio n. 10
0
Node *Best2OptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain)
{
    Node *t3, *t4, *T3 = 0, *T4 = 0;
    Candidate *Nt2;
    GainType G1, G2, BestG2 = MINUS_INFINITY;
    int Breadth2 = 0;

    if (SUC(t1) != t2)
        Reversed ^= 1;

    /* 
     * Determine (T3,T4) = (t3,t4)
     * such that 
     *
     *     G4 = *G0 - C(t2,T3) + C(T3,T4)
     *
     * is maximum (= BestG2), and (T3,T4) has not previously been included.
     * If during this process a legal move with *Gain > 0 is found, then make
     * the move and exit Best2OptMove immediately 
     */

    /* Choose (t2,t3) as a candidate edge emanating from t2 */
    for (Nt2 = t2->CandidateSet; (t3 = Nt2->To); Nt2++) {
        if (t3 == t2->Pred || t3 == t2->Suc ||
            ((G1 = *G0 - Nt2->Cost) <= 0 && GainCriterionUsed &&
             ProblemType != HCP && ProblemType != HPP))
            continue;
        /* Choose t4 (only one choice gives a closed tour) */
        t4 = PRED(t3);
        if (FixedOrCommon(t3, t4))
            continue;
        G2 = G1 + C(t3, t4);
        if (!Forbidden(t4, t1) &&
            (!c || G2 - c(t4, t1) > 0) && (*Gain = G2 - C(t4, t1)) > 0) {
            Swap1(t1, t2, t3);
            *G0 = G2;
            return 0;
        }
        if (++Breadth2 > MaxBreadth)
            break;
        if (GainCriterionUsed && G2 - Precision < t4->Cost)
            continue;
        if (!Backtracking || Swaps > 0) {
            if (G2 > BestG2 &&
                Swaps < MaxSwaps &&
                Excludable(t3, t4) && (!InInputTour(t3, t4)
                                       || !Near(t3, t4))) {
                T3 = t3;
                T4 = t4;
                BestG2 = G2;
            }
        } else if (MaxSwaps > 0) {
            GainType G = G2;
            Node *t = t4;
            Make2OptMove(t1, t2, t3, t4);
            Exclude(t1, t2);
            Exclude(t3, t4);
            while ((t = BestSubsequentMove(t1, t, &G, Gain)));
            if (*Gain > 0)
                return 0;
            RestoreTour();
            if (t2 != SUC(t1))
                Reversed ^= 1;
        }
    }
    *Gain = 0;
    if (T4) {
        /* Make the best 2-opt move */
        Swap1(t1, t2, T3);
        Exclude(t1, t2);
        Exclude(T3, T4);
        *G0 = BestG2;
    }
    return T4;
}
Esempio n. 11
0
GainType LinKernighan()
{
    Node *t1, *t2, *SUCt1;
    GainType Gain, G0, Cost;
    int X2, i, it = 0;
    Candidate *Nt1;
    Segment *S;
    SSegment *SS;
    double EntryTime = GetTime();

    Reversed = 0;
    S = FirstSegment;
    i = 0;
    do {
        S->Size = 0;
        S->Rank = ++i;
        S->Reversed = 0;
        S->First = S->Last = 0;
    }
    while ((S = S->Suc) != FirstSegment);
    SS = FirstSSegment;
    i = 0;
    do {
        SS->Size = 0;
        SS->Rank = ++i;
        SS->Reversed = 0;
        SS->First = SS->Last = 0;
    }
    while ((SS = SS->Suc) != FirstSSegment);

    FirstActive = LastActive = 0;
    Swaps = 0;

    /* Compute the cost of the initial tour, Cost.
       Compute the corresponding hash value, Hash.
       Initialize the segment list.
       Make all nodes "active" (so that they can be used as t1). */
    Cost = 0;
    Hash = 0;
    i = 0;
    t1 = FirstNode;
    do {
        t2 = t1->OldSuc = t1->Suc;
        t1->OldPred = t1->Pred;
        t1->Rank = ++i;
        Cost += (t1->SucCost = t2->PredCost = C(t1, t2)) - t1->Pi - t2->Pi;
        Hash ^= Rand[t1->Id] * Rand[t2->Id];
        t1->Cost = INT_MAX;
        for (Nt1 = t1->CandidateSet; (t2 = Nt1->To); Nt1++)
            if (t2 != t1->Pred && t2 != t1->Suc && Nt1->Cost < t1->Cost)
                t1->Cost = Nt1->Cost;
        t1->Parent = S;
        S->Size++;
        if (S->Size == 1)
            S->First = t1;
        S->Last = t1;
        if (SS->Size == 0)
            SS->First = S;
        S->Parent = SS;
        SS->Last = S;
        if (S->Size == GroupSize) {
            S = S->Suc;
            SS->Size++;
            if (SS->Size == SGroupSize)
                SS = SS->Suc;
        }
        t1->OldPredExcluded = t1->OldSucExcluded = 0;
        t1->Next = 0;
        if (KickType == 0 || Kicks == 0 ||
            !InBestTour(t1, t1->Pred) || !InBestTour(t1, t1->Suc))
            Activate(t1);
    }
    while ((t1 = t1->Suc) != FirstNode);
    if (S->Size < GroupSize)
        SS->Size++;
    Cost /= Precision;
    if (TraceLevel >= 3 || (TraceLevel == 2 && Cost < BetterCost)) {
        printff("Cost = " GainFormat, Cost);
        if (Optimum != MINUS_INFINITY && Optimum != 0)
            printff(", Gap = %0.4f%%", 100.0 * (Cost - Optimum) / Optimum);
        printff(", Time = %0.1f sec. %s\n", fabs(GetTime() - EntryTime),
                Cost < Optimum ? "<" : Cost == Optimum ? "=" : "");
    }
    PredSucCostAvailable = 1;

    /* Loop as long as improvements are found */
    do {
        /* Choose t1 as the first "active" node */
        while ((t1 = RemoveFirstActive())) {
            /* t1 is now "passive" */
            SUCt1 = SUC(t1);
            if ((TraceLevel >= 3 || (TraceLevel == 2 && Trial == 1)) &&
                ++it % (Dimension >= 100000 ? 10000 :
                        Dimension >= 10000 ? 1000 : 100) == 0)
                printff("#%d: Time = %0.1f sec.\n",
                        it, fabs(GetTime() - EntryTime));
            /* Choose t2 as one of t1's two neighbors on the tour */
            for (X2 = 1; X2 <= 2; X2++) {
                t2 = X2 == 1 ? PRED(t1) : SUCt1;
                if (FixedOrCommon(t1, t2) ||
                    (RestrictedSearch && Near(t1, t2) &&
                     (Trial == 1 ||
                      (Trial > BackboneTrials &&
                       (KickType == 0 || Kicks == 0)))))
                    continue;
                G0 = C(t1, t2);
                /* Try to find a tour-improving chain of moves */
                do
                    t2 = Swaps == 0 ? BestMove(t1, t2, &G0, &Gain) :
                        BestSubsequentMove(t1, t2, &G0, &Gain);
                while (t2);
                if (Gain > 0) {
                    /* An improvement has been found */
                    assert(Gain % Precision == 0);
                    Cost -= Gain / Precision;
                    if (TraceLevel >= 3 ||
                        (TraceLevel == 2 && Cost < BetterCost)) {
                        printff("Cost = " GainFormat, Cost);
                        if (Optimum != MINUS_INFINITY && Optimum != 0)
                            printff(", Gap = %0.4f%%",
                                    100.0 * (Cost - Optimum) / Optimum);
                        printff(", Time = %0.1f sec. %s\n",
                                fabs(GetTime() - EntryTime),
                                Cost < Optimum ? "<" : Cost ==
                                Optimum ? "=" : "");
                    }
                    StoreTour();
                    if (HashSearch(HTable, Hash, Cost))
                        goto End_LinKernighan;
                    /* Make t1 "active" again */
                    Activate(t1);
                    break;
                }
                RestoreTour();
            }
        }
        if (HashSearch(HTable, Hash, Cost))
            goto End_LinKernighan;
        HashInsert(HTable, Hash, Cost);
        /* Try to find improvements using non-sequential 4/5-opt moves */
        Gain = 0;
        if (Gain23Used && (Gain = Gain23()) > 0) {
            /* An improvement has been found */
            assert(Gain % Precision == 0);
            Cost -= Gain / Precision;
            StoreTour();
            if (TraceLevel >= 3 || (TraceLevel == 2 && Cost < BetterCost)) {
                printff("Cost = " GainFormat, Cost);
                if (Optimum != MINUS_INFINITY && Optimum != 0)
                    printff(", Gap = %0.4f%%",
                            100.0 * (Cost - Optimum) / Optimum);
                printff(", Time = %0.1f sec. + %s\n",
                        fabs(GetTime() - EntryTime),
                        Cost < Optimum ? "<" : Cost == Optimum ? "=" : "");
            }
            if (HashSearch(HTable, Hash, Cost))
                goto End_LinKernighan;
        }
    }
    while (Gain > 0);

  End_LinKernighan:
    PredSucCostAvailable = 0;
    NormalizeNodeList();
    NormalizeSegmentList();
    return Cost;
}
Esempio n. 12
0
Node *Best3OptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain)
{
    Node *t3, *t4, *t5, *t6, *T3 = 0, *T4 = 0, *T5 = 0, *T6 = 0;
    Candidate *Nt2, *Nt4;
    GainType G1, G2, G3, G4, BestG4 = MINUS_INFINITY;
    int Case6, BestCase6 = 0, X4, X6;
    int Breadth2 = 0, Breadth4;

    if (SUC(t1) != t2)
        Reversed ^= 1;

    /* 
     * Determine (T3,T4,T5,T6) = (t3,t4,t5,t6)
     * such that 
     *
     *     G4 = *G0 - C(t2,T3) + C(T3,T4) 
     *              - C(T4,T5) + C(T5,T6)
     *
     *  is maximum (= BestG4), and (T5,T6) has not previously been included.
     *  If during this process a legal move with *Gain > 0 is found, then make
     *  the move and exit Best3OptMove immediately. 
     */

    /* Choose (t2,t3) as a candidate edge emanating from t2 */
    for (Nt2 = t2->CandidateSet; (t3 = Nt2->To); Nt2++) {
        if (t3 == t2->Pred || t3 == t2->Suc ||
            ((G1 = *G0 - Nt2->Cost) <= 0 && GainCriterionUsed &&
             ProblemType != HCP && ProblemType != HPP))
            continue;
        if (++Breadth2 > MaxBreadth)
            break;
        /* Choose t4 as one of t3's two neighbors on the tour */
        for (X4 = 1; X4 <= 2; X4++) {
            t4 = X4 == 1 ? PRED(t3) : SUC(t3);
            if (FixedOrCommon(t3, t4))
                continue;
            G2 = G1 + C(t3, t4);
            if (X4 == 1 &&
                !Forbidden(t4, t1) &&
                (!c || G2 - c(t4, t1) > 0) && (*Gain = G2 - C(t4, t1)) > 0)
            {
                Swap1(t1, t2, t3);
                return 0;
            }
            if (Backtracking && !Excludable(t3, t4))
                continue;
            Breadth4 = 0;
            /* Choose (t4,t5) as a candidate edge emanating from t4 */
            for (Nt4 = t4->CandidateSet; (t5 = Nt4->To); Nt4++) {
                if (t5 == t4->Pred || t5 == t4->Suc ||
                    ((G3 = G2 - Nt4->Cost) <= 0 && GainCriterionUsed) ||
                    (X4 == 2 && !BETWEEN(t2, t5, t3)))
                    continue;
                if (++Breadth4 > MaxBreadth)
                    break;
                /* Choose t6 as one of t5's two neighbors on the tour */
                for (X6 = 1; X6 <= X4; X6++) {
                    if (X4 == 1) {
                        Case6 = 1 + !BETWEEN(t2, t5, t4);
                        t6 = Case6 == 1 ? SUC(t5) : PRED(t5);
                    } else {
                        Case6 = 4 + X6;
                        t6 = X6 == 1 ? SUC(t5) : PRED(t5);
                        if (t6 == t1)
                            continue;
                    }
                    if (FixedOrCommon(t5, t6))
                        continue;
                    G4 = G3 + C(t5, t6);
                    if (!Forbidden(t6, t1) &&
                        (!c || G4 - c(t6, t1) > 0) &&
                        (*Gain = G4 - C(t6, t1)) > 0) {
                        Make3OptMove(t1, t2, t3, t4, t5, t6, Case6);
                        return 0;
                    }
                    if (GainCriterionUsed && G4 - Precision < t6->Cost)
                        continue;
                    if (!Backtracking || Swaps > 0) {
                        if (G4 > BestG4 &&
                            Swaps < MaxSwaps &&
                            Excludable(t5, t6) &&
                            (!InInputTour(t5, t6) || !Near(t5, t6))) {
                            /* Ignore the move if the gain does not vary */
                            if (RestrictedSearch &&
                                ProblemType != HCP &&
                                ProblemType != HPP &&
                                G2 - t4->Pi == G4 - t6->Pi &&
                                G3 + t5->Pi == G1 + t3->Pi)
                                continue;
                            T3 = t3;
                            T4 = t4;
                            T5 = t5;
                            T6 = t6;
                            BestCase6 = Case6;
                            BestG4 = G4;
                        }
                    } else if (MaxSwaps > 0) {
                        GainType G = G4;
                        Node *t = t6;
                        Make3OptMove(t1, t2, t3, t4, t5, t6, Case6);
                        Exclude(t1, t2);
                        Exclude(t3, t4);
                        Exclude(t5, t6);
                        while ((t = BestSubsequentMove(t1, t, &G, Gain)));
                        if (*Gain > 0)
                            return 0;
                        RestoreTour();
                        if (t2 != SUC(t1))
                            Reversed ^= 1;
                    }
                }
            }
        }
    }
    *Gain = 0;
    if (T6) {
        /* Make the best 3-opt move */
        Make3OptMove(t1, t2, T3, T4, T5, T6, BestCase6);
        Exclude(t1, t2);
        Exclude(T3, T4);
        Exclude(T5, T6);
        *G0 = BestG4;
    }
    return T6;
}
Esempio n. 13
0
LKH::LKHAlg::Node * LKH::LKHAlg::Best5OptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain)
{
    Node *t3, *t4, *t5, *t6 = 0, *t7, *t8 = 0, *t9, *t10 = 0;
    Node *T3 = 0, *T4 = 0, *T5 = 0, *T6 = 0, *T7 = 0, *T8 = 0, *T9 =
        0, *T10 = 0;
    Candidate *Nt2, *Nt4, *Nt6, *Nt8;
    GainType G1, G2, G3, G4, G5, G6, G7, G8, BestG8 = MINUS_INFINITY;
    int Case6 = 0, Case8 = 0, Case10 = 0, BestCase10 = 0, X4, X6, X8, X10,
        BTW275 = 0, BTW674 = 0,
        BTW571 = 0, BTW376 = 0, BTW574 = 0, BTW671 = 0,
        BTW471 = 0, BTW673 = 0, BTW573 = 0, BTW273 = 0;
    int Breadth2 = 0, Breadth4, Breadth6, Breadth8;

    if (t2 != SUC(t1))
        Reversed ^= 1;

    /* 
     * Determine (T3,T4,T5,T6,T7,T8,T9,T10) = (t3,t4,t5,t6,t7,t8,t9,t10)
     * such that
     *
     *     G8 = *G0 - C(t2,T3) + C(T3,T4)
     *              - C(T4,T5) + C(T5,T6)
     *              - C(T6,T7) + C(T7,T8)
     *              - C(T8,T9) + C(T9,T10)
     *
     * is maximum (= BestG8), and (T9,T10) has not previously been included.
     * If during this process a legal move with *Gain > 0 is found, then make
     * the move and exit Best5OptMove immediately. 
     */

    /* Choose (t2,t3) as a candidate edge emanating from t2 */
    for (Nt2 = t2->CandidateSet; (t3 = Nt2->To); Nt2++) {
        if (t3 == t2->Pred || t3 == t2->Suc ||
            ((G1 = *G0 - Nt2->Cost) <= 0 && GainCriterionUsed &&
             ProblemType != HCP && ProblemType != HPP))
            continue;
        if (++Breadth2 > MaxBreadth)
            break;
        /* Choose t4 as one of t3's two neighbors on the tour */
        for (X4 = 1; X4 <= 2; X4++) {
            t4 = X4 == 1 ? PRED(t3) : SUC(t3);
            if (FixedOrCommon(t3, t4))
                continue;
            G2 = G1 + (this->*C)(t3, t4);
            if (X4 == 1 &&
                !Forbidden(t4, t1) &&
                (!c || G2 - (this->*c)(t4, t1) > 0) && (*Gain = G2 - (this->*C)(t4, t1)) > 0)
            {
                Make2OptMove(t1, t2, t3, t4);
                return 0;
            }
            if (Backtracking && !Excludable(t3, t4))
                continue;
            Breadth4 = 0;
            /* Choose (t4,t5) as a candidate edge emanating from t4 */
            for (Nt4 = t4->CandidateSet; (t5 = Nt4->To); Nt4++) {
                if (t5 == t4->Pred || t5 == t4->Suc ||
                    ((G3 = G2 - Nt4->Cost) <= 0 && GainCriterionUsed &&
                     ProblemType != HCP && ProblemType != HPP))
                    continue;
                if (++Breadth4 > MaxBreadth)
                    break;
                /* Choose t6 as one of t5's two neighbors on the tour */
                for (X6 = 1; X6 <= 2; X6++) {
                    if (X4 == 1) {
                        if (X6 == 1) {
                            Case6 = 1 + !BETWEEN(t2, t5, t4);
                            t6 = Case6 == 1 ? SUC(t5) : PRED(t5);
                        } else {
                            t6 = t6 == t5->Pred ? t5->Suc : t5->Pred;
                            if ((t5 == t1 && t6 == t2) ||
                                (t5 == t2 && t6 == t1))
                                continue;
                            Case6 += 2;
                        }
                    } else if (BETWEEN(t2, t5, t3)) {
                        Case6 = 4 + X6;
                        t6 = X6 == 1 ? SUC(t5) : PRED(t5);
                        if (t6 == t1)
                            continue;
                    } else {
                        Case6 = 6 + X6;
                        t6 = X6 == 1 ? PRED(t5) : SUC(t5);
                        if (t6 == t2)
                            continue;
                    }
                    if (FixedOrCommon(t5, t6))
                        continue;
                    G4 = G3 + (this->*C)(t5, t6);
                    if ((Case6 <= 2 || Case6 == 5 || Case6 == 6) &&
                        !Forbidden(t6, t1) &&
                        (!c || G4 - (this->*c)(t6, t1) > 0) &&
                        (*Gain = G4 - (this->*C)(t6, t1)) > 0) {
                        Make3OptMove(t1, t2, t3, t4, t5, t6, Case6);
                        return 0;
                    }
                    if (Backtracking && !Excludable(t5, t6))
                        continue;
                    Breadth6 = 0;
                    /* Choose (t6,t7) as a candidate edge emanating from t6 */
                    for (Nt6 = t6->CandidateSet; (t7 = Nt6->To); Nt6++) {
                        if (t7 == t6->Pred || t7 == t6->Suc ||
                            (t6 == t2 && t7 == t3) ||
                            (t6 == t3 && t7 == t2) ||
                            ((G5 = G4 - Nt6->Cost) <= 0 &&
                             GainCriterionUsed &&
                             ProblemType != HCP && ProblemType != HPP))
                            continue;
                        if (++Breadth6 > MaxBreadth)
                            break;
                        /* Choose t8 as one of t7's two neighbors on the tour */
                        for (X8 = 1; X8 <= 2; X8++) {
                            if (X8 == 1) {
                                Case8 = Case6;
                                switch (Case6) {
                                case 1:
                                    if ((BTW275 = BETWEEN(t2, t7, t5)))
                                        t8 = SUC(t7);
                                    else {
                                        t8 = PRED(t7);
                                        BTW674 = BETWEEN(t6, t7, t4);
                                    }
                                    break;
                                case 2:
                                    if ((BTW376 = BETWEEN(t3, t7, t6)))
                                        t8 = SUC(t7);
                                    else {
                                        t8 = PRED(t7);
                                        BTW571 = BETWEEN(t5, t7, t1);
                                    }
                                    break;
                                case 3:
                                    t8 = SUC(t7);
                                    BTW574 = BETWEEN(t5, t7, t4);
                                    break;
                                case 4:
                                    if ((BTW671 = BETWEEN(t6, t7, t1)))
                                        t8 = PRED(t7);
                                    else
                                        t8 = BETWEEN(t2, t7,
                                                     t4) ? SUC(t7) :
                                            PRED(t7);
                                    break;
                                case 5:
                                    t8 = PRED(t7);
                                    BTW471 = BETWEEN(t4, t7, t1);
                                    if (!BTW471)
                                        BTW673 = BETWEEN(t6, t7, t3);
                                    break;
                                case 6:
                                    if ((BTW471 = BETWEEN(t4, t7, t1)))
                                        t8 = PRED(t7);
                                    else {
                                        t8 = SUC(t7);
                                        BTW573 = BETWEEN(t5, t7, t3);
                                    }
                                    break;
                                case 7:
                                case 8:
                                    t8 = SUC(t7);
                                    BTW273 = BETWEEN(t2, t7, t3);
                                    break;
                                }
                            } else {
                                t8 = t8 == t7->Pred ? t7->Suc : t7->Pred;
                                Case8 += 8;
                            }
                            if ((t7 == t1 && t8 == t2) ||
                                (t7 == t2 && t8 == t1) ||
                                (t7 == t3 && t8 == t4) ||
                                (t7 == t4 && t8 == t3))
                                continue;
                            if (FixedOrCommon(t7, t8))
                                continue;
                            if (Case6 == 3 && !BTW574 &&
                                (X8 == 1) == BETWEEN(t3, t7, t1))
                                continue;
                            if (Case6 == 4 && BTW671 && X8 == 2)
                                break;
                            if (Case6 == 7 && !BTW273 &&
                                (X8 == 1) == BETWEEN(t5, t7, t1))
                                continue;
                            if (Case6 == 8 && !BTW273
                                && !BETWEEN(t4, t7, t5))
                                break;
                            G6 = G5 + (this->*C)(t7, t8);
                            if (t8 != t1 &&
                                (Case6 == 3 ? BTW574 :
                                 Case6 == 4 ? !BTW671 :
                                 Case6 == 7 ? BTW273 :
                                 Case6 != 8 && X8 == 1) &&
                                !Forbidden(t8, t1) &&
                                (!c || G6 - (this->*c)(t8, t1) > 0) &&
                                (*Gain = G6 - (this->*C)(t8, t1)) > 0) {
                                Make4OptMove(t1, t2, t3, t4, t5, t6, t7,
                                             t8, Case8);
                                return 0;
                            }
                            if (Backtracking && !Excludable(t7, t8))
                                continue;
                            Breadth8 = 0;
                            /* Choose (t8,t9) as a candidate edge emanating 
                               from t8 */
                            for (Nt8 = t8->CandidateSet; (t9 = Nt8->To);
                                 Nt8++) {
                                if (t9 == t8->Pred || t9 == t8->Suc
                                    || t9 == t1 || (t8 == t2 && t9 == t3)
                                    || (t8 == t3 && t9 == t2) || (t8 == t4
                                                                  && t9 ==
                                                                  t5)
                                    || (t8 == t5 && t9 == t4)
                                    || ((G7 = G6 - Nt8->Cost) <= 0
                                        && GainCriterionUsed
                                        && ProblemType != HCP
                                        && ProblemType != HPP))
                                    continue;
                                if (++Breadth8 > MaxBreadth)
                                    break;
                                /* Choose t10 as one of t9's two neighbors 
                                   on the tour */
                                for (X10 = 1; X10 <= 2; X10++) {
                                    if (X10 == 1) {
                                        t10 = 0;
                                        switch (Case8) {
                                        case 1:
                                            t10 = (BTW275 ?
                                                   BETWEEN(t8, t9, t5)
                                                   || BETWEEN(t3, t9,
                                                              t1) : BTW674
                                                   ? BETWEEN(t7, t9,
                                                             t1) :
                                                   BETWEEN(t7, t9,
                                                           t5)) ? PRED(t9)
                                                : SUC(t9);
                                            Case10 = 22;
                                            break;
                                        case 2:
                                            t10 = (BTW376 ?
                                                   BETWEEN(t8, t9, t4) :
                                                   BTW571 ?
                                                   BETWEEN(t7, t9, t1)
                                                   || BETWEEN(t3, t9,
                                                              t6) :
                                                   BETWEEN(t7, t9,
                                                           t1)) ? PRED(t9)
                                                : SUC(t9);
                                            Case10 = 23;
                                            break;
                                        case 3:
                                            if (BTW574) {
                                                t10 = BETWEEN(t5, t9, t1) ?
                                                    PRED(t9) : SUC(t9);
                                                Case10 = 24;
                                                break;
                                            }
                                            if (!BETWEEN(t5, t9, t4))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 1;
                                            break;
                                        case 4:
                                            if (BTW671) {
                                                if (!BETWEEN(t2, t9, t5))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 2;
                                                break;
                                            }
                                            t10 = BETWEEN(t6, t9, t4) ?
                                                PRED(t9) : SUC(t9);
                                            Case10 = 25;
                                            break;
                                        case 5:
                                            t10 = (BTW471 ?
                                                   BETWEEN(t7, t9, t1) :
                                                   BTW673 ?
                                                   BETWEEN(t7, t9, t5) :
                                                   BETWEEN(t4, t9, t1)
                                                   || BETWEEN(t7, t9,
                                                              t5)) ?
                                                PRED(t9) : SUC(t9);
                                            Case10 = 26;
                                            break;
                                        case 6:
                                            t10 = (BTW471 ?
                                                   BETWEEN(t7, t9, t3) :
                                                   BTW573 ?
                                                   BETWEEN(t8, t9, t6) :
                                                   BETWEEN(t4, t9, t1)
                                                   || BETWEEN(t8, t9,
                                                              t6)) ?
                                                PRED(t9) : SUC(t9);
                                            Case10 = 27;
                                            break;
                                        case 7:
                                            if (BTW273) {
                                                t10 = BETWEEN(t5, t9, t3) ?
                                                    PRED(t9) : SUC(t9);
                                                Case10 = 28;
                                                break;
                                            }
                                            if (!BETWEEN(t2, t9, t3))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 3;
                                            break;
                                        case 8:
                                            if (BTW273) {
                                                if (!BETWEEN(t4, t9, t5))
                                                    break;
                                                Case10 = 4;
                                            } else {
                                                if (!BETWEEN(t2, t9, t3))
                                                    break;
                                                Case10 = 5;
                                            }
                                            t10 = SUC(t9);
                                            break;
                                        case 9:
                                            if (BTW275) {
                                                if (!BETWEEN(t7, t9, t4))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 6;
                                                break;
                                            }
                                            if (!BTW674) {
                                                if (!BETWEEN(t2, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 7;
                                                break;
                                            }
                                            if (!BETWEEN(t6, t9, t7))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 8;
                                            break;
                                        case 10:
                                            if (BTW376) {
                                                if (!BETWEEN(t7, t9, t6))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 9;
                                                break;
                                            }
                                            if (BTW571) {
                                                if (!BETWEEN(t2, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 10;
                                                break;
                                            }
                                            if (!BETWEEN(t3, t9, t6) &&
                                                !BETWEEN(t2, t9, t7))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 11;
                                            break;
                                        case 11:
                                            if (BTW574) {
                                                t10 = BETWEEN(t3, t9, t1) ?
                                                    PRED(t9) : SUC(t9);
                                                Case10 = 29;
                                                break;
                                            }
                                            if (!BETWEEN(t5, t9, t4))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 12;
                                            break;
                                        case 12:
                                            t10 = BETWEEN(t3, t9, t1) ?
                                                PRED(t9) : SUC(t9);
                                            Case10 = 30;
                                            break;
                                        case 13:
                                            if (BTW471) {
                                                if (!BETWEEN(t2, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 13;
                                                break;
                                            }
                                            if (BTW673) {
                                                if (!BETWEEN(t6, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 14;
                                                break;
                                            }
                                            if (!BETWEEN(t6, t9, t3) &&
                                                !BETWEEN(t2, t9, t7))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 15;
                                            break;
                                        case 14:
                                            if (BTW471) {
                                                if (!BETWEEN(t2, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 16;
                                                break;
                                            }
                                            if (BTW573) {
                                                if (!BETWEEN(t7, t9, t3) &&
                                                    !BETWEEN(t2, t9, t6))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 17;
                                                break;
                                            }
                                            if (!BETWEEN(t7, t9, t6))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 18;
                                            break;
                                        case 15:
                                            if (BTW273) {
                                                t10 = BETWEEN(t5, t9, t1) ?
                                                    PRED(t9) : SUC(t9);
                                                Case10 = 31;
                                                break;
                                            }
                                            if (!BETWEEN(t2, t9, t3))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 19;
                                            break;
                                        case 16:
                                            if (BTW273) {
                                                if (!BETWEEN(t4, t9, t5))
                                                    break;
                                                Case10 = 20;
                                            } else {
                                                if (!BETWEEN(t2, t9, t3))
                                                    break;
                                                Case10 = 21;
                                            }
                                            t10 = SUC(t9);
                                            break;
                                        }
                                        if (!t10)
                                            break;
                                    } else {
                                        if (Case10 >= 22)
                                            continue;
                                        Case10 += 31;
                                        t10 =
                                            t10 ==
                                            t9->Pred ? t9->Suc : t9->Pred;
                                    }
                                    if (t10 == t1 ||
                                        (t9 == t3 && t10 == t4) ||
                                        (t9 == t4 && t10 == t3) ||
                                        (t9 == t5 && t10 == t6) ||
                                        (t9 == t6 && t10 == t5))
                                        continue;
                                    if (FixedOrCommon(t9, t10))
                                        continue;
                                    G8 = G7 + (this->*C)(t9, t10);
                                    if (!Forbidden(t10, t1) &&
                                        (!c || G8 - (this->*c)(t10, t1) > 0) &&
                                        (*Gain = G8 - (this->*C)(t10, t1)) > 0) {
                                        Make5OptMove(t1, t2, t3, t4, t5,
                                                     t6, t7, t8, t9, t10,
                                                     Case10);
                                        return 0;
                                    }
                                    if (GainCriterionUsed &&
                                        G8 - Precision < t10->Cost)
                                        continue;
                                    if (!Backtracking || Swaps > 0) {
                                        if ((G8 > BestG8 ||
                                             (G8 == BestG8 && !Near(t9, t10)
                                              && Near(T9, T10)))
                                            && Swaps < MaxSwaps
                                            && Excludable(t9, t10)
                                            && !InInputTour(t9, t10)) {
                                            /* Ignore the move if the gain does
                                               not vary */
                                            if (RestrictedSearch &&
                                                ProblemType != HCP &&
                                                ProblemType != HPP &&
                                                G2 - t4->Pi == G4 - t6->Pi && 
                                                G4 - t6->Pi == G6 - t8->Pi &&
                                                G6 - t8->Pi == G8 - t10->Pi &&
                                                G3 + t5->Pi == G1 + t3->Pi &&
                                                G5 + t7->Pi == G3 + t5->Pi &&
                                                G7 + t9->Pi == G5 + t7->Pi)
                                                continue;
                                            T3 = t3;
                                            T4 = t4;
                                            T5 = t5;
                                            T6 = t6;
                                            T7 = t7;
                                            T8 = t8;
                                            T9 = t9;
                                            T10 = t10;
                                            BestCase10 = Case10;
                                            BestG8 = G8;
                                        }
                                    } else if (MaxSwaps > 0) {
                                        GainType G = G8;
                                        Node *t = t10;
                                        Make5OptMove(t1, t2, t3, t4, t5,
                                                     t6, t7, t8, t9, t10,
                                                     Case10);
                                        Exclude(t1, t2);
                                        Exclude(t3, t4);
                                        Exclude(t5, t6);
                                        Exclude(t7, t8);
                                        Exclude(t9, t10);
                                        while ((t =
                                                (this->*BestSubsequentMove)(t1, t,
                                                                   &G,
                                                                   Gain)));
                                        if (*Gain > 0)
                                            return 0;
                                        RestoreTour();
                                        if (t2 != SUC(t1))
                                            Reversed ^= 1;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    *Gain = 0;
    if (T10) {
        /* Make the best 5-opt move */
        Make5OptMove(t1, t2, T3, T4, T5, T6, T7, T8, T9, T10, BestCase10);
        Exclude(t1, t2);
        Exclude(T3, T4);
        Exclude(T5, T6);
        Exclude(T7, T8);
        Exclude(T9, T10);
        *G0 = BestG8;
    }
    return T10;
}
Esempio n. 14
0
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");
}
Esempio n. 15
0
LKH::LKHAlg::Node * LKH::LKHAlg::Best4OptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain)
{
    Node *t3, *t4, *t5, *t6 = 0, *t7, *t8 = 0,
        *T3 = 0, *T4 = 0, *T5 = 0, *T6 = 0, *T7 = 0, *T8 = 0;
    Candidate *Nt2, *Nt4, *Nt6;
    GainType G1, G2, G3, G4, G5, G6, BestG6 = MINUS_INFINITY;
    int Case6 = 0, Case8 = 0, BestCase8 = 0, X4, X6, X8;
    int Breadth2 = 0, Breadth4, Breadth6;

    *Gain = 0;
    if (SUC(t1) != t2)
        Reversed ^= 1;

    /* 
     * Determine (T3,T4,T5,T6,T7,T8) = (t3,t4,t5,t6,t7,t8)
     * such that
     *
     *     G8 = *G0 - C(t2,T3) + C(T3,T4) 
     *              - C(T4,T5) + C(T5,T6)
     *              - C(T6,T7) + C(T7,T8)
     *
     * is maximum (= BestG6), and (T7,T8) has not previously been included.
     * If during this process a legal move with *Gain > 0 is found, then make
     * the move and exit Best4OptMove immediately. 
     */

    /* Choose (t2,t3) as a candidate edge emanating from t2 */
    for (Nt2 = t2->CandidateSet; (t3 = Nt2->To); Nt2++) {
        if (t3 == t2->Pred || t3 == t2->Suc ||
            ((G1 = *G0 - Nt2->Cost) <= 0 && GainCriterionUsed &&
             ProblemType != HCP && ProblemType != HPP))
            continue;
        if (++Breadth2 > MaxBreadth)
            break;
        /* Choose t4 as one of t3's two neighbors on the tour */
        for (X4 = 1; X4 <= 2; X4++) {
            t4 = X4 == 1 ? PRED(t3) : SUC(t3);
            if (FixedOrCommon(t3, t4))
                continue;
            G2 = G1 + (this->*C)(t3, t4);
            if (X4 == 1 &&
                !Forbidden(t4, t1) &&
                (!c || G2 - (this->*c)(t4, t1) > 0) && (*Gain = G2 - (this->*C)(t4, t1)) > 0)
            {
                Swap1(t1, t2, t3);
                return 0;
            }
            if (Backtracking && !Excludable(t3, t4))
                continue;
            Breadth4 = 0;
            /* Choose (t4,t5) as a candidate edge emanating from t4 */
            for (Nt4 = t4->CandidateSet; (t5 = Nt4->To); Nt4++) {
                if (t5 == t4->Pred || t5 == t4->Suc ||
                    ((G3 = G2 - Nt4->Cost) <= 0 && GainCriterionUsed &&
                     ProblemType != HCP && ProblemType != HPP))
                    continue;
                if (++Breadth4 > MaxBreadth)
                    break;
                /* Choose t6 as one of t5's two neighbors on the tour */
                for (X6 = 1; X6 <= 2; X6++) {
                    if (X4 == 1) {
                        if (X6 == 1) {
                            Case6 = 1 + !BETWEEN(t2, t5, t4);
                            t6 = Case6 == 1 ? SUC(t5) : PRED(t5);
                        } else {
                            t6 = t6 == t5->Pred ? t5->Suc : t5->Pred;
                            if ((t5 == t1 && t6 == t2) ||
                                (t5 == t2 && t6 == t1))
                                continue;
                            Case6 += 2;
                        }
                    } else if (BETWEEN(t2, t5, t3)) {
                        Case6 = 4 + X6;
                        t6 = X6 == 1 ? SUC(t5) : PRED(t5);
                        if (t6 == t1)
                            continue;
                    } else {
                        if (X6 == 2)
                            break;
                        Case6 = 7;
                        t6 = PRED(t5);
                        if (t6 == t2)
                            continue;
                    }
                    if (FixedOrCommon(t5, t6))
                        continue;
                    G4 = G3 + (this->*C)(t5, t6);
                    if ((Case6 <= 2 || Case6 == 5 || Case6 == 6) &&
                        !Forbidden(t6, t1) &&
                        (!c || G4 - (this->*c)(t6, t1) > 0) &&
                        (*Gain = G4 - (this->*C)(t6, t1)) > 0) {
                        Make3OptMove(t1, t2, t3, t4, t5, t6, Case6);
                        return 0;
                    }
                    if (Backtracking && !Excludable(t5, t6))
                        continue;
                    Breadth6 = 0;
                    /* Choose (t6,t7) as a candidate edge emanating from t6 */
                    for (Nt6 = t6->CandidateSet; (t7 = Nt6->To); Nt6++) {
                        if (t7 == t6->Pred || t7 == t6->Suc ||
                            (t6 == t2 && t7 == t3) ||
                            (t6 == t3 && t7 == t2) ||
                            ((G5 = G4 - Nt6->Cost) <= 0 &&
                             GainCriterionUsed &&
                             ProblemType != HCP && ProblemType != HPP))
                            continue;
                        if (++Breadth6 > MaxBreadth)
                            break;
                        /* Choose t8 as one of t7's two neighbors on the tour */
                        for (X8 = 1; X8 <= 2; X8++) {
                            if (X8 == 1) {
                                Case8 = Case6;
                                t8 = 0;
                                switch (Case6) {
                                case 1:
                                    t8 = BETWEEN(t2, t7,
                                                 t5) ? SUC(t7) : PRED(t7);
                                    break;
                                case 2:
                                    t8 = BETWEEN(t3, t7,
                                                 t6) ? SUC(t7) : PRED(t7);
                                    break;
                                case 3:
                                    if (BETWEEN(t5, t7, t4))
                                        t8 = SUC(t7);
                                    break;
                                case 4:
                                    if (BETWEEN(t2, t7, t5))
                                        t8 = BETWEEN(t2, t7,
                                                     t4) ? SUC(t7) :
                                            PRED(t7);
                                    break;
                                case 5:
                                    t8 = PRED(t7);
                                    break;
                                case 6:
                                    t8 = BETWEEN(t2, t7,
                                                 t3) ? SUC(t7) : PRED(t7);
                                    break;
                                case 7:
                                    if (BETWEEN(t2, t7, t3))
                                        t8 = SUC(t7);
                                    break;
                                }
                                if (t8 == 0)
                                    break;
                            } else {
                                if (Case6 != 3 && Case6 != 4 && Case6 != 7)
                                    break;
                                t8 = t8 == t7->Pred ? t7->Suc : t7->Pred;
                                Case8 += 8;
                            }
                            if (t8 == t1 ||
                                (t7 == t3 && t8 == t4) ||
                                (t7 == t4 && t8 == t3))
                                continue;
                            if (FixedOrCommon(t7, t8))
                                continue;
                            G6 = G5 + (this->*C)(t7, t8);
                            if (t8 != t1 &&
                                !Forbidden(t8, t1) &&
                                (!c || G6 - (this->*c)(t8, t1) > 0) &&
                                (*Gain = G6 - (this->*C)(t8, t1)) > 0) {
                                Make4OptMove(t1, t2, t3, t4, t5, t6, t7,
                                             t8, Case8);
                                return 0;
                            }
                            if (GainCriterionUsed &&
                                G6 - Precision < t8->Cost)
                                continue;
                            if (!Backtracking || Swaps > 0) {
                                if ((G6 > BestG6 ||
                                     (G6 == BestG6 && !Near(t7, t8) &&
                                      Near(T7, T8))) &&
                                    Swaps < MaxSwaps &&
                                    Excludable(t7, t8) &&
                                    !InInputTour(t7, t8)) {
                                    /* Ignore the move if the gain does 
                                       not vary */
                                    if (RestrictedSearch &&
                                        ProblemType != HCP &&
                                        ProblemType != HPP &&
                                        G2 - t4->Pi == G4 - t6->Pi &&
                                        G4 - t6->Pi == G6 - t8->Pi &&
                                        G3 + t5->Pi == G1 + t3->Pi &&
                                        G5 + t7->Pi == G3 + t5->Pi)
                                        continue;
                                    T3 = t3;
                                    T4 = t4;
                                    T5 = t5;
                                    T6 = t6;
                                    T7 = t7;
                                    T8 = t8;
                                    BestCase8 = Case8;
                                    BestG6 = G6;
                                }
                            } else if (MaxSwaps > 0) {
                                GainType G = G6;
                                Node *t = t8;
                                Make4OptMove(t1, t2, t3, t4, t5, t6, t7,
                                             t8, Case8);
                                Exclude(t1, t2);
                                Exclude(t3, t4);
                                Exclude(t5, t6);
                                Exclude(t7, t8);
                                while ((t =
                                        (this->*BestSubsequentMove)(t1, t, &G,
                                                           Gain)));
                                if (*Gain > 0)
                                    return 0;
                                RestoreTour();
                                if (t2 != SUC(t1))
                                    Reversed ^= 1;
                            }
                        }
                    }
                }
            }
        }
    }
    *Gain = 0;
    if (T8) {
        /* Make the best 4-opt move */
        Make4OptMove(t1, t2, T3, T4, T5, T6, T7, T8, BestCase8);
        Exclude(t1, t2), Exclude(T3, T4);
        Exclude(T5, T6);
        Exclude(T7, T8);
        *G0 = BestG6;
    }
    return T8;
}
int
SolveSubproblem(int CurrentSubproblem, int Subproblems,
                GainType * GlobalBestCost)
{
    Node *FirstNodeSaved = FirstNode, *N, *Next, *Last = 0;
    GainType OptimumSaved = Optimum, Cost, Improvement, GlobalCost;
    double LastTime, Time, ExcessSaved = Excess;
    int NewDimension = 0, OldDimension = 0, Number, i, InitialTourEdges = 0,
        AscentCandidatesSaved = AscentCandidates,
        InitialPeriodSaved = InitialPeriod, MaxTrialsSaved = MaxTrials;

    BestCost = PLUS_INFINITY;
    FirstNode = 0;
    N = FirstNodeSaved;
    do {
        if (N->Subproblem == CurrentSubproblem) {
            if (SubproblemsCompressed &&
                (((N->SubproblemPred == N->SubBestPred ||
                   FixedOrCommon(N, N->SubproblemPred) ||
                   (N->SubBestPred &&
                    (N->FixedTo1Saved == N->SubBestPred ||
                     N->FixedTo2Saved == N->SubBestPred))) &&
                  (N->SubproblemSuc == N->SubBestSuc ||
                   FixedOrCommon(N, N->SubproblemSuc) ||
                   (N->SubBestSuc &&
                    (N->FixedTo1Saved == N->SubBestSuc ||
                     N->FixedTo2Saved == N->SubBestSuc)))) ||
                 ((N->SubproblemPred == N->SubBestSuc ||
                   FixedOrCommon(N, N->SubproblemPred) ||
                   (N->SubBestSuc &&
                    (N->FixedTo1Saved == N->SubBestSuc ||
                     N->FixedTo2Saved == N->SubBestSuc))) &&
                  (N->SubproblemSuc == N->SubBestPred ||
                   FixedOrCommon(N, N->SubproblemSuc) ||
                   (N->SubBestPred &&
                    (N->FixedTo1Saved == N->SubBestPred ||
                     N->FixedTo2Saved == N->SubBestPred))))))
                N->Subproblem = -CurrentSubproblem;
            else {
                if (!FirstNode)
                    FirstNode = N;
                NewDimension++;
            }
            N->Head = N->Tail = 0;
            if (N->SubBestSuc)
                OldDimension++;
        }
        N->SubBestPred = N->SubBestSuc = 0;
        N->FixedTo1Saved = N->FixedTo1;
        N->FixedTo2Saved = N->FixedTo2;
    } while ((N = N->SubproblemSuc) != FirstNodeSaved);
    if ((Number = CurrentSubproblem % Subproblems) == 0)
        Number = Subproblems;
    if (NewDimension <= 3 || NewDimension == OldDimension) {
        if (TraceLevel >= 1 && NewDimension <= 3)
            printff
                ("\nSubproblem %d of %d: Dimension = %d (too small)\n",
                 Number, Subproblems, NewDimension);
        FirstNode = FirstNodeSaved;
        return 0;
    }
    if (AscentCandidates > NewDimension - 1)
        AscentCandidates = NewDimension - 1;
    if (InitialPeriod < 0) {
        InitialPeriod = NewDimension / 2;
        if (InitialPeriod < 100)
            InitialPeriod = 100;
    }
    if (Excess < 0)
        Excess = 1.0 / NewDimension;
    if (MaxTrials == -1)
        MaxTrials = NewDimension;
    N = FirstNode;
    do {
        Next = N->SubproblemSuc;
        if (N->Subproblem == CurrentSubproblem) {
            N->Pred = N->Suc = N;
            if (N != FirstNode)
                Follow(N, Last);
            Last = N;
        } else if (Next->Subproblem == CurrentSubproblem
                   && !Fixed(Last, Next)) {
            if (!Last->FixedTo1
                || Last->FixedTo1->Subproblem != CurrentSubproblem)
                Last->FixedTo1 = Next;
            else
                Last->FixedTo2 = Next;
            if (!Next->FixedTo1
                || Next->FixedTo1->Subproblem != CurrentSubproblem)
                Next->FixedTo1 = Last;
            else
                Next->FixedTo2 = Last;
            if (C == C_EXPLICIT) {
                if (Last->Id > Next->Id)
                    Last->C[Next->Id] = 0;
                else
                    Next->C[Last->Id] = 0;
            }
        }
    }
    while ((N = Next) != FirstNode);

    Dimension = NewDimension;
    AllocateSegments();
    InitializeStatistics();
    if (CacheSig)
        for (i = 0; i <= CacheMask; i++)
            CacheSig[i] = 0;
    OptimumSaved = Optimum;
    Optimum = 0;
    N = FirstNode;
    do {
        if (N->SubproblemSuc == N->InitialSuc ||
            N->SubproblemPred == N->InitialSuc)
            InitialTourEdges++;
        if (!Fixed(N, N->Suc))
            Optimum += Distance(N, N->Suc);
        if (N->FixedTo1 && N->Subproblem != N->FixedTo1->Subproblem)
            eprintf("Illegal fixed edge (%d,%d)", N->Id, N->FixedTo1->Id);
        if (N->FixedTo2 && N->Subproblem != N->FixedTo2->Subproblem)
            eprintf("Illegal fixed edge (%d,%d)", N->Id, N->FixedTo2->Id);
    }
    while ((N = N->Suc) != FirstNode);
    if (TraceLevel >= 1)
        printff
            ("\nSubproblem %d of %d: Dimension = %d, Upper bound = "
             GainFormat "\n", Number, Subproblems, Dimension, Optimum);
    FreeCandidateSets();
    CreateCandidateSet();

    for (Run = 1; Run <= Runs; Run++) {
        LastTime = GetTime();
        Cost = Norm != 0 ? FindTour() : Optimum;
        /* Merge with subproblem tour */
        Last = 0;
        N = FirstNode;
        do {
            if (N->Subproblem == CurrentSubproblem) {
                if (Last)
                    Last->Next = N;
                Last = N;
            }
        }
        while ((N = N->SubproblemSuc) != FirstNode);
        Last->Next = FirstNode;
        Cost = MergeWithTour();
        if (MaxPopulationSize > 1) {
            /* Genetic algorithm */
            for (i = 0; i < PopulationSize; i++)
                Cost = MergeTourWithIndividual(i);
            if (!HasFitness(Cost)) {
                if (PopulationSize < MaxPopulationSize) {
                    AddToPopulation(Cost);
                    if (TraceLevel >= 1)
                        PrintPopulation();
                } else if (Cost < Fitness[PopulationSize - 1]) {
                    ReplaceIndividualWithTour(PopulationSize - 1, Cost);
                    if (TraceLevel >= 1)
                        PrintPopulation();
                }
            }
        }
        if (Cost < BestCost) {
            N = FirstNode;
            do {
                N->SubBestPred = N->Pred;
                N->SubBestSuc = N->Suc;
            } while ((N = N->Suc) != FirstNode);
            BestCost = Cost;
        }
        if (Cost < Optimum || (Cost != Optimum && OutputTourFileName)) {
            Improvement = Optimum - Cost;
            if (Improvement > 0) {
                BestCost = GlobalCost = *GlobalBestCost -= Improvement;
                Optimum = Cost;
            } else
                GlobalCost = *GlobalBestCost - Improvement;
            N = FirstNode;
            do
                N->Mark = 0;
            while ((N = N->SubproblemSuc) != FirstNode);
            do {
                N->Mark = N;
                if (!N->SubproblemSuc->Mark &&
                    (N->Subproblem != CurrentSubproblem ||
                     N->SubproblemSuc->Subproblem != CurrentSubproblem))
                    N->BestSuc = N->SubproblemSuc;
                else if (!N->SubproblemPred->Mark &&
                         (N->Subproblem != CurrentSubproblem ||
                          N->SubproblemPred->Subproblem !=
                          CurrentSubproblem))
                    N->BestSuc = N->SubproblemPred;
                else if (!N->Suc->Mark)
                    N->BestSuc = N->Suc;
                else if (!N->Pred->Mark)
                    N->BestSuc = N->Pred;
                else
                    N->BestSuc = FirstNode;
            }
            while ((N = N->BestSuc) != FirstNode);
            Dimension = DimensionSaved;
            i = 0;
            do {
                if (ProblemType != ATSP)
                    BetterTour[++i] = N->Id;
                else if (N->Id <= Dimension / 2) {
                    i++;
                    if (N->BestSuc->Id != N->Id + Dimension / 2)
                        BetterTour[i] = N->Id;
                    else
                        BetterTour[Dimension / 2 - i + 1] = N->Id;
                }
            }
            while ((N = N->BestSuc) != FirstNode);
            BetterTour[0] =
                BetterTour[ProblemType !=
                           ATSP ? Dimension : Dimension / 2];
            WriteTour(OutputTourFileName, BetterTour, GlobalCost);
            if (Improvement > 0) {
                do
                    if (N->Subproblem != CurrentSubproblem)
                        break;
                while ((N = N->SubproblemPred) != FirstNode);
                if (N->SubproblemSuc == N->BestSuc) {
                    N = FirstNode;
                    do {
                        N->BestSuc->SubproblemPred = N;
                        N = N->SubproblemSuc = N->BestSuc;
                    }
                    while (N != FirstNode);
                } else {
                    N = FirstNode;
                    do
                        (N->SubproblemPred = N->BestSuc)->SubproblemSuc =
                            N;
                    while ((N = N->BestSuc) != FirstNode);
                }
                RecordBestTour();
                WriteTour(TourFileName, BestTour, GlobalCost);
            }
            Dimension = NewDimension;
            if (TraceLevel >= 1) {
                printff("*** %d: Cost = " GainFormat, Number, GlobalCost);
                if (OptimumSaved != MINUS_INFINITY && OptimumSaved != 0)
                    printff(", Gap = %04f%%",
                            100.0 * (GlobalCost -
                                     OptimumSaved) / OptimumSaved);
                printff(", Time = %0.2f sec. %s\n",
                        fabs(GetTime() - LastTime),
                        GlobalCost < OptimumSaved ? "<" : GlobalCost ==
                        OptimumSaved ? "=" : "");
            }
        }

        Time = fabs(GetTime() - LastTime);
        UpdateStatistics(Cost, Time);
        if (TraceLevel >= 1 && Cost != PLUS_INFINITY)
            printff("Run %d: Cost = " GainFormat ", Time = %0.2f sec.\n\n",
                    Run, Cost, Time);
        if (PopulationSize >= 2 &&
            (PopulationSize == MaxPopulationSize
             || Run >= 2 * MaxPopulationSize) && Run < Runs) {
            Node *N;
            int Parent1, Parent2;
            Parent1 = LinearSelection(PopulationSize, 1.25);
            do
                Parent2 = LinearSelection(PopulationSize, 1.25);
            while (Parent1 == Parent2);
            ApplyCrossover(Parent1, Parent2);
            N = FirstNode;
            do {
                int d = C(N, N->Suc);
                AddCandidate(N, N->Suc, d, INT_MAX);
                AddCandidate(N->Suc, N, d, INT_MAX);
                N = N->InitialSuc = N->Suc;
            }
            while (N != FirstNode);
        }
        SRandom(++Seed);
        if (Norm == 0)
            break;
    }

    if (TraceLevel >= 1)
        PrintStatistics();

    if (C == C_EXPLICIT) {
        N = FirstNode;
        do {
            for (i = 1; i < N->Id; i++) {
                N->C[i] -= N->Pi + NodeSet[i].Pi;
                N->C[i] /= Precision;
            }
            if (N->FixedTo1 && N->FixedTo1 != N->FixedTo1Saved) {
                if (N->Id > N->FixedTo1->Id)
                    N->C[N->FixedTo1->Id] = Distance(N, N->FixedTo1);
                else
                    N->FixedTo1->C[N->Id] = Distance(N, N->FixedTo1);
            }
            if (N->FixedTo2 && N->FixedTo2 != N->FixedTo2Saved) {
                if (N->Id > N->FixedTo2->Id)
                    N->C[N->FixedTo2->Id] = Distance(N, N->FixedTo2);
                else
                    N->FixedTo2->C[N->Id] = Distance(N, N->FixedTo2);
            }
        }
        while ((N = N->Suc) != FirstNode);
    }

    FreeSegments();
    FreeCandidateSets();
    FreePopulation();
    if (InitialTourEdges == Dimension) {
        do
            N->InitialSuc = N->SubproblemSuc;
        while ((N = N->SubproblemSuc) != FirstNode);
    } else {
        do
            N->InitialSuc = 0;
        while ((N = N->SubproblemSuc) != FirstNode);
    }
    Dimension = ProblemType != ATSP ? DimensionSaved : 2 * DimensionSaved;
    N = FirstNode = FirstNodeSaved;
    do {
        N->Suc = N->BestSuc = N->SubproblemSuc;
        N->Suc->Pred = N;
        Next = N->FixedTo1;
        N->FixedTo1 = N->FixedTo1Saved;
        N->FixedTo1Saved = Next;
        Next = N->FixedTo2;
        N->FixedTo2 = N->FixedTo2Saved;
        N->FixedTo2Saved = Next;
    }
    while ((N = N->Suc) != FirstNode);
    Optimum = OptimumSaved;
    Excess = ExcessSaved;
    AscentCandidates = AscentCandidatesSaved;
    InitialPeriod = InitialPeriodSaved;
    MaxTrials = MaxTrialsSaved;
    return 1;
}
Esempio n. 17
0
void LKH::LKHAlg::MinimumSpanningTree(int Sparse)
{
    Node *Blue;         /* Points to the last node included in the tree */
    Node *NextBlue = 0; /* Points to the provisional next node to be included */
    Node *N;
    Candidate *NBlue;
    int d;

    Blue = N = FirstNode;
    Blue->Dad = 0;              /* The root of the tree has no father */
    if (Sparse && Blue->CandidateSet) {
        /* The graph is sparse */
        /* Insert all nodes in the heap */
        Blue->Loc = 0;          /* A blue node is not in the heap */
        while ((N = N->Suc) != FirstNode) {
            N->Dad = Blue;
            N->Cost = N->Rank = INT_MAX;
            HeapLazyInsert(N,this);
        }
        /* Update all neighbors to the blue node */
        for (NBlue = Blue->CandidateSet; (N = NBlue->To); NBlue++) {
            if (FixedOrCommon(Blue, N)) {
                N->Dad = Blue;
                N->Cost = NBlue->Cost + Blue->Pi + N->Pi;
                N->Rank = INT_MIN;
                HeapSiftUp(N,this);
            } else if (!Blue->FixedTo2 && !N->FixedTo2) {
                N->Dad = Blue;
                N->Cost = N->Rank = NBlue->Cost + Blue->Pi + N->Pi;
                HeapSiftUp(N,this);
            }
        }
        /* Loop as long as there are more nodes to include in the tree */
        while ((NextBlue = HeapDeleteMin(this))) {
            Follow(NextBlue, Blue);
            Blue = NextBlue;
            /* Update all neighbors to the blue node */
            for (NBlue = Blue->CandidateSet; (N = NBlue->To); NBlue++) {
                if (!N->Loc)
                    continue;
                if (FixedOrCommon(Blue, N)) {
                    N->Dad = Blue;
                    N->Cost = NBlue->Cost + Blue->Pi + N->Pi;
                    N->Rank = INT_MIN;
                    HeapSiftUp(N,this);
                } else if (!Blue->FixedTo2 && !N->FixedTo2 &&
                           (d = NBlue->Cost + Blue->Pi + N->Pi) < N->Cost)
                {
                    N->Dad = Blue;
                    N->Cost = N->Rank = d;
                    HeapSiftUp(N,this);
                }
            }
        }
    } else {
        /* The graph is dense */
        while ((N = N->Suc) != FirstNode)
            N->Cost = INT_MAX;
        /* Loop as long as there a more nodes to include in the tree */
        while ((N = Blue->Suc) != FirstNode) {
            int Min = INT_MAX;
            /* Update all non-blue nodes (the successors of Blue in the list) */
            do {
                if (FixedOrCommon(Blue, N)) {
                    N->Dad = Blue;
                    N->Cost = (this->*D)(Blue, N);
                    NextBlue = N;
                    Min = INT_MIN;
                } else {
                    if (!Blue->FixedTo2 && !N->FixedTo2 &&
                        !Forbidden(Blue, N) &&
                        (!c || (this->*c)(Blue, N) < N->Cost) &&
                        (d = (this->*D)(Blue, N)) < N->Cost) {
                        N->Cost = d;
                        N->Dad = Blue;
                    }
                    if (N->Cost < Min) {
                        Min = N->Cost;
                        NextBlue = N;
                    }
                }
            }
            while ((N = N->Suc) != FirstNode);
            Follow(NextBlue, Blue);
            Blue = NextBlue;
        }
    }
}