Beispiel #1
0
        public void TestVRPInstances()
        {
            var vrp             = new VehicleRoutingProblem();
            var providers       = ProblemInstanceManager.GetProviders(vrp);
            var failedInstances = new StringBuilder();

            Assert.IsTrue(providers.Any(), "No providers could be found.");

            foreach (var provider in providers)
            {
                IEnumerable <IDataDescriptor> instances = ((dynamic)provider).GetDataDescriptors();
                Assert.IsTrue(instances.Any(), string.Format("No instances could be found in {0}.", provider.Name));

                foreach (var instance in instances)
                {
                    try {
                        // throws InvalidOperationException if zero or more than one interpreter is found
                        ((dynamic)vrp).Load(((dynamic)provider).LoadData(instance));
                    } catch (Exception exc) {
                        failedInstances.AppendLine(instance.Name + ": " + exc.Message);
                    }
                }
            }

            Assert.IsTrue(failedInstances.Length == 0, "Following instances failed: " + Environment.NewLine + failedInstances);
        }
    private ScatterSearch CreateScatterSearchVRPSample() {
      #region Problem Configuration
      var provider = new SolomonInstanceProvider();
      var instance = provider.GetDataDescriptors().Single(x => x.Name == "C101");
      VehicleRoutingProblem vrpProblem = new VehicleRoutingProblem();
      vrpProblem.Load(provider.LoadData(instance));
      #endregion

      #region Algorithm Configuration
      ScatterSearch ss = new ScatterSearch();
      ss.Engine = new SequentialEngine.SequentialEngine();
      ss.Name = "Scatter Search - VRP";
      ss.Description = "A scatter search algorithm which solves the \"C101\" vehicle routing problem (imported from Solomon)";
      ss.Problem = vrpProblem;

      var improver = ss.Problem.Operators.OfType<VRPIntraRouteImprovementOperator>().First();
      improver.ImprovementAttemptsParameter.Value.Value = 15;
      improver.SampleSizeParameter.Value.Value = 10;
      ss.Improver = improver;

      var pathRelinker = ss.Problem.Operators.OfType<VRPPathRelinker>().First();
      pathRelinker.IterationsParameter.Value.Value = 25;
      ss.PathRelinker = pathRelinker;

      var similarityCalculator = ss.SimilarityCalculatorParameter.ValidValues.OfType<VRPSimilarityCalculator>().First();
      ss.SimilarityCalculator = similarityCalculator;

      ss.MaximumIterations.Value = 2;
      ss.PopulationSize.Value = 20;
      ss.ReferenceSetSize.Value = 10;
      ss.Seed.Value = 0;
      return ss;
      #endregion
    }
        static async Task Main(string[] args)
        {
            //IrisDataCluster classifier = new IrisDataCluster(3);
            //classifier.RunAsync();

            //TravelingSalespersonProblem tsp = new TravelingSalespersonProblem(50);
            //tsp.Run();

            //TravelingSalespersonProblem tsp = new TravelingSalespersonProblem("./data/cities.data");
            //tsp.Run();
            //for (int i = 0; i < 3; i++)
            //{
            //    //tsp.RunRestart();
            //    tsp.RunTwoOpt();
            //    tsp.RunTwoOpt();
            //    tsp.RunTwoOpt();
            //}

            //TravellingSalespersonProblem tsp = new TravellingSalespersonProblem("./data/cities.data");
            //tsp.Run();
            //BranchAndBound bnb = new BranchAndBound(tsp.GetCities());
            //await bnb.RunAsync();

            //BranchAndBound bnb = new BranchAndBound("./data/cities.data");
            //await bnb.RunAsync();

            VehicleRoutingProblem vrp = new VehicleRoutingProblem();

            vrp.Run();
        }
