コード例 #1
0
ファイル: Best2OptMove.c プロジェクト: feng1o/LK-Heuristic
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;
}
コード例 #2
0
ファイル: Best3OptMove.c プロジェクト: ashleywang1/TSP-solver
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;
}
コード例 #3
0
ファイル: LinKernighan.c プロジェクト: ashleywang1/TSP-solver
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;
}
コード例 #4
0
ファイル: Best4OptMove.c プロジェクト: Jason3424/future_net-1
Node *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))
            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))
                    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 + C(t5, t6);
                    if ((Case6 <= 2 || Case6 == 5 || Case6 == 6) &&
                        !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 (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))
                            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 + C(t7, t8);
                            if (!Forbidden(t8, t1) &&
                                (!c || G6 - c(t8, t1) > 0) &&
                                (*Gain = G6 - 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 &&
                                        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 =
                                        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;
}