Beispiel #1
0
        /// <summary>
        /// Solves the given problem.
        /// </summary>
        /// <returns></returns>
        public sealed override Tour Solve(TSPTWProblem problem, TObjective objective, out float fitness)
        {
            // generate random solution.
            var customers = new List <int>();

            for (var customer = 0; customer < problem.Times.Length; customer++)
            {
                if (customer != problem.First &&
                    customer != problem.Last)
                {
                    customers.Add(customer);
                }
            }
            customers.Shuffle <int>();
            customers.Insert(0, problem.First);
            if (problem.Last.HasValue && problem.First != problem.Last)
            { // the special case of a fixed last customer.
                customers.Add(problem.Last.Value);
            }
            var route = new Tour(customers, problem.Last);

            // calculate fitness.
            fitness = objective.Calculate(problem, route);
            return(route);
        }
Beispiel #2
0
        /// <summary>
        /// Solves the given problem.
        /// </summary>
        /// <returns></returns>
        public sealed override Tour Solve(TSPTWProblem problem, TObjective objective, out float fitness)
        {
            // generate random order for unplaced customers.
            var customers = new List <int>();

            for (var customer = 0; customer < problem.Times.Length / 2; customer++)
            {
                if (customer != problem.First &&
                    customer != problem.Last)
                {
                    customers.Add(customer);
                }
            }
            customers.Shuffle <int>();

            // generate empty route based on problem definition.
            var route = problem.CreateEmptyTour();

            // add all customers by using cheapest insertion.
            for (var i = 0; i < customers.Count; i++)
            {
                CheapestInsertionDirectedHelper.InsertCheapestDirected(route, problem.Times, problem.TurnPenalties,
                                                                       customers[i], float.MaxValue);
            }

            // calculate fitness.
            fitness = objective.Calculate(problem, route);
            return(route);
        }
Beispiel #3
0
        /// <summary>
        /// Returns true if there was an improvement, false otherwise.
        /// </summary>
        /// <returns></returns>
        public bool Apply(TSPTWProblem problem, TObjective objective, Tour tour, int level, out float difference)
        {
            var original = objective.Calculate(problem, tour);

            if (problem.Times.Length == 1)
            {
                difference = 0;
                return(false);
            }

            difference = 0;
            while (level > 0)
            {
                // remove random customer after another random customer.
                var customer = _random.Generate(problem.Times.Length);
                var insert   = _random.Generate(problem.Times.Length - 1);
                if (insert >= customer)
                { // customer is the same of after.
                    insert++;
                }

                // shift after the next customer.
                tour.ShiftAfter(customer, insert);
                var afterShift = objective.Calculate(problem, tour);
                var shiftDiff  = afterShift - original;
                difference += shiftDiff;

                // decrease level.
                level--;
            }
            return(difference < 0);
        }
Beispiel #4
0
        /// <summary>
        /// Returns true if there was an improvement, false otherwise.
        /// </summary>
        /// <returns></returns>
        public bool Apply(TSPTWProblem problem, TObjective objective, Tour solution, out float delta)
        {
            var before = float.MaxValue;

            if (objective.IsNonContinuous)
            {
                before = objective.Calculate(problem, solution);
            }

            // STRATEGY:
            // 1: try to move a violated customer backwards.
            // 2: try to move a non-violated customer forward.
            // 3: try to move a non-violated customer backward.
            // 4: try to move a violated customer forward.
            if (!_assumeFeasible)
            {
                if (this.MoveViolatedBackward(problem, objective, solution, out delta))
                { // success already, don't try anything else.
                    if (objective.IsNonContinuous)
                    {
                        delta = before - objective.Calculate(problem, solution);
                    }
                    return(delta > 0);
                }
            }
            if (this.MoveNonViolatedForward(problem, objective, solution, out delta))
            { // success already, don't try anything else.
                if (objective.IsNonContinuous)
                {
                    delta = before - objective.Calculate(problem, solution);
                }
                return(delta > 0);
            }
            if (this.MoveNonViolatedBackward(problem, objective, solution, out delta))
            { // success already, don't try anything else.
                if (objective.IsNonContinuous)
                {
                    delta = before - objective.Calculate(problem, solution);
                }
                return(delta > 0);
            }
            if (!_assumeFeasible)
            {
                if (this.MoveViolatedForward(problem, objective, solution, out delta))
                { // success already, don't try anything else.
                    if (objective.IsNonContinuous)
                    {
                        delta = before - objective.Calculate(problem, solution);
                    }
                    return(delta > 0);
                }
            }
            return(false);
        }
