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");
    }
}
Пример #2
0
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 CreateNearestNeighborCandidateSet(int K)
{
    Node *From, *To;
    int i;

    if (TraceLevel >= 2)
        printff("Creating nearest neighbor 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;
    assert(CandidateSet =
           (Candidate *) malloc((K + 1) * sizeof(Candidate)));

    From = FirstNode;
    do {
        NearestQuadrantNeighbors(From, 0, K);
        for (i = 0; i < Candidates; i++) {
            To = CandidateSet[i].To;
            AddCandidate(From, To, D(From, To), 1);
        }
    } 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 == GEOM || WeightType == GEOM_MEEUS)) {
        Candidate **SavedCandidateSet;
        assert(SavedCandidateSet =
               (Candidate **) malloc((1 + DimensionSaved) *
                                     sizeof(Candidate *)));
        if (TraceLevel >= 2)
            printff("done\n");
        /* Transform longitude (180 and -180 map to 0) */
        From = FirstNode;
        do {
            SavedCandidateSet[From->Id] = From->CandidateSet;
            From->CandidateSet = 0;
            From->Yc = From->Y;
            From->Y += From->Y > 0 ? -180 : 180;
        } while ((From = From->Suc) != FirstNode);
        Level++;
        CreateNearestNeighborCandidateSet(K);
        Level--;
        From = FirstNode;
        do
            From->Y = From->Yc;
        while ((From = From->Suc) != FirstNode);
        do {
            Candidate *QCandidateSet = From->CandidateSet;
            Candidate *NFrom;
            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");
    }
}
Пример #4
0
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);
}