Beispiel #1
0
        /// <summary>
        /// Applies this operator.
        /// </summary>
        public bool Apply(TSProblem problem, TSPObjective objective, Tour solution, out float delta)
        {
            if (problem.Weights.Length <= 2)
            {
                delta = 0;
                return(false);
            }

            var before        = objective.Calculate(problem, solution);
            var weights       = problem.Weights;
            var turnPenalties = problem.TurnPenalties;

            delta = 0;

            // test switching directions in random order.
            if (_pool == null || solution.Count != _pool.Size)
            { // create a new pool.
                _pool = new RandomPool(solution.Count);
            }
            else
            { // just reset the existing one.
                _pool.Reset();
            }

            var i        = _n;
            var toInsert = new List <int>();

            while (_pool.MoveNext() && i > 0)
            {
                i--;
                var currentId = _pool.Current;
                var current   = solution.GetDirectedId(currentId);
                if (current != Constants.NOT_SET)
                {
                    if (current != solution.First &&
                        current != solution.Last &&
                        solution.Remove(current))
                    {
                        toInsert.Add(current);
                    }
                }
            }

            foreach (var current in toInsert)
            {
                CheapestInsertionDirectedHelper.InsertCheapestDirected(solution, weights, turnPenalties,
                                                                       DirectedHelper.ExtractId(current));
            }

            var after = objective.Calculate(problem, solution);

            delta = after - before;
            return(delta < 0);
        }
Beispiel #2
0
        /// <summary>
        /// Solves the given problem.
        /// </summary>
        /// <returns></returns>
        public sealed override Tour Solve(STSProblem problem, STSPObjective objective, out STSPFitness fitness)
        {
            // generate empty route based on problem definition.
            var route = problem.CreateEmptyTour();

            fitness = new STSPFitness()
            {
                Weight    = 0,
                Customers = 1
            };

            // generate random pool to select customers from.
            if (_randomPool == null || _randomPool.Size < problem.Weights.Length)
            {
                _randomPool = new RandomPool(problem.Weights.Length / 2);
            }
            else
            {
                _randomPool.Reset();
            }

            // keep adding customers until no more space is left or no more customers available.
            while (_randomPool.MoveNext())
            {
                var customer = _randomPool.Current;
                if (customer == DirectedHelper.ExtractId(route.First) ||
                    (route.Last.HasValue && customer == DirectedHelper.ExtractId(route.Last.Value)))
                { // customer is first or last.
                    continue;
                }

                var cost = CheapestInsertionDirectedHelper.InsertCheapestDirected(route, problem.Weights, problem.TurnPenalties,
                                                                                  customer, problem.Max - fitness.Weight);
                if (cost > 0)
                {
                    fitness.Customers++;
                    fitness.Weight += cost;
                }
            }

            // calculate fitness.
            fitness = objective.Calculate(problem, route);
            return(route);
        }
