Example #1
0
 private void GetInitialSolutions()
 {
     tspSolution            = new TspSolution(new TspProblem(tspCities));
     vehicleRoutingSolution = new VehicleRoutingSolution(new VehicleRoutingProblem(routingCustomers, routingVehicles));
     floorplanSolution      = new FloorplanSolution(new FloorplanProblem(floorplanRectangles)).Shuffle(1) as FloorplanSolution;
     for (int i = 0; i < 12; i++)
     {
         floorplanSolution = floorplanSolution.Transcode() as FloorplanSolution;
     }
 }
Example #2
0
        /// <summary>
        ///     This is the entry point for the default solver
        ///     which just finds a valid random tour
        /// </summary>
        /// <returns>
        ///     results array for GUI that contains three ints: cost of solution, time spent to find solution, number of
        ///     solutions found during search (not counting initial BSSF estimate)
        /// </returns>
        public string[] DefaultSolveProblem()
        {
            var count   = 0;
            var results = new string[3];
            var perm    = new int[_cities.Length];

            _route = new List <City>();
            var rnd   = new Random();
            var timer = new Stopwatch();

            timer.Start();

            do
            {
                int i;
                for (i = 0; i < perm.Length; i++) // create a random permutation template
                {
                    perm[i] = i;
                }
                for (i = 0; i < perm.Length; i++)
                {
                    var swap = i;
                    while (swap == i)
                    {
                        swap = rnd.Next(0, _cities.Length);
                    }
                    var temp = perm[i];
                    perm[i]    = perm[swap];
                    perm[swap] = temp;
                }
                _route.Clear();
                for (i = 0; i < _cities.Length; i++) // Now build the route using the random permutation
                {
                    _route.Add(_cities[perm[i]]);
                }
                _bssf = new TspSolution(_route);
                count++;
            } while (double.IsPositiveInfinity(CostOfBssf())); // until a valid route is found
            timer.Stop();

            results[Cost]  = CostOfBssf().ToString(CultureInfo.CurrentCulture); // load results array
            results[Time]  = timer.Elapsed.ToString();
            results[Count] = count.ToString();

            return(results);
        }
Example #3
0
        /// <summary>
        /// Perform calculation for next path iteration, reporting progress.
        /// Progress report must be handled in class creating a member of this class.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void SolverDoWork(object sender, DoWorkEventArgs e)
        {
            // Start calculating runtime
            var startTime = DateTime.Now;

            // Thread sleeps allow user time to visually process each update
            var threadSleepLength = (e.Argument as Tuple <Tsp, int>).Item2;
            var sleepCount        = 0;

            var tsp         = (e.Argument as Tuple <Tsp, int>).Item1;
            var tspSolution = new TspSolution();

            var shortestPath      = new Path();
            var unvisitedCities   = new Path(tsp.Cities);
            var calculationAmount = 0;

            while (shortestPath.Count != tsp.Cities.Count)
            {
                // Get next stage of path
                this.TraverseNext(ref shortestPath, ref unvisitedCities, ref calculationAmount);

                // Update solution
                tspSolution.ShortestPath      = shortestPath;
                tspSolution.Runtime           = (DateTime.Now - startTime).TotalSeconds - ((double)threadSleepLength / 1000) * sleepCount;
                tspSolution.CalculationAmount = calculationAmount;

                // Calculate completion percentage
                var progressPercentage = Convert.ToInt32((shortestPath.Count * 100) / tsp.Cities.Count);

                // Report progress
                (sender as BackgroundWorker).ReportProgress(progressPercentage, tspSolution);

                // Sleep to allow user to visually process update
                if (threadSleepLength > 0)
                {
                    sleepCount++;
                    System.Threading.Thread.Sleep(threadSleepLength);
                }
            }

            // Return solution
            e.Result = tspSolution;
        }