Beispiel #4
0
        private void SetProblemInstance(VehicleRoutingProblem problem)
        {
            //var pi = problem.ProblemInstance.Clone() as HeuristicLab.Problems.VehicleRouting.ProblemInstances.MDCVRPTWProblemInstance;
            HeuristicLab.Problems.VehicleRouting.Datalytics.ProblemInstances.MDCVRPTWProblemInstance pi = new HeuristicLab.Problems.VehicleRouting.Datalytics.ProblemInstances.MDCVRPTWProblemInstance();

            pi.Cities.Value            = _tasks.Count;
            pi.Depots.Value            = _drivers.Count;
            pi.Vehicles.Value          = _drivers.Count;     // only allow 1 vehicle per depot
            pi.DistanceFactor.Value    = 1.0;
            pi.FleetUsageFactor.Value  = 0.0;
            pi.UseDistanceMatrix.Value = true;

            pi.Capacity    = new DoubleArray(GetCapacity());
            pi.Coordinates = new DoubleMatrix(GetCoordinates());

            //_coordinates = pi.Coordinates;

            //string patientList = string.Join(",", _stopIds);
            //string staffList = string.Join(",", _driverIds);

            UpdateRun("Calculating Distance Matrix", StrategyState.Running);

            //Routing.Routing routing = new Routing.Routing();
            //_routeLegs = routing.GetRouteLegs(patientList, staffList, "Distance");

            pi.DistanceMatrix = CreateDistanceMatrix();
            pi.TimeMatrix     = CreateTimeMatrix();
            pi.QualityMatrix  = CreateQualityMatrix();

            // cost-based functionality
            pi.CostOptimization.Value    = _costOptimization;
            pi.DistanceToCostRatio.Value = _distanceCostRatio;
            pi.PerStopCost          = CreatePerVisitCostArray();
            pi.PerMileCost          = CreatePerMileCostArray();
            pi.AvgLegLength.Value   = _avgLegLength;
            pi.AvgLegPenality.Value = _avgLegPenalty;
            pi.MaxLegLength.Value   = _maxLegLength;
            pi.MaxLegPenality.Value = _maxLegPenalty;

            UpdateRun("Distance Matrix Loaded", StrategyState.Running);

            pi.Demand = new DoubleArray(GetDemand(_tasks.Count));

            double dueTime = 1.7976931348623157E308;              // Max double, we need this for some reason, 0 didn't work

            pi.DueTime                = new DoubleArray(GetDueTime(_tasks.Count + _drivers.Count, dueTime));
            pi.ServiceTime            = new DoubleArray(GetServiceTime(_tasks.Count));
            pi.ReadyTime              = new DoubleArray(GetReadyTime(_tasks.Count + _drivers.Count));
            pi.VehicleDepotAssignment = new IntArray(SetVehicleDepotAssignment(_drivers.Count));

            // set the vehicle assigment array
            _vehicleAssignment = pi.VehicleDepotAssignment;

            problem.SetProblemInstance(pi);

            UpdateRun("Problem Instance Set", StrategyState.Running);
        }
        private GeneticAlgorithm CreateGaVrpSample()
        {
            GeneticAlgorithm ga = new GeneticAlgorithm();

            #region Problem Configuration
            VehicleRoutingProblem vrpProblem = new VehicleRoutingProblem();

            SolomonFormatInstanceProvider instanceProvider = new SolomonInstanceProvider();
            CVRPTWData data = instanceProvider.Import(@"Test Resources\C101.txt", @"Test Resources\C101.opt.txt") as CVRPTWData;
            vrpProblem.Load(data);
            vrpProblem.Name        = "C101 VRP (imported from Solomon)";
            vrpProblem.Description = "Represents a Vehicle Routing Problem.";
            CVRPTWProblemInstance instance = vrpProblem.ProblemInstance as CVRPTWProblemInstance;
            instance.DistanceFactor.Value   = 1;
            instance.FleetUsageFactor.Value = 100;
            instance.OverloadPenalty.Value  = 100;
            instance.TardinessPenalty.Value = 100;
            instance.TimeFactor.Value       = 0;
            vrpProblem.MaximizationParameter.Value.Value = false;
            instance.UseDistanceMatrix.Value             = true;
            instance.Vehicles.Value = 25;
            #endregion
            #region Algorithm Configuration
            ga.Name        = "Genetic Algorithm - VRP";
            ga.Description = "A genetic algorithm which solves the \"C101\" vehicle routing problem (imported from Solomon)";
            ga.Problem     = vrpProblem;
            SamplesUtils.ConfigureGeneticAlgorithmParameters <TournamentSelector, MultiVRPSolutionCrossover, MultiVRPSolutionManipulator>(
                ga, 100, 1, 1000, 0.05, 3);

            var xOver = (MultiVRPSolutionCrossover)ga.Crossover;
            foreach (var op in xOver.Operators)
            {
                xOver.Operators.SetItemCheckedState(op, false);
            }
            xOver.Operators.SetItemCheckedState(xOver.Operators
                                                .OfType <PotvinRouteBasedCrossover>()
                                                .Single(), true);
            xOver.Operators.SetItemCheckedState(xOver.Operators
                                                .OfType <PotvinSequenceBasedCrossover>()
                                                .Single(), true);

            var manipulator = (MultiVRPSolutionManipulator)ga.Mutator;
            foreach (var op in manipulator.Operators)
            {
                manipulator.Operators.SetItemCheckedState(op, false);
            }
            manipulator.Operators.SetItemCheckedState(manipulator.Operators
                                                      .OfType <PotvinOneLevelExchangeMainpulator>()
                                                      .Single(), true);
            manipulator.Operators.SetItemCheckedState(manipulator.Operators
                                                      .OfType <PotvinTwoLevelExchangeManipulator>()
                                                      .Single(), true);
            #endregion

            return(ga);
        }
