/// <summary> /// Executes a solver procedure. /// </summary> /// <param name="problem"></param> /// <returns></returns> internal override MaxTimeSolution Solve(MaxTimeProblem problem) { MaxTimeCalculator calculator = new MaxTimeCalculator(problem); // get the seed customers. ICollection<int> seeds = _seed_selector.SelectSeeds( problem, _k); double[] weights = new double[seeds.Count]; // start the seed routes. List<int> selectable_customers = problem.Customers; MaxTimeSolution routes = new MaxTimeSolution( problem.Size, true); foreach (int seed in seeds) { routes.Add(seed); selectable_customers.Remove(seed); } if (!routes.IsValid()) { throw new Exception(); } // keep a list of cheapest insertions. IInsertionCosts costs = new BinaryHeapInsertionCosts(); // keep looping until all customers have been placed. while (selectable_customers.Count > 0) { // try and place into every route. CheapestInsertionResult best_result = new CheapestInsertionResult(); best_result.Increase = float.MaxValue; int best_route_idx = -1; CheapestInsertionResult best_result_above_max = new CheapestInsertionResult(); best_result_above_max.Increase = float.MaxValue; int best_route_above_max_idx = -1; for (int route_idx = 0; route_idx < routes.Count; route_idx++) { IRoute current_route = routes.Route(route_idx); // choose the next customer. CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, selectable_customers, costs); if (result.Customer == result.CustomerAfter) { throw new Exception(); } // get the current weight double weight = weights[route_idx]; if (result.Increase < best_result.Increase) { if (weight + result.Increase + calculator.DeliveryTime < problem.Max.Value) { // route will still be inside bounds. best_result = result; best_route_idx = route_idx; } else { // route will become above max. if (result.Increase < best_result_above_max.Increase) { best_result_above_max = result; best_route_above_max_idx = route_idx; } } } } // do the placement if a placement is found without max violation. // else do the placement in the above max route. CheapestInsertionResult placement_result = new CheapestInsertionResult(); placement_result.Increase = double.MaxValue; int placement_result_idx = -1; if (best_route_idx >= 0) { // best placement found. placement_result = best_result; placement_result_idx = best_route_idx; } else { // best placement found but only above max. placement_result = best_result_above_max; placement_result_idx = best_route_above_max_idx; } // do the actual placement. weights[placement_result_idx] = calculator.CalculateOneRouteIncrease( weights[placement_result_idx], placement_result.Increase); selectable_customers.Remove(placement_result.Customer); //routes.Route(placement_result_idx).InsertAfterAndRemove( // placement_result.CustomerBefore, placement_result.Customer, placement_result.CustomerAfter); routes.Route(placement_result_idx).InsertAfter( placement_result.CustomerBefore, placement_result.Customer); if (!routes.IsValid()) { throw new Exception(); } } return routes; }
internal override MaxTimeSolution Solve(MaxTimeProblem problem) { MaxTimeCalculator calculator = new MaxTimeCalculator( problem); // generate a ATSP solution. IRoute tsp_solution = _tsp_solution; if (tsp_solution == null) { tsp_solution = _tsp_solver.Solve(new TSPProblem(problem)); } // generate subtours from this solution. MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true); // select a random start point. int start = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(problem.Size); // start the first tour. int placed = 0; int previous = -1; // place the first customer. double weight = 0; double total_weight = 0; IRoute route = solution.Add(start); previous = start; while (placed < problem.Size) { // get the next customer from the tsp solution. int next = tsp_solution.GetNeigbours(previous)[0]; // get the weight to the current start. double weight_to_next = problem.WeightMatrix[previous][next]; double weight_to_start = problem.WeightMatrix[next][start]; total_weight = calculator.CalculateOneRouteIncrease( weight, weight_to_next + weight_to_start); weight = calculator.CalculateOneRouteIncrease( weight, weight_to_next); if (total_weight > problem.Max.Value) { // start a new route. route = solution.Add(next); weight = 0; } else { // just insert the next customer. route.InsertAfter(previous, next); //route.InsertAfterAndRemove(previous, next, -1); } // set the previous. previous = next; placed++; } if (!solution.IsValid()) { throw new Exception(); } StringBuilder builder = new StringBuilder(); builder.Append("["); total_weight = 0; for (int idx = 0; idx < solution.Count; idx++) { //IRoute route = routes.Route(idx); route = solution.Route(idx); weight = calculator.CalculateOneRoute(route); builder.Append(" "); builder.Append(weight); builder.Append(" "); total_weight = total_weight + weight; } builder.Append("]"); builder.Append(total_weight); builder.Append(": "); builder.Append(calculator.Calculate(solution)); Console.WriteLine(builder.ToString()); return(solution); }
/// <summary> /// Calculates a solution. /// </summary> /// <param name="problem"></param> /// <returns></returns> internal override MaxTimeSolution Solve(MaxTimeProblem problem) { // create the calculator. MaxTimeCalculator calculator = new MaxTimeCalculator(problem); // create the solution. MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true); double max = problem.Max.Value; // keep placing customer until none are left. List<int> customers = new List<int>(problem.Customers); // create n routes. for (int customer = 0; customer < customers.Count; customer++) { solution.Add(customer); solution[solution.Count - 1] = calculator.CalculateOneRouteIncrease( 0, 0); } // creates a result. MergeResult result = new MergeResult(); result.Weight = double.MaxValue; // loop over all route pairs and merge the smallest merge. while (result != null) { // keep looping until there is no result anymore. result = new MergeResult(); result.Weight = double.MaxValue; for (int route1_idx = 1; route1_idx < solution.Count; route1_idx++) { // keep looping over all routes. for (int route2_idx = 0; route2_idx < solution.Count; route2_idx++) { // keep looping over all routes. if (route1_idx == route2_idx) { // only consider different routes. break; } // calculate the merge result. MergeResult current_result = this.TryMerge(problem, solution, route1_idx, route2_idx, problem.Max.Value); // evaluate the current result. if (current_result != null && current_result.Weight < result.Weight) { // current result is best. result = current_result; } } } // evaluate the result. if (result.Weight < double.MaxValue) { // there is a result; apply it! IRoute source = solution.Route(result.RouteSourceId); IRoute target = solution.Route(result.RouteTargetId); //string source_string = source.ToString(); //string target_string = target.ToString(); if (target.Count > 1 && target.First == target.GetNeigbours(result.CustomerTargetSource)[0]) { //throw new Exception(); } // create an enumeration of all customers of source in the correct order. IEnumerable<int> source_between = new List<int>( source.Between(result.CustomerSourceSource, result.CustomerSourceTarget)); // insert after the complete source. int previous = result.CustomerTargetSource; int next = target.GetNeigbours(result.CustomerTargetSource)[0]; foreach (int source_customer in source_between) { // insert. target.ReplaceEdgeFrom(previous, source_customer); previous = source_customer; // update previous. } target.ReplaceEdgeFrom(previous, next); // remove the source route. solution.Remove(result.RouteSourceId); solution.RemoveWeight(result.RouteTargetId); // calculate the weight of the new route. solution[result.RouteTargetId] = solution[result.RouteTargetId] + result.Weight + solution[result.RouteSourceId]; if (!solution.IsValid()) { throw new Exception(); } } else { // set the result null. result = null; } } return solution; }
/// <summary> /// Executes a solver procedure. /// </summary> /// <param name="problem"></param> /// <returns></returns> internal override MaxTimeSolution Solve(MaxTimeProblem problem) { // create the calculator. MaxTimeCalculator calculator = new MaxTimeCalculator(problem); // create the solution. MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true); // keep placing customer until none are left. List <int> customers = new List <int>(problem.Customers); while (customers.Count > 0) { // select a customer using some heuristic. int customer_idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customers.Count); int customer = customers[customer_idx]; customers.Remove(customer); // start a route r. double current_route_weight = 0; IRoute current_route = solution.Add(customer); //Console.WriteLine("Starting new route with {0}", customer); while (customers.Count > 0) { // calculate the best placement. CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, customers); // calculate the new weight. double potential_weight = calculator.CalculateOneRouteIncrease(current_route_weight, result.Increase); // cram as many customers into one route as possible. if (potential_weight < problem.Max.Value) { // insert the customer, it is customers.Remove(result.Customer); //current_route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter); current_route.InsertAfter(result.CustomerBefore, result.Customer); current_route_weight = potential_weight; //// improve if needed. ////if (improvement_probalitity > OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(1)) //if (((problem.Size - customers.Count) % _k) == 0) //{ // an improvement is descided. // current_route_weight = this.ImproveIntraRoute(problem, // current_route, current_route_weight); //} } else {// ok we are done! //// apply the intra-route heuristics. //for (int route_idx = 0; route_idx < solution.Count - 1; route_idx++) //{ // apply the intra-route heurstic between the new and all existing routes. // this.ImproveInterRoute(problem, solution.Route(route_idx), current_route); //} //// apply the inter-route heuristics. //for (int route_idx = 0; route_idx < solution.Count; route_idx++) //{ // apply heurstic for each route. // IRoute route = solution.Route(route_idx); // this.ImproveIntraRoute(problem, current_route, current_route_weight); //} // break the route. break; } } } return(solution); }
/// <summary> /// Executes a solver procedure. /// </summary> /// <param name="problem"></param> /// <returns></returns> internal override MaxTimeSolution Solve(MaxTimeProblem problem) { // create the calculator. MaxTimeCalculator calculator = new MaxTimeCalculator(problem); // create the solution. MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true); // keep placing customer until none are left. List<int> customers = new List<int>(problem.Customers); while (customers.Count > 0) { // select a customer using some heuristic. int customer_idx = OsmSharp.Tools.Math.Random.StaticRandomGenerator.Get().Generate(customers.Count); int customer = customers[customer_idx]; customers.Remove(customer); // start a route r. double current_route_weight = 0; IRoute current_route = solution.Add(customer); //Console.WriteLine("Starting new route with {0}", customer); while (customers.Count > 0) { // calculate the best placement. CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, customers); // calculate the new weight. double potential_weight = calculator.CalculateOneRouteIncrease(current_route_weight, result.Increase); // cram as many customers into one route as possible. if (potential_weight < problem.Max.Value) { // insert the customer, it is customers.Remove(result.Customer); //current_route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter); current_route.InsertAfter(result.CustomerBefore, result.Customer); current_route_weight = potential_weight; //// improve if needed. ////if (improvement_probalitity > OsmSharp.Tools.Math.Random.StaticRandomGenerator.Get().Generate(1)) //if (((problem.Size - customers.Count) % _k) == 0) //{ // an improvement is descided. // current_route_weight = this.ImproveIntraRoute(problem, // current_route, current_route_weight); //} } else {// ok we are done! //// apply the intra-route heuristics. //for (int route_idx = 0; route_idx < solution.Count - 1; route_idx++) //{ // apply the intra-route heurstic between the new and all existing routes. // this.ImproveInterRoute(problem, solution.Route(route_idx), current_route); //} //// apply the inter-route heuristics. //for (int route_idx = 0; route_idx < solution.Count; route_idx++) //{ // apply heurstic for each route. // IRoute route = solution.Route(route_idx); // this.ImproveIntraRoute(problem, current_route, current_route_weight); //} // break the route. break; } } } return solution; }
internal override MaxTimeSolution Solve(MaxTimeProblem problem) { MaxTimeCalculator calculator = new MaxTimeCalculator( problem); // generate a ATSP solution. IRoute tsp_solution = _tsp_solution; if (tsp_solution == null) { tsp_solution = _tsp_solver.Solve(new TSPProblem(problem)); } // generate subtours from this solution. MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true); // select a random start point. int start = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(problem.Size); // start the first tour. int placed = 0; int previous = -1; // place the first customer. double weight = 0; double total_weight = 0; IRoute route = solution.Add(start); previous = start; while (placed < problem.Size) { // get the next customer from the tsp solution. int next = tsp_solution.GetNeigbours(previous)[0]; // get the weight to the current start. double weight_to_next = problem.WeightMatrix[previous][next]; double weight_to_start = problem.WeightMatrix[next][start]; total_weight = calculator.CalculateOneRouteIncrease( weight, weight_to_next + weight_to_start); weight = calculator.CalculateOneRouteIncrease( weight, weight_to_next); if (total_weight > problem.Max.Value) { // start a new route. route = solution.Add(next); weight = 0; } else { // just insert the next customer. route.InsertAfter(previous, next); //route.InsertAfterAndRemove(previous, next, -1); } // set the previous. previous = next; placed++; } if (!solution.IsValid()) { throw new Exception(); } StringBuilder builder = new StringBuilder(); builder.Append("["); total_weight = 0; for (int idx = 0; idx < solution.Count; idx++) { //IRoute route = routes.Route(idx); route = solution.Route(idx); weight = calculator.CalculateOneRoute(route); builder.Append(" "); builder.Append(weight); builder.Append(" "); total_weight = total_weight + weight; } builder.Append("]"); builder.Append(total_weight); builder.Append(": "); builder.Append(calculator.Calculate(solution)); OsmSharp.Logging.Log.TraceEvent("TSPPlacementSolver", TraceEventType.Information, builder.ToString()); return solution; }
/// <summary> /// Executes a solver procedure. /// </summary> /// <param name="problem"></param> /// <returns></returns> internal override MaxTimeSolution Solve(MaxTimeProblem problem) { MaxTimeCalculator calculator = new MaxTimeCalculator(problem); // get the seed customers. ICollection <int> seeds = _seed_selector.SelectSeeds( problem, _k); double[] weights = new double[seeds.Count]; // start the seed routes. List <int> selectable_customers = problem.Customers; MaxTimeSolution routes = new MaxTimeSolution( problem.Size, true); foreach (int seed in seeds) { routes.Add(seed); selectable_customers.Remove(seed); } if (!routes.IsValid()) { throw new Exception(); } // keep a list of cheapest insertions. IInsertionCosts costs = new BinaryHeapInsertionCosts(); // keep looping until all customers have been placed. while (selectable_customers.Count > 0) { // try and place into every route. CheapestInsertionResult best_result = new CheapestInsertionResult(); best_result.Increase = float.MaxValue; int best_route_idx = -1; CheapestInsertionResult best_result_above_max = new CheapestInsertionResult(); best_result_above_max.Increase = float.MaxValue; int best_route_above_max_idx = -1; for (int route_idx = 0; route_idx < routes.Count; route_idx++) { IRoute current_route = routes.Route(route_idx); // choose the next customer. CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, selectable_customers, costs); if (result.Customer == result.CustomerAfter) { throw new Exception(); } // get the current weight double weight = weights[route_idx]; if (result.Increase < best_result.Increase) { if (weight + result.Increase + calculator.DeliveryTime < problem.Max.Value) { // route will still be inside bounds. best_result = result; best_route_idx = route_idx; } else { // route will become above max. if (result.Increase < best_result_above_max.Increase) { best_result_above_max = result; best_route_above_max_idx = route_idx; } } } } // do the placement if a placement is found without max violation. // else do the placement in the above max route. CheapestInsertionResult placement_result = new CheapestInsertionResult(); placement_result.Increase = double.MaxValue; int placement_result_idx = -1; if (best_route_idx >= 0) { // best placement found. placement_result = best_result; placement_result_idx = best_route_idx; } else { // best placement found but only above max. placement_result = best_result_above_max; placement_result_idx = best_route_above_max_idx; } // do the actual placement. weights[placement_result_idx] = calculator.CalculateOneRouteIncrease( weights[placement_result_idx], placement_result.Increase); selectable_customers.Remove(placement_result.Customer); //routes.Route(placement_result_idx).InsertAfterAndRemove( // placement_result.CustomerBefore, placement_result.Customer, placement_result.CustomerAfter); routes.Route(placement_result_idx).InsertAfter( placement_result.CustomerBefore, placement_result.Customer); if (!routes.IsValid()) { throw new Exception(); } } return(routes); }
/// <summary> /// Calculates a solution. /// </summary> /// <param name="problem"></param> /// <returns></returns> internal override MaxTimeSolution Solve(MaxTimeProblem problem) { // create the calculator. MaxTimeCalculator calculator = new MaxTimeCalculator(problem); // create the solution. MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true); double max = problem.Max.Value; // keep placing customer until none are left. List <int> customers = new List <int>(problem.Customers); // create n routes. for (int customer = 0; customer < customers.Count; customer++) { solution.Add(customer); solution[solution.Count - 1] = calculator.CalculateOneRouteIncrease( 0, 0); } // creates a result. MergeResult result = new MergeResult(); result.Weight = double.MaxValue; // loop over all route pairs and merge the smallest merge. while (result != null) { // keep looping until there is no result anymore. result = new MergeResult(); result.Weight = double.MaxValue; for (int route1_idx = 1; route1_idx < solution.Count; route1_idx++) { // keep looping over all routes. for (int route2_idx = 0; route2_idx < solution.Count; route2_idx++) { // keep looping over all routes. if (route1_idx == route2_idx) { // only consider different routes. break; } // calculate the merge result. MergeResult current_result = this.TryMerge(problem, solution, route1_idx, route2_idx, problem.Max.Value); // evaluate the current result. if (current_result != null && current_result.Weight < result.Weight) { // current result is best. result = current_result; } } } // evaluate the result. if (result.Weight < double.MaxValue) { // there is a result; apply it! IRoute source = solution.Route(result.RouteSourceId); IRoute target = solution.Route(result.RouteTargetId); //string source_string = source.ToString(); //string target_string = target.ToString(); if (target.Count > 1 && target.First == target.GetNeigbours(result.CustomerTargetSource)[0]) { //throw new Exception(); } // create an enumeration of all customers of source in the correct order. IEnumerable <int> source_between = new List <int>( source.Between(result.CustomerSourceSource, result.CustomerSourceTarget)); // insert after the complete source. int previous = result.CustomerTargetSource; int next = target.GetNeigbours(result.CustomerTargetSource)[0]; foreach (int source_customer in source_between) { // insert. target.ReplaceEdgeFrom(previous, source_customer); previous = source_customer; // update previous. } target.ReplaceEdgeFrom(previous, next); // remove the source route. solution.Remove(result.RouteSourceId); solution.RemoveWeight(result.RouteTargetId); // calculate the weight of the new route. solution[result.RouteTargetId] = solution[result.RouteTargetId] + result.Weight + solution[result.RouteSourceId]; if (!solution.IsValid()) { throw new Exception(); } } else { // set the result null. result = null; } } return(solution); }