Example #4
0
        /* 2-Opt solution is based on psuedo code found at https://en.wikipedia.org/wiki/2-opt */
        private TspSolution threeOptSwapB(TspSolution curRoute, int i, int j, int k)
        {
            List <City> newRoute = new List <City>();

            curRoute = new TspSolution(pre_shift(curRoute.Route, i));

            // 2.take route[i] to route[k] and add them in reverse order to new_route
            for (int p = j; p >= 0; p--)
            {
                newRoute.Add(curRoute.Route[p]);
            }
            for (int p = k - 1; p > j; p--)
            {
                newRoute.Add(curRoute.Route[p]);
            }
            for (int p = k; p < curRoute.Route.Count; p++)
            {
                newRoute.Add(curRoute.Route[p]);
            }
            return(new TspSolution(post_shift(newRoute, i)));
        }
Example #5
0
        /* 2-Opt solution is based on psuedo code found at https://en.wikipedia.org/wiki/2-opt */
        private TspSolution twoOptSwap(TspSolution curRoute, int i, int k)
        {
            List <City> newRoute = new List <City>();

            // 1.take route[1] to route[i - 1] and add them in order to new_route
            for (int p = 0; p < i; p++)
            {
                newRoute.Add(curRoute.Route[p]);
            }
            // 2.take route[i] to route[k] and add them in reverse order to new_route
            for (int p = k; p >= i; p--)
            {
                newRoute.Add(curRoute.Route[p]);
            }
            // 3.take route[k + 1] to end and add them in order to new_route
            for (int p = k + 1; p < curRoute.Route.Count; p++)
            {
                newRoute.Add(curRoute.Route[p]);
            }
            return(new TspSolution(newRoute));
        }
Example #6
0
 //O(n^2)
 private bool isCompleteSolution(TspSolution tspSolution)
 {
     if (tspSolution.Route.Count != _cities.Length)
     {
         return(false);
     }
     //O(n^2)
     for (int i = 0; i < _cities.Length; i++)
     {
         //O(n)
         if (!tspSolution.Route.Contains(_cities[i]))
         {
             return(false);
         }
         if (i + 1 < _cities.Length && tspSolution.Route[i].CostToGetTo(tspSolution.Route[i + 1]) == double.PositiveInfinity)
         {
             return(false);
         }
     }
     return(true);
 }