Beispiel #3
0
        /// <summary>
        /// Solves the given problem.
        /// </summary>
        /// <returns></returns>
        public sealed override Tour Solve(STSProblem problem, STSPObjective objective, out STSPFitness fitness)
        {
            // generate random pool to select customers from.
            if (_randomPool == null || _randomPool.Size < problem.Weights.Length)
            {
                _randomPool = new RandomPool(problem.Weights.Length);
            }
            else
            {
                _randomPool.Reset();
            }

            // keep adding customers until no more space is left or no more customers available.
            var tour = problem.CreateEmptyTour();

            fitness = new STSPFitness()
            {
                Weight    = 0,
                Customers = 1
            };
            while (_randomPool.MoveNext())
            {
                var customer = _randomPool.Current;
                if (customer == problem.First ||
                    customer == problem.Last)
                {
                    continue;
                }

                Pair location;
                var  cost = CheapestInsertionHelper.CalculateCheapest(tour, problem.Weights, customer, out location);
                if (cost + fitness.Weight < problem.Max)
                {
                    tour.InsertAfter(location.From, customer);

                    fitness.Weight    = fitness.Weight + cost;
                    fitness.Customers = fitness.Customers + 1;
                }
            }

            // calculate fitness.
            fitness = objective.Calculate(problem, tour);
            return(tour);
        }
        /// <summary>
        /// Applies this operator.
        /// </summary>
        public bool Apply(TSProblem problem, TSPObjective objective, Tour solution, out float delta)
        {
            if (problem.Weights.Length <= 2)
            {
                delta = 0;
                return(false);
            }

            var weights = problem.Weights;

            delta = 0;

            // test switching directions in random order.
            if (_pool == null || solution.Count != _pool.Size)
            { // create a new pool.
                _pool = new RandomPool(solution.Count);
            }
            else
            { // just reset the existing one.
                _pool.Reset();
            }

            while (_pool.MoveNext())
            {
                var previous            = solution.GetDirectedId(_pool.Current);
                var previousDepartureId = DirectedHelper.ExtractDepartureId(previous);
                var current             = solution.GetNeigbour(previous);
                if (current == Constants.NOT_SET)
                { // last of open.
                    continue;
                }
                var next          = solution.GetNeigbour(current);
                var nextArrivalId = Constants.NOT_SET;
                if (next != Constants.NOT_SET)
                {
                    nextArrivalId = DirectedHelper.ExtractArrivalId(next);
                }
                int currentTurn, currentId, currentArrivalId, currentDepartureId;
                DirectedHelper.ExtractAll(current, out currentArrivalId, out currentDepartureId, out currentId, out currentTurn);

                var weightBefore  = weights[previousDepartureId][currentArrivalId];
                var weightAfter   = float.MaxValue;
                var newDirectedId = Constants.NOT_SET;
                if (next == Constants.NOT_SET)
                { // there is no next, only one option here:
                    // 0 or 1: arrival id offset = 0 OR
                    // 2 or 3: arrival id offset = 1
                    if (currentArrivalId % 2 == 0)
                    { // check turn = 2.
                        weightAfter = weights[previousDepartureId][currentArrivalId + 1];
                        if (weightAfter < weightBefore)
                        { // do the switch.
                            newDirectedId = DirectedHelper.BuildDirectedId(currentId, 2);
                        }
                    }
                    else
                    { // check turn = 0
                        weightAfter = weights[previousDepartureId][currentArrivalId - 1];
                        if (weightAfter < weightBefore)
                        { // do the switch.
                            newDirectedId = DirectedHelper.BuildDirectedId(currentId, 0);
                        }
                    }
                }
                else
                { // three options left, excluding the current one of 4.
                    weightBefore += weights[currentDepartureId][nextArrivalId];
                    weightBefore += problem.TurnPenalties[currentTurn];

                    currentArrivalId   = currentArrivalId - (currentArrivalId % 2);
                    currentDepartureId = currentDepartureId - (currentDepartureId % 2);
                    for (var i = 0; i < 4; i++)
                    {
                        if (i == currentTurn)
                        {
                            continue;
                        }

                        int arrivalOffset, departureOffset;
                        DirectedHelper.ExtractOffset(i, out arrivalOffset, out departureOffset);
                        var newWeightAfter = weights[previousDepartureId][currentArrivalId + arrivalOffset]
                                             + weights[currentDepartureId + departureOffset][nextArrivalId]
                                             + problem.TurnPenalties[i];
                        if (newWeightAfter < weightAfter &&
                            newWeightAfter < weightBefore)
                        {
                            newDirectedId = DirectedHelper.BuildDirectedId(currentId, i);
                            weightAfter   = newWeightAfter;
                        }
                    }
                }

                // switch if a new directed if was found.
                if (newDirectedId != Constants.NOT_SET)
                {
                    delta = weightAfter - weightBefore; // negative when improvement.

                    solution.Replace(current, newDirectedId);
                }
            }

            return(delta < 0);
        }