Beispiel #6
0
    private GeneticAlgorithm CreateGaVrpSample() {
      GeneticAlgorithm ga = new GeneticAlgorithm();

      #region Problem Configuration
      VehicleRoutingProblem vrpProblem = new VehicleRoutingProblem();

      SolomonFormatInstanceProvider instanceProvider = new SolomonInstanceProvider();
      CVRPTWData data = instanceProvider.Import(@"Test Resources\C101.txt", @"Test Resources\C101.opt.txt") as CVRPTWData;
      vrpProblem.Load(data);
      vrpProblem.Name = "C101 VRP (imported from Solomon)";
      vrpProblem.Description = "Represents a Vehicle Routing Problem.";
      CVRPTWProblemInstance instance = vrpProblem.ProblemInstance as CVRPTWProblemInstance;
      instance.DistanceFactor.Value = 1;
      instance.FleetUsageFactor.Value = 100;
      instance.OverloadPenalty.Value = 100;
      instance.TardinessPenalty.Value = 100;
      instance.TimeFactor.Value = 0;
      vrpProblem.MaximizationParameter.Value.Value = false;
      instance.UseDistanceMatrix.Value = true;
      instance.Vehicles.Value = 25;
      #endregion
      #region Algorithm Configuration
      ga.Name = "Genetic Algorithm - VRP";
      ga.Description = "A genetic algorithm which solves the \"C101\" vehicle routing problem (imported from Solomon)";
      ga.Problem = vrpProblem;
      SamplesUtils.ConfigureGeneticAlgorithmParameters<TournamentSelector, MultiVRPSolutionCrossover, MultiVRPSolutionManipulator>(
        ga, 100, 1, 1000, 0.05, 3);

      var xOver = (MultiVRPSolutionCrossover)ga.Crossover;
      foreach (var op in xOver.Operators) {
        xOver.Operators.SetItemCheckedState(op, false);
      }
      xOver.Operators.SetItemCheckedState(xOver.Operators
        .OfType<PotvinRouteBasedCrossover>()
        .Single(), true);
      xOver.Operators.SetItemCheckedState(xOver.Operators
        .OfType<PotvinSequenceBasedCrossover>()
        .Single(), true);

      var manipulator = (MultiVRPSolutionManipulator)ga.Mutator;
      foreach (var op in manipulator.Operators) {
        manipulator.Operators.SetItemCheckedState(op, false);
      }
      manipulator.Operators.SetItemCheckedState(manipulator.Operators
        .OfType<PotvinOneLevelExchangeMainpulator>()
        .Single(), true);
      manipulator.Operators.SetItemCheckedState(manipulator.Operators
        .OfType<PotvinTwoLevelExchangeManipulator>()
        .Single(), true);
      #endregion

      return ga;
    }