Example #7
0
        //if (_mode == HardMode.Modes.Hard)
        //{
        //    var upperBound = double.PositiveInfinity;
        //    for (var startCity = 0; startCity < _cities.Length; ++startCity)
        //    {
        //        var testState = BranchBoundCalc(baseState, startCity);
        //        if (testState == null || testState.LowerBound >= upperBound) continue;
        //        upperBound = testState.LowerBound;
        //        bestState = testState;
        //    }
        //}
        //else

        /////////////////////////////////////////////////////////////////////////////////////////////
        // These additional solver methods will be implemented as part of the group project.
        ////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        ///     finds the greedy tour starting from each city and keeps the best (valid) one
        /// </summary>
        /// <returns>
        ///     results array for GUI that contains three ints: cost of solution, time spent to find solution, number of
        ///     solutions found during search (not counting initial BSSF estimate)
        /// </returns>
        public string[] GreedySolveProblem()
        {
            var results = new string[3];
            var timer   = new Stopwatch();

            Debug.Assert(_cities.Length > 0);
            timer.Start();
            var costMatrix = new TspState(_cities).CostMatrix;

            if (_mode == HardMode.Modes.Hard)
            {
                // CostOfBssf() is still used because new TspState reduces the matrix once
                var cost = double.PositiveInfinity;
                for (var startCity = 0; startCity < _cities.Length; ++startCity)
                {
                    var thisResult = FastGreedyCalc(startCity, costMatrix);
                    if (thisResult.Item1 >= cost)
                    {
                        continue;
                    }
                    cost  = thisResult.Item1;
                    _bssf = new TspSolution(thisResult.Item2.Select(i => _cities[i]));
                }
            }
            else
            {
                var cityIndexes = FastGreedyCalc(0, costMatrix);
                _bssf = new TspSolution(cityIndexes.Item2.Select(i => _cities[i]));
            }
            timer.Stop();

            results[Cost]  = CostOfBssf().ToString(CultureInfo.InvariantCulture);
            results[Time]  = timer.Elapsed.ToString();
            results[Count] = (_cities.Length + 1).ToString();

            return(results);
        }
        private void DrawGraphOf(TspSolution tspSolution, bool graphShouldConnect = true, TravellingSalesmanProblemLibrary.Path cities = null)
        {
            // Clear the graph of previous solution
            this.cityMap.Children.Clear();

            // Set the list of all cities to the shortest path if it is null
            cities = cities == null ? new TravellingSalesmanProblemLibrary.Path(tspSolution.ShortestPath) : cities;

            // Plot each city on the graph
            foreach (var city in cities)
            {
                // Dimensions are modified to space them out on the graph
                var cityX = city.Coordinate.X * CITY_COORDINATE_MODIFIER;
                var cityY = city.Coordinate.Y * CITY_COORDINATE_MODIFIER;

                // Create a visual representation of the point on the graph
                var cityEllipse = new Ellipse()
                {
                    Height = CITY_CIRCLE_DIAMETER,
                    Width  = CITY_CIRCLE_DIAMETER,
                    Stroke = Brushes.Black,
                    Margin = new Thickness(cityX - CITY_CIRCLE_DIAMETER / 2, cityY - CITY_CIRCLE_DIAMETER / 2, 0, 0)
                };

                // Add ellipse to graph
                this.cityMap.Children.Add(cityEllipse);

                // Create a label for the point
                var cityTextBlock = new TextBlock()
                {
                    Text = Convert.ToString(city.Name)
                };

                // Set label coordinates
                Canvas.SetLeft(cityTextBlock, cityX + CITY_LABEL_BUFFER);
                Canvas.SetTop(cityTextBlock, cityY - CITY_LABEL_BUFFER);

                // Add label to graph
                this.cityMap.Children.Add(cityTextBlock);
            }

            // Create points list for graphing
            var points = new TravellingSalesmanProblemLibrary.Path(tspSolution.ShortestPath);

            // Re-add the first city to connect the graph
            if (graphShouldConnect)
            {
                points.Add(points[0]);
            }

            // Add lines to the graph
            for (int i = 0; i < points.Count - 1; i++)
            {
                // Create a line between the current point and the next
                var line = new Line()
                {
                    X1              = points[i].Coordinate.X * CITY_COORDINATE_MODIFIER,
                    Y1              = points[i].Coordinate.Y * CITY_COORDINATE_MODIFIER,
                    X2              = points[i + 1].Coordinate.X * CITY_COORDINATE_MODIFIER,
                    Y2              = points[i + 1].Coordinate.Y * CITY_COORDINATE_MODIFIER,
                    Stroke          = new SolidColorBrush(Colors.Red),
                    StrokeThickness = 2
                };

                // Add line to graph
                this.cityMap.Children.Add(line);
            }

            // Update all label text
            var shortestPathLength = graphShouldConnect ? tspSolution.ShortestPath.CompleteLength : tspSolution.ShortestPath.Length;

            this.shortestPath.Text     = $"{Math.Round(shortestPathLength, 4)} m";
            this.runtime.Text          = $"{Math.Round(tspSolution.Runtime * 1000, 4)} ms";
            this.calculationCount.Text = $"{tspSolution.CalculationAmount}";
        }