Beispiel #5
0
        /// <summary>
        /// Returns true if there was an improvement, false otherwise.
        /// </summary>
        /// <returns></returns>
        public bool Apply(TSPTWProblem problem, TObjective objective, Tour tour, int level, out float difference)
        {
            var original = objective.Calculate(problem, tour);

            if (problem.Times.Length / 2 == 1)
            {
                difference = 0;
                return(false);
            }

            difference = 0;
            while (level > 0)
            {
                // remove random customer after another random customer.
                var customer = _random.Generate(problem.Times.Length / 2);
                if (customer == problem.First ||
                    customer == problem.Last)
                { // don't move unmovable customers.
                    continue;
                }
                var before = _random.Generate((problem.Times.Length / 2) - 1);
                if (before >= customer)
                { // customer is the same of after.
                    before++;
                }
                if (problem.First != problem.Last &&
                    problem.Last.HasValue &&
                    problem.Last == before)
                { // don't move after a fixed last customer.
                    continue;
                }

                // get the actual id's of the customers.
                var directedCustomer = tour.GetDirectedId(customer);
                var directedBefore   = tour.GetDirectedId(before);

                // do the best possible shift after.
                tour.ShiftAfterBestTurns(problem.Times, problem.TurnPenalties, directedCustomer, directedBefore);

                // calculate new fitness.
                var afterShift = objective.Calculate(problem, tour);
                var shiftDiff  = afterShift - original;
                difference += shiftDiff;

                // decrease level.
                level--;
            }
            return(difference < 0);
        }
Beispiel #6
0
        /// <summary>
        /// Returns true if there was an improvement, false otherwise.
        /// </summary>
        /// <returns></returns>
        public bool Apply(TSPTWProblem problem, TObjective objective, Tour solution, out float delta)
        {
            if (_validFlags == null)
            {
                _validFlags = new bool[problem.Times.Length / 2];
            }

            // STRATEGY:
            // 1: try to move a violated customer backwards.
            // 2: try to move a non-violated customer forward.
            // 3: try to move a non-violated customer backward.
            // 4: try to move a violated customer forward.
            if (!_assumeFeasible)
            {
                if (this.MoveViolatedBackward(problem, objective, solution, out delta))
                { // success already, don't try anything else.
                    return(delta > 0);
                }
            }
            if (this.MoveNonViolatedForward(problem, objective, solution, out delta))
            { // success already, don't try anything else.
                return(delta > 0);
            }
            if (this.MoveNonViolatedBackward(problem, objective, solution, out delta))
            { // success already, don't try anything else.
                return(delta > 0);
            }
            if (!_assumeFeasible)
            {
                if (this.MoveViolatedForward(problem, objective, solution, out delta))
                { // success already, don't try anything else.
                    return(delta > 0);
                }
            }
            return(false);
        }
