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>
        /// Switches the arrival offset.
        /// </summary>
        public static int SwitchArrivalOffset(int directedId)
        {
            int turn;
            var id = DirectedHelper.ExtractId(directedId, out turn);
            int arrivalOffset, oldDepartureOffset;

            DirectedHelper.ExtractOffset(turn, out arrivalOffset, out oldDepartureOffset);
            return(DirectedHelper.BuildDirectedId(id, DirectedHelper.BuildTurn(1 - arrivalOffset, oldDepartureOffset)));
        }
Exemple #4
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);
        }
Exemple #5
0
        /// <summary>
        /// Shifts the directed customer aft er the given directed before with the best possible turns.
        /// </summary>
        public static float ShiftAfterBestTurns(this Tour tour, float[][] weights, float[] penalties, int directedCustomer, int directedBefore)
        {
            var customer      = DirectedHelper.ExtractId(directedCustomer);
            var directedAfter = tour.GetNeigbour(directedCustomer);

            if (directedAfter == Constants.NOT_SET)
            { // TODO: figure out if this happens and if so how to calculate turns.
                return(0);
            }

            // insert directed customer.
            tour.ShiftAfter(directedCustomer, directedBefore);

            // calculate best shift-after.
            int departureOffset1, arrivalOffset3, turn2;
            var cost = CheapestInsertion.CheapestInsertionDirectedHelper.CalculateCheapestInsert(weights, penalties, directedBefore, customer, directedAfter,
                                                                                                 !tour.IsFirst(directedBefore), !tour.IsLast(directedAfter), out departureOffset1, out arrivalOffset3, out turn2);
            var newDirectedBefore   = DirectedHelper.UpdateDepartureOffset(directedBefore, departureOffset1);
            var newDirectedAfter    = DirectedHelper.UpdateArrivalOffset(directedAfter, arrivalOffset3);
            var newDirectedCustomer = DirectedHelper.BuildDirectedId(customer, turn2);

            if (directedBefore != newDirectedBefore)
            {
                tour.Replace(directedBefore, newDirectedBefore);
            }
            if (directedCustomer != newDirectedCustomer)
            {
                tour.Replace(directedCustomer, newDirectedCustomer);
            }
            if (directedAfter != newDirectedAfter)
            {
                tour.Replace(directedAfter, newDirectedAfter);
            }

            return(cost);
        }