Example #9
0
        static void Main(string[] args)
        {
            //FloorplanProblem problem = new FloorplanProblem(50);
            //FloorplanSolution solution = new FloorplanSolution(problem);
            //Swap swap = new Swap(problem.Dimension);
            //Shift shift = new Shift(problem.Dimension);
            //FullLeafMove leaf = new FullLeafMove(problem.Dimension);
            //List<Operator> operations = new List<Operator> { swap, shift, leaf };



            TspProblem      problem    = new TspProblem(100);
            TspSolution     solution   = new TspSolution(problem);
            Swap            swap       = new Swap(problem.Dimension, 1);
            Shift           shift      = new Shift(problem.Dimension, 2);
            TwoOpt          twoOpt     = new TwoOpt(problem.Dimension, 3);
            List <Operator> operations = new List <Operator> {
                swap, shift, twoOpt
            };



            MultistartParameters multistartOptions = new MultistartParameters()
            {
                InstancesNumber = 1,
                OutputFrequency = 500,
            };

            LocalDescentParameters ldParameters = new LocalDescentParameters()
            {
                DetailedOutput    = true,
                Seed              = 0,
                Operators         = operations,
                IsSteepestDescent = false
            };

            SimulatedAnnealingParameters saParameters = new SimulatedAnnealingParameters()
            {
                InitProbability         = 0.3,
                TemperatureCooling      = 0.97,
                UseWeightedNeighborhood = true,
                DetailedOutput          = false,
                Seed      = 0,
                Operators = operations,
            };

            MultistartParameters ldMultistartParameters = (MultistartParameters)multistartOptions.Clone();

            ldMultistartParameters.Parameters = ldParameters;

            MultistartParameters saMultistartParameters = (MultistartParameters)multistartOptions.Clone();

            saMultistartParameters.Parameters = saParameters;

            LocalDescent       ld  = new LocalDescent(ldParameters);
            SimulatedAnnealing sa  = new SimulatedAnnealing(saParameters);
            ParallelMultistart pld = new ParallelMultistart(ldMultistartParameters);
            ParallelMultistart psa = new ParallelMultistart(saMultistartParameters);

            List <string> operators = new List <string>();

            IPermutation sol = solution;

            foreach (IPermutation s in ld.Minimize(solution))
            {
                Console.WriteLine("{0}, {1:f}s, {2}, {3}, {4}, {5}", s.CostValue, s.TimeInSeconds, s.IterationNumber, s.IsCurrentBest, s.IsFinal, sol.CostValue - s.CostValue);
                sol = s;
                operators.Add(s.OperatorTag);
            }


            //var groups = operators.GroupBy(s => s).Select(s => new { Operator = s.Key, Count = s.Count() });
            //var dictionary = groups.ToDictionary(g => g.Operator, g => g.Count);

            //foreach (var o in groups)
            //{
            //    Console.WriteLine("{0} = {1}", o.Operator, o.Count);
            //}

            Console.WriteLine("Done");
            Console.ReadLine();
        }