Beispiel #7
0
        /// <summary>
        /// Returns true if there was an improvement, false otherwise.
        /// </summary>
        /// <returns></returns>
        public bool MoveViolatedForward(TSPTWProblem problem, TObjective objective, Tour solution, out float delta)
        {
            // search for invalid customers.
            var enumerator = solution.GetEnumerator();
            var time       = 0f;
            var fitness    = 0f;
            var position   = 0;
            var invalids   = new List <Tuple <int, int> >(); // al list of customer-position pairs.
            var previous   = Constants.NOT_SET;

            while (enumerator.MoveNext())
            {
                var current = enumerator.Current;
                if (previous != Constants.NOT_SET)
                { // keep track of time.
                    time += problem.Times[previous][current];
                }
                var window = problem.Windows[enumerator.Current];
                if (window.Max < time && position > 0 && position < problem.Times.Length - 1)
                { // ok, unfeasible and customer is not the first 'moveable' customer.
                    fitness += time - window.Max;
                    if (enumerator.Current != problem.Last)
                    { // when the last customer is fixed, don't try to relocate.
                        invalids.Add(new Tuple <int, int>(enumerator.Current, position));
                    }
                }
                if (window.Min > time)
                { // wait here!
                    time = window.Min;
                }

                // increase position.
                position++;
                previous = enumerator.Current;
            }

            // ... ok, if a customer was found, try to move it.
            foreach (var invalid in invalids)
            {
                // ok try the new position.
                for (var newPosition = invalid.Item2 + 1; newPosition < problem.Times.Length; newPosition++)
                {
                    var before = solution.GetCustomerAt(newPosition);
                    if (before == problem.Last)
                    { // cannot move a customer after a fixed last customer.
                        continue;
                    }

                    // calculate new total min diff.
                    var newFitness = 0.0f;
                    previous   = Constants.NOT_SET;
                    time       = 0;
                    enumerator = solution.GetEnumerator();
                    while (enumerator.MoveNext())
                    {
                        var current = enumerator.Current;
                        if (current != invalid.Item1)
                        {     // ignore invalid, add it after 'before'.
                            if (previous != Constants.NOT_SET)
                            { // keep track if time.
                                time += problem.Times[previous][current];
                            }
                            var window = problem.Windows[enumerator.Current];
                            if (window.Max < time)
                            { // ok, unfeasible and customer is not the first 'moveable' customer.
                                newFitness += time - window.Max;
                            }
                            if (window.Min > time)
                            { // wait here!
                                time = window.Min;
                            }
                            previous = current;
                            if (current == before)
                            { // also add the before->invalid.
                                time  += problem.Times[current][invalid.Item1];
                                window = problem.Windows[invalid.Item1];
                                if (window.Max < time)
                                { // ok, unfeasible and customer is not the first 'moveable' customer.
                                    newFitness += time - window.Max;
                                }
                                if (window.Min > time)
                                { // wait here!
                                    time = window.Min;
                                }
                                previous = invalid.Item1;
                            }
                        }
                    }

                    if (newFitness < fitness)
                    { // there is improvement!
                        delta = fitness - newFitness;
                        solution.ShiftAfter(invalid.Item1, before);
                        return(true);
                    }
                }
            }
            delta = 0;
            return(false);
        }
Beispiel #8
0
 /// <summary>
 /// Returns true if there was an improvement, false otherwise.
 /// </summary>
 /// <returns></returns>
 public bool Apply(TSPTWProblem problem, TObjective objective, Tour tour, out float difference)
 {
     return(this.Apply(problem, objective, tour, 1, out difference));
 }
Beispiel #9
0
        /// <summary>
        /// Returns true if there was an improvement, false otherwise.
        /// </summary>
        /// <returns></returns>
        public bool MoveViolatedForward(TSPTWProblem problem, TObjective objective, Tour solution, out float delta)
        {
            if (_validFlags == null)
            {
                _validFlags = new bool[problem.Times.Length / 2];
            }

            float time, waitTime, violatedTime;
            int   violated;
            var   fitness = objective.Calculate(problem, solution, out violated, out violatedTime, out waitTime, out time, ref _validFlags);

            // if no violated customer found return false.
            if (violated == 0)
            {
                delta = 0;
                return(false);
            }

            // loop over all customers.
            var enumerator = solution.GetEnumerator();
            var position   = 0;

            while (enumerator.MoveNext())
            {
                if (position == 0)
                { // don't move the first customer.
                    position++;
                    continue;
                }

                // get the id of the current customer.
                var current = enumerator.Current;
                var id      = DirectedHelper.ExtractId(current);

                if (problem.Last == id)
                { // don't place a fixed last customer.
                    position++;
                    continue;
                }

                // is this customer violated.
                if (_validFlags[id])
                { // no it's not, move on.
                    position++;
                    continue;
                }

                // move over all customers before the current position.
                var enumerator2 = solution.GetEnumerator();
                var position2   = 0;
                while (enumerator2.MoveNext())
                {
                    if (position2 <= position)
                    { // only consider placement after.
                        position2++;
                        continue;
                    }

                    var current2 = enumerator2.Current;
                    var id2      = DirectedHelper.ExtractId(current2);
                    if (problem.Last == id2 &&
                        problem.Last != problem.First)
                    { // don't place a fixed last customer.
                        position2++;
                        continue;
                    }

                    // test and check fitness.
                    // TODO: do best-placement? check best turn at 'current'.
                    var shiftedTour = solution.GetShiftedAfter(current, current2); // generates a tour as if current was placed right after current2.
                    var newFitness  = objective.Calculate(problem, shiftedTour);

                    if (newFitness < fitness)
                    { // there is improvement!
                        delta = fitness - newFitness;
                        solution.ShiftAfter(current, current2);
                        return(true);
                    }

                    position2++;
                }

                position++;
            }
            delta = 0;
            return(false);
        }