Beispiel #7
0
        private TabuSearch CreateTabuSearchVrpSample()
        {
            TabuSearch ts = new TabuSearch();

            #region Problem Configuration
            var provider = new AugeratInstanceProvider();
            var instance = provider.GetDataDescriptors().Where(x => x.Name == "A-n62-k8").Single();
            VehicleRoutingProblem vrpProblem = new VehicleRoutingProblem();
            vrpProblem.Load(provider.LoadData(instance));
            #endregion
            #region Algorithm Configuration
            ts.Name        = "Tabu Search - VRP";
            ts.Description = "A tabu search algorithm that solves the \"A-n62-k8\" VRP (imported from Augerat)";
            ts.Problem     = vrpProblem;

            ts.MaximumIterations.Value = 200;
            // move generator has to be set first
            var moveGenerator = ts.MoveGeneratorParameter.ValidValues
                                .OfType <PotvinCustomerRelocationExhaustiveMoveGenerator>()
                                .Single();
            ts.MoveGenerator = moveGenerator;
            var moveEvaluator = ts.MoveEvaluatorParameter.ValidValues
                                .OfType <PotvinCustomerRelocationMoveEvaluator>()
                                .Single();
            ts.MoveEvaluator = moveEvaluator;
            var moveMaker = ts.MoveMakerParameter.ValidValues
                            .OfType <PotvinCustomerRelocationMoveMaker>()
                            .Single();
            ts.MoveMaker             = moveMaker;
            ts.SampleSize.Value      = 1000;
            ts.Seed.Value            = 0;
            ts.SetSeedRandomly.Value = true;

            var tabuChecker = ts.TabuCheckerParameter.ValidValues
                              .OfType <PotvinCustomerRelocationMoveTabuCriterion>()
                              .Single();
            tabuChecker.UseAspirationCriterion.Value = false;
            ts.TabuChecker = tabuChecker;

            var tabuMaker = ts.TabuMakerParameter.ValidValues
                            .OfType <PotvinCustomerRelocationMoveTabuMaker>()
                            .Single();
            ts.TabuMaker        = tabuMaker;
            ts.TabuTenure.Value = 6;

            #endregion
            ts.Engine = new ParallelEngine.ParallelEngine();
            return(ts);
        }
    private TabuSearch CreateTabuSearchVrpSample() {
      TabuSearch ts = new TabuSearch();
      #region Problem Configuration
      var provider = new AugeratInstanceProvider();
      var instance = provider.GetDataDescriptors().Where(x => x.Name == "A-n62-k8").Single();
      VehicleRoutingProblem vrpProblem = new VehicleRoutingProblem();
      vrpProblem.Load(provider.LoadData(instance));
      #endregion
      #region Algorithm Configuration
      ts.Name = "Tabu Search - VRP";
      ts.Description = "A tabu search algorithm that solves the \"A-n62-k8\" VRP (imported from Augerat)";
      ts.Problem = vrpProblem;

      ts.MaximumIterations.Value = 200;
      // move generator has to be set first
      var moveGenerator = ts.MoveGeneratorParameter.ValidValues
        .OfType<PotvinCustomerRelocationExhaustiveMoveGenerator>()
        .Single();
      ts.MoveGenerator = moveGenerator;
      var moveEvaluator = ts.MoveEvaluatorParameter.ValidValues
        .OfType<PotvinCustomerRelocationMoveEvaluator>()
        .Single();
      ts.MoveEvaluator = moveEvaluator;
      var moveMaker = ts.MoveMakerParameter.ValidValues
        .OfType<PotvinCustomerRelocationMoveMaker>()
        .Single();
      ts.MoveMaker = moveMaker;
      ts.SampleSize.Value = 1000;
      ts.Seed.Value = 0;
      ts.SetSeedRandomly.Value = true;

      var tabuChecker = ts.TabuCheckerParameter.ValidValues
        .OfType<PotvinCustomerRelocationMoveTabuCriterion>()
        .Single();
      tabuChecker.UseAspirationCriterion.Value = false;
      ts.TabuChecker = tabuChecker;

      var tabuMaker = ts.TabuMakerParameter.ValidValues
        .OfType<PotvinCustomerRelocationMoveTabuMaker>()
        .Single();
      ts.TabuMaker = tabuMaker;
      ts.TabuTenure.Value = 6;

      #endregion
      ts.Engine = new ParallelEngine.ParallelEngine();
      return ts;
    }
Beispiel #9
0
        private void LoadingCompleted(IStorableContent content)
        {
            //if (error != null) throw error;
            UpdateRun("Algorithm loading complete", StrategyState.Running);

            if (content is HeuristicLab.Algorithms.EvolutionStrategy.EvolutionStrategy)
            {
                algorithm = content as HeuristicLab.Algorithms.EvolutionStrategy.EvolutionStrategy;
                VehicleRoutingProblem problem = algorithm.Problem as VehicleRoutingProblem;

                if (problem == null)
                {
                    Console.WriteLine("Unsupported problem type detected.");
                    return;
                }

                SetProblemInstance(problem);

                ParameterizeProblem(problem);
                ParameterizeAlgorithm(algorithm);

                RegisterAlgorithmEventHandlers(algorithm);

                try
                {
                    algorithm.Start();
                }
                catch (Exception exc)
                {
                    Console.WriteLine("Error Loading: " + exc.Message);
                }
            }
            else
            {
                // TODO: update the run status to error...
                //_strategyState = StrategyState.Stopped;
            }
        }