Example #10
0
        public string[] ThreeOptSolveProblem()
        {
            var results = new string[3];

            // get initial bssf using default algorithm
            int i, swap, temp, count = 0;

            int[] perm = new int[_cities.Length];
            _route = new List <City>();
            Random rnd = new Random();

            do
            {
                for (i = 0; i < perm.Length; i++)                                 // create a random permutation template
                {
                    perm[i] = i;
                }
                for (i = 0; i < perm.Length; i++)
                {
                    swap = i;
                    while (swap == i)
                    {
                        swap = rnd.Next(0, _cities.Length);
                    }
                    temp       = perm[i];
                    perm[i]    = perm[swap];
                    perm[swap] = temp;
                }
                _route.Clear();
                for (i = 0; i < _cities.Length; i++)                            // Now build the route using the random permutation
                {
                    _route.Add(_cities[perm[i]]);
                }
                _bssf = new TspSolution(_route);
            } while (CostOfBssf() == double.PositiveInfinity);                // until a valid route is found


            Stopwatch timer = new Stopwatch();

            timer.Start();
            count = 0;
            TspSolution prevSolution = _bssf;

            bool found = false;

            do
            {
                double bestDist = _bssf.CostOfRoute();
                found = false;
                for (i = 0; i < _bssf.Route.Count - 2; i++)
                {
                    for (int j = i + 1; j < _bssf.Route.Count - 1; j++)
                    {
                        for (int k = j + 1; k < _bssf.Route.Count; k++)
                        {
                            TspSolution newRoute1 = threeOptSwapA(_bssf, i, j, k);
                            TspSolution newRoute2 = threeOptSwapB(_bssf, i, j, k);
                            TspSolution newRoute3 = threeOptSwapC(_bssf, i, j, k);
                            TspSolution newRoute4 = twoOptSwap(_bssf, i, j);
                            TspSolution newRoute5 = twoOptSwap(_bssf, j, k);
                            TspSolution newRoute6 = twoOptSwap(_bssf, i, k);

                            double newDist1 = newRoute1.CostOfRoute();
                            double newDist2 = newRoute2.CostOfRoute();
                            double newDist3 = newRoute3.CostOfRoute();
                            double newDist4 = newRoute4.CostOfRoute();
                            double newDist5 = newRoute5.CostOfRoute();
                            double newDist6 = newRoute6.CostOfRoute();


                            if (isCompleteSolution(newRoute1) && newDist1 < bestDist && newDist1 <= newDist2 && newDist1 <= newDist3 && newDist1 <= newDist4 && newDist1 <= newDist5 && newDist1 <= newDist6)
                            {
                                prevSolution = _bssf;
                                _bssf        = newRoute1;
                                found        = true;
                                count++;
                                break;
                            }
                            if (isCompleteSolution(newRoute2) && newDist2 < bestDist && newDist2 <= newDist1 && newDist2 <= newDist3 && newDist2 <= newDist4 && newDist2 <= newDist5 && newDist2 <= newDist6)
                            {
                                prevSolution = _bssf;
                                _bssf        = newRoute2;
                                found        = true;
                                count++;
                                break;
                            }
                            if (isCompleteSolution(newRoute3) && newDist3 < bestDist && newDist3 <= newDist2 && newDist3 <= newDist1 && newDist3 <= newDist4 && newDist3 <= newDist5 && newDist3 <= newDist6)
                            {
                                prevSolution = _bssf;
                                _bssf        = newRoute3;
                                found        = true;
                                count++;
                                break;
                            }
                            if (isCompleteSolution(newRoute4) && newDist4 < bestDist && newDist4 <= newDist2 && newDist4 <= newDist1 && newDist4 <= newDist3 && newDist4 <= newDist5 && newDist4 <= newDist6)
                            {
                                prevSolution = _bssf;
                                _bssf        = newRoute4;
                                found        = true;
                                count++;
                                break;
                            }
                            if (isCompleteSolution(newRoute5) && newDist5 < bestDist && newDist5 <= newDist2 && newDist5 <= newDist1 && newDist5 <= newDist4 && newDist5 <= newDist3 && newDist5 <= newDist6)
                            {
                                prevSolution = _bssf;
                                _bssf        = newRoute5;
                                found        = true;
                                count++;
                                break;
                            }
                            if (isCompleteSolution(newRoute6) && newDist6 < bestDist && newDist6 <= newDist2 && newDist6 <= newDist1 && newDist6 <= newDist4 && newDist6 <= newDist5 && newDist6 <= newDist3)
                            {
                                prevSolution = _bssf;
                                _bssf        = newRoute6;
                                found        = true;
                                count++;
                                break;
                            }
                        }
                        if (found)
                        {
                            break;
                        }
                    }
                    if (found)
                    {
                        break;
                    }
                }
            } while (found);


            timer.Stop();

            results[Cost]  = _bssf.CostOfRoute().ToString();
            results[Time]  = timer.Elapsed.ToString();
            results[Count] = count.ToString();

            return(results);
        }
