/// <summary> /// Solves the problem. /// </summary> /// <returns></returns> protected override IRoute DoSolve(IProblem problem) { bool is_round; int first; if (problem.First.HasValue) { // the first customer is set. // test if the last customer is the same. if (problem.Last == problem.First) { // the route is a round. is_round = true; first = problem.First.Value; } else { // the route is not a round. is_round = false; first = problem.First.Value; } } else { // the first and last customer can be choosen randomly. is_round = false; first = -1; } // convert the problem to another problem with a virtual depot if needed. IProblem converted_problem; if (!is_round && first < 0) { // the end points can both vary. converted_problem = problem.AddVirtualDepot(); } else { // the problem does not need to be converted. converted_problem = problem; } // do the RAI. IRoute route = RandomizedArbitraryInsertionSolver.DoSolve(this, converted_problem, _route); // convert the route again if needed. if (!is_round && first < 0) { // the end points could both vary so a virtual one was added. Remove it again here. List <int> route_list = new List <int>(route); List <int> new_route_list = new List <int>(); for (int idx = 0; idx < route_list.Count; idx++) { // remove customer zero. if (route_list[idx] > 0) { new_route_list.Add(route_list[idx] - 1); } } route = DynamicAsymmetricRoute.CreateFrom(new_route_list, false); } return(route); }
/// <summary> /// Generates a random route. /// </summary> /// <param name="problem"></param> /// <returns></returns> public static IRoute DoSolveStatic(IProblem problem) { List <int> customers = new List <int>(); for (int customer = 0; customer < problem.Size; customer++) { customers.Add(customer); } customers.Shuffle <int>(); return(DynamicAsymmetricRoute.CreateFrom(customers)); }
/// <summary> /// Executes the solver. /// </summary> /// <param name="problem"></param> /// <returns></returns> public IRoute Solve(IProblem problem) { IProblem converted_problem = problem; bool first = problem.First.HasValue; bool last = problem.Last.HasValue; // convert the problem if needed. if (!first && !last) { // add a virtual customer with distance zero to all existing customers. double[][] new_weights = new double[problem.WeightMatrix.Length + 1][]; new_weights[0] = new double[problem.WeightMatrix.Length + 1]; for (int idx = 0; idx < problem.WeightMatrix.Length + 1; idx++) { new_weights[0][idx] = 0; } for (int idx = 0; idx < problem.WeightMatrix.Length; idx++) { new_weights[idx + 1] = new double[problem.WeightMatrix.Length + 1]; new_weights[idx + 1][0] = 0; problem.WeightMatrix[idx].CopyTo(new_weights[idx + 1], 1); } converted_problem = MatrixProblem.CreateATSP(new_weights, 0); } else if (!last) { // set all weights to the first customer to zero. for (int idx = 0; idx < problem.WeightMatrix.Length; idx++) { problem.WeightMatrix[idx][problem.First.Value] = 0; } converted_problem = MatrixProblem.CreateATSP(problem.WeightMatrix, problem.First.Value); } // execute the solver on the converted problem. IRoute converted_route = this.DoSolve(converted_problem); // convert the route back. if (!first && !last) { // when a virtual customer was added the route needs converting. List <int> customers_list = converted_route.ToList <int>(); customers_list.RemoveAt(0); for (int idx = 0; idx < customers_list.Count; idx++) { customers_list[idx] = customers_list[idx] - 1; } converted_route = DynamicAsymmetricRoute.CreateFrom(customers_list, false); } else if (!last) { // the returned route will return to customer zero; convert the route. converted_route = DynamicAsymmetricRoute.CreateFrom(converted_route, false); } return(converted_route); }
/// <summary> /// Returns a solution found using best-placement. /// </summary> /// <returns></returns> protected override IRoute DoSolve(OsmSharp.Math.TSP.Problems.IProblem problem) { // create the settings. SolverSettings settings = new SolverSettings( -1, -1, 1000000000, -1, -1, -1); Solver <List <int>, GeneticProblem, Fitness> solver = new Solver <List <int>, GeneticProblem, Fitness>( new GeneticProblem(problem), settings, null, null, null, _generation_operation, new FitnessCalculator(), true, false); Population <List <int>, GeneticProblem, Fitness> population = new Population <List <int>, GeneticProblem, Fitness>(true); while (population.Count < _population_size) { // generate new. Individual <List <int>, GeneticProblem, Fitness> new_individual = _generation_operation.Generate(solver); // add to population. population.Add(new_individual); } // select each individual once. Population <List <int>, GeneticProblem, Fitness> new_population = new Population <List <int>, GeneticProblem, Fitness>(true); Individual <List <int>, GeneticProblem, Fitness> best = null; int stagnation = 0; while (stagnation < _stagnation) { while (new_population.Count < _population_size) { // select an individual and the next one. int idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(population.Count); Individual <List <int>, GeneticProblem, Fitness> individual1 = population[idx]; Individual <List <int>, GeneticProblem, Fitness> individual2 = null; if (idx == population.Count - 1) { individual2 = population[0]; } else { individual2 = population[idx + 1]; } population.RemoveAt(idx); Individual <List <int>, GeneticProblem, Fitness> new_individual = _cross_over_operation.CrossOver(solver, individual1, individual2); new_individual.CalculateFitness(solver.Problem, solver.FitnessCalculator); if (new_individual.Fitness.CompareTo( individual1.Fitness) < 0) { new_population.Add(new_individual); } else { new_population.Add(individual1); } } population = new_population; population.Sort(solver, solver.FitnessCalculator); new_population = new Population <List <int>, GeneticProblem, Fitness>(true); if (best == null || best.Fitness.CompareTo(population[0].Fitness) > 0) { stagnation = 0; best = population[0]; } else { stagnation++; } // report progress. OsmSharp.Logging.Log.TraceEvent("EdgeAssemblyCrossOverSolver", Logging.TraceEventType.Information, string.Format("Solving using EAX: Stagnation {0}.", stagnation)); } var result = new List <int>(best.Genomes); result.Insert(0, 0); return(DynamicAsymmetricRoute.CreateFrom(result)); }
/// <summary> /// Returns a solution found using best-placement. /// </summary> /// <returns></returns> protected override IRoute DoSolve(IProblem problem) { // build the customer list to place. List<int> customers = null; if (_customers != null) { // copy the list of the given customers and keep this order. customers = new List<int>(_customers); } else { // generate some random route. customers = new List<int>(); List<int> customers_to_place = new List<int>(); for (int customer = 0; customer < problem.Size; customer++) { customers_to_place.Add(customer); } while (customers_to_place.Count > 0) { int idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customers_to_place.Count); customers.Add(customers_to_place[idx]); customers_to_place.RemoveAt(idx); } } // initialize the route based on the problem definition. IRoute route = null; double weight = double.MaxValue; if (problem.Symmetric) { // create a symmetric route that is dynamic and can accept new customers. if (problem.First.HasValue && problem.Last.HasValue && problem.First == problem.Last) { // route is a round. route = new DynamicSymmetricRoute(problem.First.Value); } else { // not a round. throw new NotImplementedException("No symmetric routes implemented that are not rounds!"); } } else { // create a asymmetric route that is dynamic and can accept new customers. if (problem.First.HasValue) { // the first customer is set. // test if the last customer is the same. if (!problem.Last.HasValue || problem.Last == problem.First) { // the route is a round. route = new DynamicAsymmetricRoute(customers.Count, problem.First.Value, true); // remove the first customer. customers.Remove(problem.First.Value); // find the customer that is farthest away and add it. int to = -1; weight = double.MinValue; for (int x = 0; x < customers.Count; x++) { if (x != problem.First.Value) { // only different customers. double current_weight = problem.WeightMatrix[x][problem.First.Value] + problem.WeightMatrix[problem.First.Value][x]; if (current_weight > weight) { // the current weight is better. to = x; weight = current_weight; } } } route.InsertAfter(problem.First.Value, to); customers.Remove(to); } else { // the route is not a round. route = new DynamicAsymmetricRoute(customers.Count, problem.First.Value, false); route.InsertAfter(problem.First.Value, problem.Last.Value); // remove the first customer. customers.Remove(problem.First.Value); customers.Remove(problem.Last.Value); } } else { // the first and last customer can be choosen randomly. // find two customers close together. int from = -1; int to = -1; for (int x = 0; x < customers.Count; x++) { for (int y = 0; y < customers.Count; y++) { if (x != y) { // only different customers. double current_weight = problem.WeightMatrix[x][y]; if (current_weight < weight) { // the current weight is better. from = x; to = y; weight = current_weight; if (weight == 0) { // no edge with less weight is going to be found. break; } } } } } route = new DynamicAsymmetricRoute(customers.Count, from, false); route.InsertAfter(from, to); // remove the first customer. customers.Remove(from); customers.Remove(to); } } // insert the rest of the customers. while (customers.Count > 0 && !_stopped) { // keep placing customer 0 until all customers are placed. int customer = customers[0]; customers.RemoveAt(0); // insert the customer at the best place. double difference; ArbitraryInsertionSolver.InsertOne(problem, route, customer, out difference); } return route; }
/// <summary> /// Returns a solution found using best-placement. /// </summary> /// <returns></returns> protected override IRoute DoSolve(IProblem problem) { // build the customer list to place. List <int> customers = null; if (_customers != null) { // copy the list of the given customers and keep this order. customers = new List <int>(_customers); } else { // generate some random route. customers = new List <int>(); List <int> customers_to_place = new List <int>(); for (int customer = 0; customer < problem.Size; customer++) { customers_to_place.Add(customer); } while (customers_to_place.Count > 0) { int idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customers_to_place.Count); customers.Add(customers_to_place[idx]); customers_to_place.RemoveAt(idx); } } // initialize the route based on the problem definition. IRoute route = null; double weight = double.MaxValue; if (problem.Symmetric) { // create a symmetric route that is dynamic and can accept new customers. if (problem.First.HasValue && problem.Last.HasValue && problem.First == problem.Last) { // route is a round. route = new DynamicSymmetricRoute(problem.First.Value); } else { // not a round. throw new NotImplementedException("No symmetric routes implemented that are not rounds!"); } } else { // create a asymmetric route that is dynamic and can accept new customers. if (problem.First.HasValue) { // the first customer is set. // test if the last customer is the same. if (!problem.Last.HasValue || problem.Last == problem.First) { // the route is a round. route = new DynamicAsymmetricRoute(customers.Count, problem.First.Value, true); // remove the first customer. customers.Remove(problem.First.Value); // find the customer that is farthest away and add it. int to = -1; weight = double.MinValue; for (int x = 0; x < customers.Count; x++) { if (x != problem.First.Value) { // only different customers. double current_weight = problem.WeightMatrix[x][problem.First.Value] + problem.WeightMatrix[problem.First.Value][x]; if (current_weight > weight) { // the current weight is better. to = x; weight = current_weight; } } } route.InsertAfter(problem.First.Value, to); customers.Remove(to); } else { // the route is not a round. route = new DynamicAsymmetricRoute(customers.Count, problem.First.Value, false); route.InsertAfter(problem.First.Value, problem.Last.Value); // remove the first customer. customers.Remove(problem.First.Value); customers.Remove(problem.Last.Value); } } else { // the first and last customer can be choosen randomly. // find two customers close together. int from = -1; int to = -1; for (int x = 0; x < customers.Count; x++) { for (int y = 0; y < customers.Count; y++) { if (x != y) { // only different customers. double current_weight = problem.WeightMatrix[x][y]; if (current_weight < weight) { // the current weight is better. from = x; to = y; weight = current_weight; if (weight == 0) { // no edge with less weight is going to be found. break; } } } } } route = new DynamicAsymmetricRoute(customers.Count, from, false); route.InsertAfter(from, to); // remove the first customer. customers.Remove(from); customers.Remove(to); } } // insert the rest of the customers. while (customers.Count > 0 && !_stopped) { // keep placing customer 0 until all customers are placed. int customer = customers[0]; customers.RemoveAt(0); // insert the customer at the best place. double difference; ArbitraryInsertionSolver.InsertOne(problem, route, customer, out difference); } return(route); }
/// <summary> /// Executes the RAI. /// </summary> /// <param name="problem"></param> /// <param name="solver"></param> /// <param name="initial_route"></param> /// <returns></returns> private static IRoute DoSolve(RandomizedArbitraryInsertionSolver solver, IProblem problem, IRoute initial_route) { // initialize a route using best-placement. DynamicAsymmetricRoute route = null; if (initial_route == null) { OsmSharp.Math.TSP.ArbitraryInsertion.ArbitraryInsertionSolver ai_solver = new OsmSharp.Math.TSP.ArbitraryInsertion.ArbitraryInsertionSolver(); initial_route = ai_solver.Solve(problem); } // get/create the dynamic route. if (initial_route is DynamicAsymmetricRoute) { // initial route is already the correct type. route = initial_route as DynamicAsymmetricRoute; } else { // convert the initial route to a route of the correct type. route = DynamicAsymmetricRoute.CreateFrom(initial_route); } // do the Arbitrary Insertion. double weight = route.CalculateWeight(problem); int try_count = 0; while (try_count < (route.Count * route.Count)) { // keep trying for a given number of times. int factor = 2; // cut out a part. int i = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate((route.Count / factor) - 1) + 1; int j = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate((route.Count / factor) - 1) + 1; while (i == j) { j = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate((route.Count / factor) - 1) + 1; } if (i > j) { int k = j; j = i; i = k; } // cut out the i->j part. int length = j - i; if (length > 0) { // cut and remove. DynamicAsymmetricRoute.CutResult cut_result = route.CutAndRemove( problem, weight, i, length); // calculate the weight that was removed. double new_weight = cut_result.Weight; List <int> cut_part = cut_result.CutPart; DynamicAsymmetricRoute cut_route = cut_result.Route; // use best placement to re-insert. int c = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(cut_part.Count); while (cut_part.Count > 0) { // loop until it's empty. int customer = cut_part[c]; cut_part.RemoveAt(c); // calculate the best placement. CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement( problem, cut_route, customer); //cut_route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter); cut_route.InsertAfter(result.CustomerBefore, result.Customer); new_weight = new_weight + result.Increase; // choose next random customer. c = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(cut_part.Count); } // descide to keep new route or not. if (weight > new_weight) { route = cut_route; weight = new_weight; //if (this.CanRaiseIntermidiateResult()) //{ // this.RaiseIntermidiateResult(route.ToArray<int>(), weight); //} } } // increase the try count. try_count++; } if (solver != null && solver.CanRaiseIntermidiateResult()) { solver.RaiseIntermidiateResult(route.ToArray <int>()); } return(route); }