Beispiel #10
0
    public void TestVRPInstances() {
      var vrp = new VehicleRoutingProblem();
      var providers = ProblemInstanceManager.GetProviders(vrp);
      var failedInstances = new StringBuilder();

      Assert.IsTrue(providers.Any(), "No providers could be found.");

      foreach (var provider in providers) {
        IEnumerable<IDataDescriptor> instances = ((dynamic)provider).GetDataDescriptors();
        Assert.IsTrue(instances.Any(), string.Format("No instances could be found in {0}.", provider.Name));

        foreach (var instance in instances) {
          try {
            // throws InvalidOperationException if zero or more than one interpreter is found
            ((dynamic)vrp).Load(((dynamic)provider).LoadData(instance));
          } catch (Exception exc) {
            failedInstances.AppendLine(instance.Name + ": " + exc.Message);
          }
        }
      }

      Assert.IsTrue(failedInstances.Length == 0, "Following instances failed: " + Environment.NewLine + failedInstances);
    }
Beispiel #11
0
        private ScatterSearch CreateScatterSearchVRPSample()
        {
            #region Problem Configuration
            var provider = new SolomonInstanceProvider();
            var instance = provider.GetDataDescriptors().Single(x => x.Name == "C101");
            VehicleRoutingProblem vrpProblem = new VehicleRoutingProblem();
            vrpProblem.Load(provider.LoadData(instance));
            #endregion

            #region Algorithm Configuration
            ScatterSearch ss = new ScatterSearch();
            ss.Engine      = new SequentialEngine.SequentialEngine();
            ss.Name        = "Scatter Search - VRP";
            ss.Description = "A scatter search algorithm which solves the \"C101\" vehicle routing problem (imported from Solomon)";
            ss.Problem     = vrpProblem;

            var improver = ss.Problem.Operators.OfType <VRPIntraRouteImprovementOperator>().First();
            improver.ImprovementAttemptsParameter.Value.Value = 15;
            improver.SampleSizeParameter.Value.Value          = 10;
            ss.Improver = improver;

            var pathRelinker = ss.Problem.Operators.OfType <VRPPathRelinker>().First();
            pathRelinker.IterationsParameter.Value.Value = 25;
            ss.PathRelinker = pathRelinker;

            var similarityCalculator = ss.SimilarityCalculatorParameter.ValidValues.OfType <VRPSimilarityCalculator>().First();
            ss.SimilarityCalculator = similarityCalculator;

            ss.MaximumIterations.Value = 2;
            ss.PopulationSize.Value    = 20;
            ss.ReferenceSetSize.Value  = 10;
            ss.Seed.Value = 0;
            return(ss);

            #endregion
        }
Beispiel #12
0
        private void bwVehicleRouting_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = (BackgroundWorker)sender;

            algorithmStatus.Text = "Press ESC to cancel";

            VehicleRoutingProblem  problem       = new VehicleRoutingProblem(routingCustomers, routingVehicles);
            VehicleRoutingSolution startSolution = new VehicleRoutingSolution(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           = "VEHICLE LD",
                Seed           = seed,
                DetailedOutput = true,
                Operators      = operations
            };

            SimulatedAnnealingParameters saParameters = new SimulatedAnnealingParameters()
            {
                Name               = "VEHICLE SA",
                InitProbability    = 0.4,
                TemperatureCooling = 0.95,
                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.002;
                saParameters.MinCostDeviation              = 10E-2;
                multistartParameters.Parameters            = ssParameters;
                multistartParameters.OptimizationAlgorithm = typeof(StackedSearch);
            }
            break;

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

            vehicleRoutingOptimizer = new ParallelMultistart(multistartParameters);

            toRenderBackground = false;

            foreach (ISolution solution in vehicleRoutingOptimizer.Minimize(startSolution))
            {
                if (worker.CancellationPending)
                {
                    vehicleRoutingOptimizer.Stop();
                    e.Cancel = true;
                }
                if (e.Cancel)
                {
                    solution.IsFinal = false;
                }
                worker.ReportProgress(0);
            }
        }