Example #11
0
        public string[] TwoOptSolveProblem()
        {
            var results = new string[3];

            // get initial bssf using default algorithm
            int i, swap, temp, count = 0;

            int[] perm = new int[_cities.Length];
            _route = new List <City>();
            Random rnd = new Random();

            do
            {
                for (i = 0; i < perm.Length; i++)                                 // create a random permutation template
                {
                    perm[i] = i;
                }
                for (i = 0; i < perm.Length; i++)
                {
                    swap = i;
                    while (swap == i)
                    {
                        swap = rnd.Next(0, _cities.Length);
                    }
                    temp       = perm[i];
                    perm[i]    = perm[swap];
                    perm[swap] = temp;
                }
                _route.Clear();
                for (i = 0; i < _cities.Length; i++)                            // Now build the route using the random permutation
                {
                    _route.Add(_cities[perm[i]]);
                }
                _bssf = new TspSolution(_route);
            } while (CostOfBssf() == double.PositiveInfinity);                // until a valid route is found



            Stopwatch timer = new Stopwatch();

            timer.Start();
            count = 0;
            TspSolution prevSolution = _bssf;

            bool found = false;

            do
            {
                double bestDist = _bssf.CostOfRoute();
                for (i = 0; i < _bssf.Route.Count; i++)
                {
                    found = false;
                    for (int k = i + 1; k < _bssf.Route.Count; k++)
                    {
                        TspSolution newRoute = twoOptSwap(_bssf, i, k);
                        double      newDist  = newRoute.CostOfRoute();
                        if (isCompleteSolution(newRoute) && newDist < bestDist)
                        {
                            prevSolution = _bssf;
                            _bssf        = newRoute;
                            found        = true;
                            count++;
                            break;
                        }
                    }
                    if (found)
                    {
                        break;
                    }
                }
            } while (found);


            timer.Stop();

            results[Cost]  = _bssf.CostOfRoute().ToString();
            results[Time]  = timer.Elapsed.ToString();
            results[Count] = count.ToString();

            return(results);
        }
Example #12
0
        /// <summary>
        ///     performs a Branch and Bound search of the state space of partial tours
        ///     stops when time limit expires and uses BSSF as solution
        /// </summary>
        /// <returns>
        ///     results array for GUI that contains three ints: cost of solution, time spent to find solution, number of
        ///     solutions found during search (not counting initial BSSF estimate)
        /// </returns>
        public string[] BranchBoundSolveProblem()
        {
            var results = new string[3];

            var timer = new Stopwatch();

            Debug.Assert(_cities.Length > 0);
            var baseState = new TspState(_cities);

            timer.Start();

            var n     = _cities.Length;
            var queue = new FastPriorityQueue <TspState>(n * n * n);

            baseState = baseState.Visit(0);
            queue.Enqueue(baseState, baseState.Heuristic());
            // The current best complete route
            var bestState  = GreedyCalc(baseState);
            var upperBound = bestState?.LowerBound ?? double.PositiveInfinity;
            var stored     = 0;
            var pruned     = 0;
            var maxStates  = 0;
            var updates    = 0;

            while (queue.Count > 0)
            {
                if (queue.Count > maxStates)
                {
                    maxStates = queue.Count;
                }
                // Get best state to check based on heuristic.
                // Runs in O(log n) time.
                var state = queue.Dequeue();
                // Branch
                for (var toCity = 0; toCity < n; ++toCity)
                {
                    // If we can't visit the city, no need to consider it
                    if (!state.CanVisit(toCity))
                    {
                        continue;
                    }
                    var branchState = state.Visit(toCity);
                    // Bound
                    if (branchState.LowerBound < upperBound)
                    {
                        if (branchState.IsComplete)
                        {
                            ++updates;
                            // On a complete instance, no need to add it to the queue.
                            Debug.Assert(branchState.CostMatrix.Cast <double>().All(double.IsPositiveInfinity),
                                         "Cost Matrix is not all infinity");
                            upperBound = branchState.LowerBound;
                            bestState  = branchState;
                            continue;
                        }
                        ++stored;
                        if (queue.Count + 5 >= queue.MaxSize)
                        {
                            queue.Resize(queue.MaxSize * 2);
                        }
                        // Runs in O(log n) time
                        queue.Enqueue(branchState, branchState.Heuristic());
                    }
                    else
                    {
                        ++pruned;
                    }
                }
                // Abandon ship and give the best result otherwise
                if (timer.ElapsedMilliseconds > _timeLimit)
                {
                    break;
                }
            }
            timer.Stop();

            Debug.Assert(bestState != null && bestState.IsComplete);
            _bssf = StateToSolution(bestState);

            results[Cost]  = CostOfBssf().ToString(CultureInfo.InvariantCulture); // load results array
            results[Time]  = timer.Elapsed.ToString();
            results[Count] = $"{maxStates}/{updates}/{stored}/{pruned}";

            return(results);
        }
