Exemple #1
0
 /// <summary>
 /// Applies this operator.
 /// </summary>
 public bool Apply(TSPTWProblem problem, TSPTWObjective objective, Tour solution, out float delta)
 {
     foreach (var c in solution.Triples())
     {
         int  betterDirectedId;
         bool switchDepartureId, switchedArrivalId;
         if (DirectedHelper.SwitchToBestTurn(c.Along, c.From, c.To, problem.Times, problem.TurnPenalties, out betterDirectedId,
                                             out switchDepartureId, out switchedArrivalId, out delta))
         { // an improvement was found.
             solution.Replace(c.Along, betterDirectedId);
             if (switchDepartureId)
             {
                 var newFromId = DirectedHelper.SwitchDepartureOffset(c.From);
                 solution.Replace(c.From, newFromId);
             }
             if (switchedArrivalId)
             {
                 var newToId = DirectedHelper.SwitchArrivalOffset(c.To);
                 solution.Replace(c.To, newToId);
             }
             return(true);
         }
     }
     delta = 0;
     return(false);
 }
Exemple #2
0
        /// <summary>
        /// Optimizes the given part of the tour by choosing the best improvements in either the departureOffset or arrivalOffset of the first/last customers or the turns at any of the intermediate ones.
        /// </summary>
        private float OptimizePart(TSPTWProblem problem, List <int> part)
        {
            int turn1, arrivalId1, departureId1, id1;
            int turn2, arrivalId2, departureId2, id2;
            int turn3, arrivalId3, departureId3, id3;

            var delta             = 0f; // the positive difference.
            var arrivalIdChange   = -1;
            var departureIdChange = -1;
            var customerIdx       = -1;
            var customerTurn      = -1;

            // try changing the departureId.
            DirectedHelper.ExtractAll(part[0], out arrivalId1, out departureId1, out id1, out turn1);
            DirectedHelper.ExtractAll(part[1], out arrivalId2, out departureId2, out id2, out turn2);
            var weight = problem.TurnPenalties[turn1];

            weight += problem.Times[departureId1][arrivalId2];
            var new0 = DirectedHelper.SwitchDepartureOffset(part[0]);

            DirectedHelper.ExtractAll(new0, out arrivalId3, out departureId3, out id3, out turn3);
            var newWeight = problem.TurnPenalties[turn3];

            newWeight += problem.Times[departureId3][arrivalId2];
            if (newWeight < weight)
            { // there was an improvement found in changing the departure id.
                departureIdChange = DirectedHelper.ExtractDepartureId(new0);
                delta             = newWeight - weight;
            }

            // try changing the arrivalId.
            DirectedHelper.ExtractAll(part[part.Count - 2], out arrivalId1, out departureId1, out id1, out turn1);
            DirectedHelper.ExtractAll(part[part.Count - 1], out arrivalId2, out departureId2, out id2, out turn2);
            weight  = problem.TurnPenalties[turn2];
            weight += problem.Times[departureId1][arrivalId2];
            var newLast = DirectedHelper.SwitchArrivalOffset(part[part.Count - 1]);

            DirectedHelper.ExtractAll(newLast, out arrivalId3, out departureId3, out id3, out turn3);
            newWeight  = problem.TurnPenalties[turn3];
            newWeight += problem.Times[departureId1][arrivalId3];
            if (newWeight < weight &&
                delta < (newWeight - weight))
            { // there was an improvement found in changing the arrival id.
                arrivalIdChange   = DirectedHelper.ExtractDepartureId(newLast);
                departureIdChange = -1;
                delta             = newWeight - weight;
            }

            for (var c = 1; c < part.Count - 1; c++)
            {
                var perviousDepartureId = DirectedHelper.ExtractDepartureId(part[c - 1]);
                DirectedHelper.ExtractAll(part[c], out arrivalId1, out departureId1, out id1, out turn1);
                var nextArrivalid = DirectedHelper.ExtractArrivalId(part[c + 1]);
                weight  = problem.Times[perviousDepartureId][arrivalId1];
                weight += problem.TurnPenalties[turn1];
                weight += problem.Times[departureId1][nextArrivalid];

                for (var t = 0; t < 3; t++)
                {
                    if (t == turn1)
                    {
                        continue;
                    }

                    var newDirectedId = DirectedHelper.BuildDirectedId(id1, t);
                    DirectedHelper.ExtractAll(newDirectedId, out arrivalId2, out departureId2, out id2, out turn2);
                    newWeight  = problem.Times[perviousDepartureId][arrivalId2];
                    newWeight += problem.TurnPenalties[turn2];
                    newWeight += problem.Times[departureId2][nextArrivalid];

                    if (newWeight < weight &&
                        delta < (newWeight - weight))
                    { // there was an improvement found in changing the turn.
                        arrivalIdChange   = -1;
                        departureIdChange = -1;
                        customerIdx       = c;
                        customerTurn      = t;
                        delta             = newWeight - weight;
                    }
                }
            }

            if (delta > 0)
            {
                if (departureIdChange != -1)
                {
                    part[0] = DirectedHelper.SwitchDepartureOffset(part[0]);
                }
                else if (arrivalIdChange != -1)
                {
                    part[part.Count - 1] = DirectedHelper.SwitchArrivalOffset(part[part.Count - 1]);
                }
                else if (customerIdx != -1)
                {
                    part[customerIdx] = DirectedHelper.BuildDirectedId(
                        DirectedHelper.ExtractId(part[customerIdx]), customerTurn);
                }
            }
            return(delta);
        }