Beispiel #13
0
        private void ParameterizeProblem(VehicleRoutingProblem problem)
        {
            //set all parameters of the problem, e.g.

            //problem.MaximizationParameter = false;
        }
 protected GamsSolverWrapper(VehicleRoutingProblem <TClient> problemData)
     : this(problemData, @"C:\Program Files (x86)\GAMS22.2\gams.exe")
 {
 }
 protected GamsSolverWrapper(VehicleRoutingProblem <TClient> problemData, string gamsSolverPath)
 {
     ProblemData    = problemData;
     GamsSolverPath = gamsSolverPath;
 }
        static void Main(string[] args)
        {
            //VehicleRoutingProblem vrProblem = new VehicleRoutingProblem(4, 2);
            //VehicleRoutingSolution vrSolution = new VehicleRoutingSolution(vrProblem);

            //Console.WriteLine(vrSolution.ToString());
            //Console.WriteLine(vrSolution.CostValue);
            //Console.ReadLine();

            //return;


            //FloorplanProblem problem = new FloorplanProblem(100);
            //FloorplanProblem problem = FloorplanProblem.Load("500.vlsi");
            //FloorplanSolution solution = new FloorplanSolution(problem);
            //Swap swap = new Swap(problem.Dimension, 10);
            //Shift shift = new Shift(problem.Dimension, 1);
            //EmptyLeafMove eLeaf = new EmptyLeafMove(problem.Dimension, 5);
            //FullLeafMove fLeaf = new FullLeafMove(problem.Dimension, 5);
            //FullNodeMove fnode = new FullNodeMove(problem.Dimension, 5);
            //List<Operator> operations = new List<Operator> { swap, fLeaf };



            //TspProblem problem = new TspProblem(200);
            //TspSolution solution = new TspSolution(problem);

            VehicleRoutingProblem  problem  = new VehicleRoutingProblem(225, 10);
            VehicleRoutingSolution solution = new VehicleRoutingSolution(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()
            {
                Name            = "P",
                InstancesNumber = 5,
                RandomizeStart  = false,
                DetailedOutput  = true,
                OutputFrequency = 100,
            };

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

            SimulatedAnnealingParameters saParameters = new SimulatedAnnealingParameters()
            {
                Name                    = "SA",
                InitProbability         = 0.5,
                TemperatureCooling      = 0.98,
                MinCostDeviation        = 0,
                UseWeightedNeighborhood = false,
                DetailedOutput          = false,
                Seed                    = 0,
                Operators               = operations,
            };

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

            pldParameters.OptimizationAlgorithm = typeof(LocalDescent);
            pldParameters.Parameters            = ldParameters;

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

            psaParameters.OptimizationAlgorithm = typeof(SimulatedAnnealing);
            psaParameters.Parameters            = saParameters;

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

            StackedParameters sspParameters = new StackedParameters()
            {
                Name                   = "B",
                DetailedOutput         = false,
                OptimizationAlgorithms = new Type[] { typeof(LocalDescent), typeof(ParallelMultistart), typeof(LocalDescent) },
                Parameters             = new OptimizationParameters[] { ldParameters, psaParameters, ldParameters }
            };



            LocalDescent       ld  = new LocalDescent(ldParameters);
            SimulatedAnnealing sa  = new SimulatedAnnealing(saParameters);
            ParallelMultistart pld = new ParallelMultistart(pldParameters);
            ParallelMultistart psa = new ParallelMultistart(psaParameters);

            StackedSearch ss  = new StackedSearch(ssParameters);
            StackedSearch ssp = new StackedSearch(sspParameters);


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

            pssParameters.DetailedOutput        = false;
            pssParameters.RandomizeStart        = true;
            pssParameters.OptimizationAlgorithm = typeof(StackedSearch);
            pssParameters.Parameters            = ssParameters;

            ParallelMultistart pss = new ParallelMultistart(pssParameters);

            IOptimizationAlgorithm optimizer = sa;
            ISolution bestSolution           = solution;

            foreach (ISolution s in optimizer.Minimize(solution.Shuffle(0)))
            {
                //if (s.IsCurrentBest)
                Console.WriteLine("\t{0}, {1:f}s, {2}, {3}, {4}, {5}, {6}", s.CostValue, s.TimeInSeconds, s.IterationNumber, s.IsCurrentBest, s.IsFinal, bestSolution.CostValue - s.CostValue, s.InstanceTag);
                bestSolution = s;
            }

            Console.WriteLine(bestSolution.TimeInSeconds + "s");
            Console.WriteLine(bestSolution.IterationNumber + " iterations");

            //var groups = optimizer.SearchHistory.GroupBy(s => s.OperatorTag).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");


            foreach (var b in DrawSolution(bestSolution, optimizer))
            {
                b?.Save("solution" + DateTime.Now.Millisecond + ".jpg");
            }

            Console.ReadLine();
        }