Example #13
0
        private void bwTsp_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = (BackgroundWorker)sender;

            algorithmStatus.Text = "Press ESC to cancel";

            TspProblem  problem       = new TspProblem(tspCities);
            TspSolution startSolution = new TspSolution(problem);

            Swap   swap   = new Swap(problem.Dimension, 1);
            Shift  shift  = new Shift(problem.Dimension, 2);
            TwoOpt twoOpt = new TwoOpt(problem.Dimension, 3);

            List <Operator> operations = new List <Operator> {
                swap, shift, twoOpt
            };
            MultistartParameters multistartParameters = (MultistartParameters)multistartOptions.Clone();

            LocalDescentParameters ldParameters = new LocalDescentParameters()
            {
                Name           = "TSP LD",
                Seed           = seed,
                DetailedOutput = true,
                Operators      = operations
            };

            SimulatedAnnealingParameters saParameters = new SimulatedAnnealingParameters()
            {
                Name               = "TSP SA",
                InitProbability    = 0.5,
                TemperatureCooling = 0.91,
                MinCostDeviation   = 10E-3,
                Seed               = seed,
                DetailedOutput     = true,
                Operators          = operations
            };

            StackedParameters ssParameters = new StackedParameters()
            {
                Name                   = "B",
                DetailedOutput         = true,
                OptimizationAlgorithms = new Type[] { typeof(LocalDescent), typeof(SimulatedAnnealing), typeof(LocalDescent) },
                Parameters             = new OptimizationParameters[] { ldParameters, saParameters, ldParameters }
            };

            switch (optimizerType)
            {
            case 0:
            {
                multistartParameters.Parameters            = ldParameters;
                multistartParameters.OptimizationAlgorithm = typeof(LocalDescent);
            }
            break;

            case 1:
            {
                multistartParameters.Parameters            = saParameters;
                multistartParameters.OptimizationAlgorithm = typeof(SimulatedAnnealing);
            }
            break;

            case 2:
            {
                saParameters.InitProbability               = 0.007;
                saParameters.MinCostDeviation              = 10E-2;
                multistartParameters.Parameters            = ssParameters;
                multistartParameters.OptimizationAlgorithm = typeof(StackedSearch);
            }
            break;

            case 3:
            {
                saParameters.InitProbability               = 0.007;
                saParameters.MinCostDeviation              = 10E-2;
                multistartParameters.InstancesNumber       = 3;
                multistartParameters.Parameters            = ssParameters;
                multistartParameters.OptimizationAlgorithm = typeof(StackedSearch);
            }
            break;
            }

            tspOptimizer = new ParallelMultistart(multistartParameters);

            toRenderBackground = false;

            foreach (ISolution solution in tspOptimizer.Minimize(startSolution))
            {
                if (worker.CancellationPending)
                {
                    tspOptimizer.Stop();
                    e.Cancel = true;
                }
                if (e.Cancel)
                {
                    solution.IsFinal = false;
                }
                worker.ReportProgress(0);
            }
        }