Exemple #1
0
        /// <summary>
        /// Switches the given directed id to the best turn given the before and after directed id's.
        /// </summary>
        public static bool SwitchToBestTurn(int directedId, int beforeDirectedId, int afterDirectedId, float[][] weights, float[] turnPenalties,
                                            out int betterDirectedId, out bool departureIdSwitched, out bool arrivalIdSwitched, out float delta)
        {
            int arrivalId, departureId, turn, id, beforeDepartureOffset, afterArrivalOffset, temp;

            DirectedHelper.ExtractOffset(DirectedHelper.ExtractTurn(beforeDirectedId), out temp, out beforeDepartureOffset);
            DirectedHelper.ExtractOffset(DirectedHelper.ExtractTurn(afterDirectedId), out afterArrivalOffset, out temp);
            DirectedHelper.ExtractAll(directedId, out arrivalId, out departureId, out id, out turn);

            var bestWeight     = float.MaxValue;
            var bestDirectedId = -1;
            var previousWeight = float.MaxValue;

            departureIdSwitched = false;
            arrivalIdSwitched   = false;
            for (var newBeforeDepartureOffset = 0; newBeforeDepartureOffset < 2; newBeforeDepartureOffset++)
            {
                for (var newAfterArrivalOffset = 0; newAfterArrivalOffset < 2; newAfterArrivalOffset++)
                {
                    for (var i = 0; i < 4; i++)
                    {
                        var newDirectedId = DirectedHelper.BuildDirectedId(id, i);
                        int localTurn;
                        DirectedHelper.ExtractAll(newDirectedId, out arrivalId, out departureId, out id, out localTurn);
                        var newBeforeDirectedId  = DirectedHelper.UpdateDepartureOffset(beforeDirectedId, newBeforeDepartureOffset);
                        var newAfterDirectedId   = DirectedHelper.UpdateArrivalOffset(afterDirectedId, newAfterArrivalOffset);
                        var newBeforeDepartureId = DirectedHelper.ExtractDepartureId(newBeforeDirectedId);
                        var newAfterArrivalId    = DirectedHelper.ExtractArrivalId(newAfterDirectedId);
                        var newBeforeTurn        = DirectedHelper.ExtractTurn(newBeforeDirectedId);
                        var newAfterTurn         = DirectedHelper.ExtractTurn(newAfterDirectedId);

                        var newWeight = turnPenalties[localTurn];
                        newWeight += weights[newBeforeDepartureId][arrivalId];
                        newWeight += weights[departureId][newAfterArrivalId];
                        newWeight += turnPenalties[newBeforeTurn];
                        newWeight += turnPenalties[newAfterTurn];

                        if (i == turn && newBeforeDepartureOffset == beforeDepartureOffset &&
                            newAfterArrivalOffset == afterArrivalOffset)
                        {
                            previousWeight = newWeight;
                        }

                        if (bestWeight > newWeight)
                        {
                            bestWeight          = newWeight;
                            bestDirectedId      = newDirectedId;
                            departureIdSwitched = newBeforeDepartureOffset != beforeDepartureOffset;
                            arrivalIdSwitched   = newAfterArrivalOffset != afterArrivalOffset;
                        }
                    }
                }
            }
            delta            = previousWeight - bestWeight;
            betterDirectedId = bestDirectedId;
            return(betterDirectedId != directedId);
        }
Exemple #2
0
        /// <summary>
        /// Calculates the weights between the two directed id's without the turn weights.
        /// </summary>
        public static float WeightWithoutTurns(this float[][] weights, int directed1, int directed2)
        {
            int arrivalId1, departureId1, id1, turn1, arrivalId2, departureId2, id2, turn2;

            DirectedHelper.ExtractAll(directed1, out arrivalId1, out departureId1, out id1, out turn1);
            DirectedHelper.ExtractAll(directed2, out arrivalId2, out departureId2, out id2, out turn2);

            return(weights[departureId1][arrivalId2]);
        }
Exemple #3
0
        /// <summary>
        /// Calculates the weight of the given tour.
        /// </summary>
        public static float Weight(this Tour tour, float[][] weights, float[] turnPenalties)
        {
            var weight       = 0f;
            var previousFrom = int.MaxValue;
            var firstTo      = int.MaxValue;
            var lastTurn     = int.MaxValue;

            foreach (var directedId in tour)
            {
                // extract turns and stuff from directed id.
                int arrivalId, departureId, id, turn;
                DirectedHelper.ExtractAll(directedId, out arrivalId, out departureId, out id, out turn);

                // add the weight from the previous customer to the current one.
                if (previousFrom != int.MaxValue)
                {
                    weight = weight + weights[previousFrom][arrivalId];
                }
                else
                {
                    firstTo = arrivalId;
                }

                // add turn penalty.
                if ((tour.First != directedId &&
                     tour.Last != directedId) ||
                    tour.Last == tour.First)
                { // never count turn @ first customer.
                    // don't count turn @ last customer if it's different from first.
                    weight += turnPenalties[turn];
                }

                previousFrom = departureId;
                lastTurn     = turn;
            }

            // remove the last turn penalty if it's an open non-fixed tour.
            if (tour.Last == null)
            {
                weight -= turnPenalties[lastTurn];
            }

            // add the weight between last and first.
            if (previousFrom != int.MaxValue &&
                tour.First == tour.Last)
            {
                weight = weight + weights[previousFrom][firstTo];
            }
            return(weight);
        }