void SolveKCenterSubproblems()
{
    Node *N;
    GainType GlobalBestCost, OldGlobalBestCost;
    double EntryTime = GetTime();
    int CurrentSubproblem, Subproblems;

    AllocateStructures();
    ReadPenalties();

    /* Compute upper bound for the original problem */
    GlobalBestCost = 0;
    N = FirstNode;
    do {
        if (!Fixed(N, N->SubproblemSuc))
            GlobalBestCost += Distance(N, N->SubproblemSuc);
        N->Subproblem = 0;
    }
    while ((N = N->SubproblemSuc) != FirstNode);
    if (TraceLevel >= 1) {
        if (TraceLevel >= 2)
            printff("\n");
        printff("*** K-center partitioning *** [Cost = " GainFormat "]\n",
                GlobalBestCost);
    }

    Subproblems = (int) ceil((double) Dimension / SubproblemSize);
    KCenterClustering(Subproblems);
    for (CurrentSubproblem = 1;
         CurrentSubproblem <= Subproblems; CurrentSubproblem++) {
        OldGlobalBestCost = GlobalBestCost;
        SolveSubproblem(CurrentSubproblem, Subproblems, &GlobalBestCost);
        if (SubproblemsCompressed && GlobalBestCost == OldGlobalBestCost)
            SolveCompressedSubproblem(CurrentSubproblem, Subproblems,
                                      &GlobalBestCost);
    }
    printff("\nCost = " GainFormat, GlobalBestCost);
    if (Optimum != MINUS_INFINITY && Optimum != 0)
        printff(", Gap = %0.4f%%",
                100.0 * (GlobalBestCost - Optimum) / Optimum);
    printff(", Time = %0.2f sec. %s\n", fabs(GetTime() - EntryTime),
            GlobalBestCost < Optimum ? "<" : GlobalBestCost ==
            Optimum ? "=" : "");
    if (SubproblemBorders && Subproblems > 1)
        SolveSubproblemBorderProblems(Subproblems, &GlobalBestCost);
}
Example #2
0
void LKH::LKHAlg::CreateCandidateSet()
{
    GainType Cost, MaxAlpha, A;
    Node *Na;
    int CandidatesRead = 0, i;
    double EntryTime = GetTime();

    Norm = 9999;
    if (C == &LKH::LKHAlg::C_EXPLICIT) {
        Na = FirstNode;
        do {
            for (i = 1; i < Na->Id; i++)
                Na->C[i] *= Precision;
        }
        while ((Na = Na->Suc) != FirstNode);
    }
    if (Distance == &LKH::LKHAlg::Distance_1 ||
            (MaxTrials == 0 &&
             (FirstNode->InitialSuc || InitialTourAlgorithm == SIERPINSKI ||
              InitialTourAlgorithm == MOORE))) {
        ReadCandidates(MaxCandidates);
        AddTourCandidates();
        if (ProblemType == HCP || ProblemType == HPP)
            Ascent();
        goto End_CreateCandidateSet;
    }
    if (TraceLevel >= 2)
        printff("Creating candidates ...\n");
    if (MaxCandidates > 0 &&
            (CandidateSetType == QUADRANT || CandidateSetType == NN)) {
        ReadPenalties();
        if (!(CandidatesRead = ReadCandidates(MaxCandidates)) &&
                MaxCandidates > 0) {
            if (CandidateSetType == QUADRANT)
                CreateQuadrantCandidateSet(MaxCandidates);
            else if (CandidateSetType == NN)
                CreateNearestNeighborCandidateSet(MaxCandidates);
        } else {
            AddTourCandidates();
            if (CandidateSetSymmetric)
                SymmetrizeCandidateSet();
        }
        goto End_CreateCandidateSet;
    }
    if (!ReadPenalties()) {
        /* No PiFile specified or available */
        Na = FirstNode;
        do
            Na->Pi = 0;
        while ((Na = Na->Suc) != FirstNode);
        CandidatesRead = ReadCandidates(MaxCandidates);
        Cost = Ascent();
        if (Subgradient && SubproblemSize == 0) {
            WritePenalties();
            PiFile = 0;
        }
    } else if ((CandidatesRead = ReadCandidates(MaxCandidates)) ||
               MaxCandidates == 0) {
        AddTourCandidates();
        if (CandidateSetSymmetric)
            SymmetrizeCandidateSet();
        goto End_CreateCandidateSet;
    } else {
        if (CandidateSetType != DELAUNAY && MaxCandidates > 0) {
            if (TraceLevel >= 2)
                printff("Computing lower bound ... ");
            Cost = Minimum1TreeCost(0);
            if (TraceLevel >= 2)
                printff("done\n");
        } else {
            CreateDelaunayCandidateSet();
            Na = FirstNode;
            do {
                Na->BestPi = Na->Pi;
                Na->Pi = 0;
            }
            while ((Na = Na->Suc) != FirstNode);
            if (TraceLevel >= 2)
                printff("Computing lower bound ... ");
            Cost = Minimum1TreeCost(1);
            if (TraceLevel >= 2)
                printff("done\n");
            Na = FirstNode;
            do {
                Na->Pi = Na->BestPi;
                Cost -= 2 * Na->Pi;
            }
            while ((Na = Na->Suc) != FirstNode);
        }
    }
    LowerBound = (double) Cost / Precision;
    if (TraceLevel >= 1) {
        /*    printff("Lower bound = %0.1f", LowerBound);
            if (Optimum != MINUS_INFINITY && Optimum != 0)
                printff(", Gap = %0.2f%%",
                        100.0 * (Optimum - LowerBound) / Optimum);
            if (!PiFile)
                printff(", Ascent time = %0.2f sec.",
                        fabs(GetTime() - EntryTime));
            printff("\n"); */
        if (Optimum != MINUS_INFINITY && Optimum != 0)
            m_Gap=100.0 * (Optimum - LowerBound) / Optimum;
        if (!PiFile)
            m_AscentTime=fabs(GetTime() - EntryTime);
    }
    MaxAlpha = (GainType) fabs(Excess * Cost);
    if ((A = Optimum * Precision - Cost) > 0 && A < MaxAlpha)
        MaxAlpha = A;
    if (CandidateSetType == DELAUNAY || MaxCandidates == 0)
        OrderCandidateSet(MaxCandidates, MaxAlpha, CandidateSetSymmetric);
    else
        GenerateCandidates(MaxCandidates, MaxAlpha, CandidateSetSymmetric);

End_CreateCandidateSet:
    if (ExtraCandidates > 0) {
        AddExtraCandidates(ExtraCandidates,
                           ExtraCandidateSetType,
                           ExtraCandidateSetSymmetric);
        AddTourCandidates();
    }
    ResetCandidateSet();
    Na = FirstNode;
    do {
        if (!Na->CandidateSet || !Na->CandidateSet[0].To) {
            if (MaxCandidates == 0)
                eprintf("MAX_CANDIDATES = 0: Node %d has no candidates",
                        Na->Id);
            else
                eprintf("Node %d has no candidates", Na->Id);
        }
    }
    while ((Na = Na->Suc) != FirstNode);
    if (!CandidatesRead && SubproblemSize == 0)
        WriteCandidates();
    if (C == &LKH::LKHAlg::C_EXPLICIT) {
        Na = FirstNode;
        do
            for (i = 1; i < Na->Id; i++)
                Na->C[i] += Na->Pi + NodeSet[i].Pi;
        while ((Na = Na->Suc) != FirstNode);
    }
    if (TraceLevel >= 1) {
        CandidateReport();
        //     printff("Preprocessing time = %0.2f sec.\n",
        //           fabs(GetTime() - EntryTime));
    }
}
void SolveKarpSubproblems()
{
    Node *N;
    int i;
    double EntryTime = GetTime();

    AllocateStructures();
    ReadPenalties();
    /* Compute upper bound for the original problem */
    GlobalBestCost = 0;
    N = FirstNode;
    do {
        if (!Fixed(N, N->SubproblemSuc))
            GlobalBestCost += Distance(N, N->SubproblemSuc);
        N->Subproblem = 0;
    }
    while ((N = N->BestSuc = N->SubproblemSuc) != FirstNode);
    if (TraceLevel >= 1) {
        if (TraceLevel >= 2)
            printff("\n");
        printff("*** Karp partitioning *** [Cost = " GainFormat "]\n",
                GlobalBestCost);
    }
    if (WeightType == GEO || WeightType == GEOM ||
        WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) {
        N = FirstNode;
        do {
            N->Xc = N->X;
            N->Yc = N->Y;
            N->Zc = N->Z;
            if (WeightType == GEO || WeightType == GEO_MEEUS)
                GEO2XYZ(N->Xc, N->Yc, &N->X, &N->Y, &N->Z);
            else
                GEOM2XYZ(N->Xc, N->Yc, &N->X, &N->Y, &N->Z);
        } while ((N = N->SubproblemSuc) != FirstNode);
        CoordType = THREED_COORDS;
    }
    KDTree = BuildKDTree();
    if (WeightType == GEO || WeightType == GEOM ||
        WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) {
        N = FirstNode;
        do {
            N->X = N->Xc;
            N->Y = N->Yc;
            N->Z = N->Zc;
        } while ((N = N->SubproblemSuc) != FirstNode);
        CoordType = TWOD_COORDS;
    }

    CurrentSubproblem = 0;
    Subproblems = 1;
    for (i = Dimension - 1; i > SubproblemSize; i /= 2)
        Subproblems *= 2;
    RestrictedSearchSaved = RestrictedSearch;
    KarpPartition(0, Dimension - 1, 0);
    free(KDTree);
    printff("\nCost = " GainFormat, GlobalBestCost);
    if (Optimum != MINUS_INFINITY && Optimum != 0)
        printff(", Gap = %0.3f%%",
                100.0 * (GlobalBestCost - Optimum) / Optimum);
    printff(", Time = %0.1f sec. %s\n", fabs(GetTime() - EntryTime),
            GlobalBestCost < Optimum ? "<" : GlobalBestCost ==
            Optimum ? "=" : "");
    if (SubproblemBorders && Subproblems > 1)
        SolveSubproblemBorderProblems(Subproblems);
}
void SolveRoheSubproblems()
{
    Node *N;
    int CurrentSubproblem, Subproblems, Remaining, i;
    GainType GlobalBestCost, OldGlobalBestCost;
    double XMin, XMax, YMin, YMax, ZMin, ZMax, DX, DY, DZ, CLow, CMid,
        CHigh;
    double EntryTime = GetTime();

    AllocateStructures();
    ReadPenalties();
    Subproblems = 0;

    /* Compute upper bound for the original problem */
    GlobalBestCost = 0;
    N = FirstNode;
    do {
        if (!Fixed(N, N->SubproblemSuc))
            GlobalBestCost += Distance(N, N->SubproblemSuc);
        N->Subproblem = 0;
    }
    while ((N = N->SubproblemSuc) != FirstNode);
    if (TraceLevel >= 1) {
        if (TraceLevel >= 2)
            printff("\n");
        printff("*** Rohe partitioning *** [Cost = " GainFormat "]\n",
                GlobalBestCost);
    }
    if (WeightType == GEO || WeightType == GEOM ||
        WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) {
        N = FirstNode;
        do {
            N->Xc = N->X;
            N->Yc = N->Y;
            N->Zc = N->Z;
            if (WeightType == GEO || WeightType == GEO_MEEUS)
                GEO2XYZ(N->Xc, N->Yc, &N->X, &N->Y, &N->Z);
            else
                GEOM2XYZ(N->Xc, N->Yc, &N->X, &N->Y, &N->Z);
        } while ((N = N->SubproblemSuc) != FirstNode);
        CoordType = THREED_COORDS;
    }
    N = FirstNode;
    XMin = XMax = N->X;
    YMin = YMax = N->Y;
    ZMin = ZMax = N->Z;
    while ((N = N->SubproblemSuc) != 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 (N->Z < ZMin)
            ZMin = N->Z;
        else if (N->Z > ZMax)
            ZMax = N->Z;
    }
    KDTree = BuildKDTree(SubproblemSize);
    Remaining = Dimension;
    while (Remaining > SubproblemSize) {
        N = FirstNode;
        i = Random() % Remaining;
        while (i--)
            N = N->Suc;
        DX = (0.5 + 0.5 * Random() / (PRANDMAX - 1)) * (XMax - XMin);
        DY = (0.5 + 0.5 * Random() / (PRANDMAX - 1)) * (YMax - YMin);
        DZ = (0.5 + 0.5 * Random() / (PRANDMAX - 1)) * (ZMax - ZMin);
        CLow = 0;
        CHigh = 2;
        /* Binary search */
        do {
            CMid = (CLow + CHigh) / 2;
            Size = 0;
            WindowSize(N->X - CMid * DX, N->X + CMid * DX,
                       N->Y - CMid * DY, N->Y + CMid * DY,
                       N->Z - CMid * DZ, N->Z + CMid * DZ,
                       0, Dimension - 1);
            if (Size >= 2.0 / 3 * SubproblemSize && Size <= SubproblemSize)
                break;
            if (Size < 2.0 / 3 * SubproblemSize)
                CLow = CMid;
            else
                CHigh = CMid;
        }
        while (CHigh - CLow > DBL_EPSILON);
        MakeSubproblem(N->X - CMid * DX, N->X + CMid * DX,
                       N->Y - CMid * DY, N->Y + CMid * DY,
                       N->Z - CMid * DZ, N->Z + CMid * DZ,
                       ++Subproblems, 0, Dimension - 1);
        Remaining -= Size;
    }
    if (Remaining > 3) {
        Subproblems++;
        N = FirstNode;
        do
            N->Subproblem = Subproblems;
        while ((N = N->Suc) != FirstNode);
    }
    if (WeightType == GEO || WeightType == GEOM || WeightType == GEO_MEEUS
        || WeightType == GEOM_MEEUS) {
        N = FirstNode;
        do {
            N->X = N->Xc;
            N->Y = N->Yc;
            N->Z = N->Zc;
        } while ((N = N->SubproblemSuc) != FirstNode);
        CoordType = TWOD_COORDS;
    }
    free(KDTree);
    for (CurrentSubproblem = 1;
         CurrentSubproblem <= Subproblems; CurrentSubproblem++) {
        OldGlobalBestCost = GlobalBestCost;
        SolveSubproblem(CurrentSubproblem, Subproblems, &GlobalBestCost);
        if (SubproblemsCompressed && GlobalBestCost == OldGlobalBestCost)
            SolveCompressedSubproblem(CurrentSubproblem, Subproblems,
                                      &GlobalBestCost);
    }
    printff("\nCost = " GainFormat, GlobalBestCost);
    if (Optimum != MINUS_INFINITY && Optimum != 0)
        printff(", Gap = %0.4f%%",
                100.0 * (GlobalBestCost - Optimum) / Optimum);
    printff(", Time = %0.1f sec. %s\n", fabs(GetTime() - EntryTime),
            GlobalBestCost < Optimum ? "<" : GlobalBestCost ==
            Optimum ? "=" : "");
    if (SubproblemBorders && Subproblems > 1)
        SolveSubproblemBorderProblems(Subproblems, &GlobalBestCost);
}