void Initial_solution::do_while_foo(int kind) { invariant(); pgassert(kind > 0 && kind < 7); msg.log << "\nInitial_solution::do_while_foo\n"; Identifiers<size_t> notused; #if 0 bool out_of_trucks(true); #endif while (!unassigned.empty()) { msg.log << unassigned.size() << " unassigned: " << unassigned << "\n"; msg.log << assigned.size() << " assigned:" << assigned << "\n"; auto current = unassigned.size(); #if 0 auto truck = out_of_trucks? trucks.get_truck(unassigned.front()) : trucks.get_truck(); #else auto truck = trucks.get_truck(unassigned.front()); #endif msg.log << "got truck:" << truck.tau() << "\n"; /* * kind 1 to 7 work with the same code structure */ truck.do_while_feasable(kind, unassigned, assigned); msg.log << unassigned.size() << " unassigned: " << unassigned << "\n"; msg.log << assigned.size() << " assigned:" << assigned << "\n"; msg.log << "current" << current << " unassigned: " << unassigned.size(); pgassertwm(current > unassigned.size(), msg.get_log().c_str()); #if 0 if (truck.orders_in_vehicle().empty()) { out_of_trucks = notused.has(truck.idx()); if (out_of_trucks) { for (auto t : notused) { trucks.release_truck(t); } } notused += truck.idx(); continue; } #endif fleet.push_back(truck); invariant(); } pgassertwm(true, msg.get_log().c_str()); pgassert(is_feasable()); invariant(); }
/* * from_truck trying to make from_truck's duration smaller * - maybe all orders can be moved * - if that is the case, the from_truck could be removed * * Deleting an order on the from_truck * - number of truck remains the same * - from_truk duration() can not get larger * - the overall duration can get larger * */ bool Optimize::move_reduce_cost(size_t from_pos, size_t to_pos) { pgassert(to_pos < from_pos); auto from_truck = fleet[from_pos]; auto to_truck = fleet[to_pos]; auto moved(false); auto orders(from_truck.orders_in_vehicle); while (!orders.empty()) { /* * get the order that decreases the duration the most * (there is always a worse) */ auto order = from_truck.get_worse_order(orders); orders.erase(order.id()); /* * insert it in the next truck */ to_truck.insert(order); if (to_truck.is_feasable()) { problem->log << "\n Move order " << order.id() << " from truck " << from_truck.id() << " to truck " << to_truck.id(); #ifndef NDEBUG problem->dbg_log << "\nMove before:"; problem->dbg_log << "\n" << fleet[to_pos].tau(); problem->dbg_log << "\n" << fleet[from_pos].tau(); #endif from_truck.erase(order); move_order(order, fleet[from_pos], fleet[to_pos]); moved = true; save_if_best(); #ifndef NDEBUG problem->dbg_log << "\nMove after:"; problem->dbg_log << "\n" << fleet[to_pos].tau(); problem->dbg_log << "\n" << fleet[from_pos].tau(); #endif } } return moved; }
bool Optimize::swap_worse(size_t from_pos, size_t to_pos) { pgassert(to_pos < from_pos); auto from_truck = fleet[from_pos]; auto to_truck = fleet[to_pos]; auto swapped(false); auto from_orders(from_truck.orders_in_vehicle); auto to_orders(to_truck.orders_in_vehicle); auto local_limit(from_orders.size() * to_orders.size() + 1); while (!from_orders.empty() && --local_limit > 0) { auto from_order(from_truck.get_worse_order(from_orders)); from_orders.erase(from_order.id()); while (!to_orders.empty()) { auto to_order(to_truck.get_worse_order(to_orders)); to_orders.erase(to_order.id()); /* * delete from_order, and to order from their trucks */ auto curr_from_duration(from_truck.duration()); auto curr_to_duration(to_truck.duration()); from_truck.erase(from_order); to_truck.erase(to_order); /* * insert them in the other truck */ from_truck.insert(to_order); to_truck.insert(from_order); if (from_truck.is_feasable() && to_truck.is_feasable()) { /* * Can swap but: * - only swap when the total duration is reduced * - or from_truck duration is reduced */ if (((from_truck.duration() + to_truck.duration()) < (curr_from_duration + curr_to_duration)) || (from_truck.duration() < curr_from_duration)) { problem->log << "\n Swap order " << from_order.id() << " from truck " << from_truck.id() << " with order " << to_order.id() << " of truck " << to_truck.id(); #ifndef NDEBUG problem->dbg_log << "\nswappping before:"; problem->dbg_log << "\n" << fleet[to_pos].tau(); problem->dbg_log << "\n" << fleet[from_pos].tau(); #endif swap_order(from_order, fleet[from_pos], to_order, fleet[to_pos]); swapped = true; save_if_best(); from_orders.insert(to_order.id()); #ifndef NDEBUG problem->dbg_log << "\nswappping after:"; problem->dbg_log << "\n" << fleet[to_pos].tau(); problem->dbg_log << "\n" << fleet[from_pos].tau(); #endif break; } } /* * wasn't swapped */ to_truck = fleet[to_pos]; from_truck = fleet[from_pos]; } } return swapped; }
void Vehicle_pickDeliver::insert(const Order &order) { invariant(); pgassert(!has_order(order)); auto pick_pos(position_limits(order.pickup())); auto deliver_pos(position_limits(order.delivery())); #ifndef NDEBUG std::ostringstream err_log; err_log << "\n\tpickup limits (low, high) = (" << pick_pos.first << ", " << pick_pos.second << ") " << "\n\tdeliver limits (low, high) = (" << deliver_pos.first << ", " << deliver_pos.second << ") " << "\noriginal" << tau(); #endif if (pick_pos.second < pick_pos.first) { /* pickup generates twv evrywhere, * so put the order as last */ push_back(order); return; } if (deliver_pos.second < deliver_pos.first) { /* delivery generates twv evrywhere, * so put the order as last */ push_back(order); return; } /* * Because delivery positions were estimated without * the pickup: * - increase the upper limit position estimation */ ++deliver_pos.second; auto d_pos_backup(deliver_pos); auto best_pick_pos = m_path.size(); auto best_deliver_pos = m_path.size() + 1; auto current_duration(duration()); auto min_delta_duration = (std::numeric_limits<double>::max)(); auto found(false); pgassertwm(!has_order(order), err_log.str()); while (pick_pos.first <= pick_pos.second) { #ifndef NDEBUG err_log << "\n\tpickup cycle limits (low, high) = (" << pick_pos.first << ", " << pick_pos.second << ") "; #endif Vehicle::insert(pick_pos.first, order.pickup()); #ifndef NDEBUG err_log << "\npickup inserted: " << tau(); #endif while (deliver_pos.first <= deliver_pos.second) { Vehicle::insert(deliver_pos.first, order.delivery()); orders_in_vehicle.insert(order.id()); pgassertwm(has_order(order), err_log.str()); #ifndef NDEBUG err_log << "\ndelivery inserted: " << tau(); #endif if (is_feasable()) { pgassert(is_feasable()); auto delta_duration = duration()-current_duration; if (delta_duration < min_delta_duration) { #ifndef NDEBUG err_log << "\nsuccess" << tau(); #endif min_delta_duration = delta_duration; best_pick_pos = pick_pos.first; best_deliver_pos = deliver_pos.first; found = true; } } Vehicle::erase(deliver_pos.first); #ifndef NDEBUG err_log << "\ndelivery erased: " << tau(); #endif ++deliver_pos.first; } Vehicle::erase(pick_pos.first); #ifndef NDEBUG err_log << "\npickup erased: " << tau(); #endif orders_in_vehicle.erase(order.id()); pgassertwm(!has_order(order), err_log.str()); deliver_pos = d_pos_backup; #ifndef NDEBUG err_log << "\n\trestoring deliver limits (low, high) = (" << deliver_pos.first << ", " << deliver_pos.second << ") "; #endif ++pick_pos.first; } pgassertwm(!has_order(order), err_log.str()); if (!found) { /* order causes twv * so put the order as last */ push_back(order); return; } Vehicle::insert(best_pick_pos, order.pickup()); Vehicle::insert(best_deliver_pos, order.delivery()); orders_in_vehicle.insert(order.id()); pgassertwm(is_feasable(), err_log.str()); pgassertwm(has_order(order), err_log.str()); pgassertwm(!has_cv(), err_log.str()); invariant(); }
/* * from_truck trying to make from_truck's duration smaller * - maybe all orders can be moved * - if that is the case, the from_truck could be removed * * Deleting an order on the from_truck * - number of truck remains the same * - from_truk duration() can not get larger * - the overall duration can get larger * */ bool Optimize::move_reduce_cost( Vehicle_pickDeliver &from, Vehicle_pickDeliver &to) { auto from_truck = from; auto to_truck = to; /* * don't move from a real truck to a phoney truck */ if (!from_truck.is_phony() && to_truck.is_phony()) { return false; } #if 0 from.id() > to.id() ? to : from; #endif size_t from_pos = 0; size_t to_pos = 0; for (; from_pos < fleet.size() && fleet[from_pos].idx() != from_truck.idx() ; ++from_pos) { } pgassert(from_pos < fleet.size()); for (; to_pos < fleet.size() && fleet[to_pos].idx() != to_truck.idx() ; ++to_pos) { } pgassert(to_pos < fleet.size()); auto moved = false; auto from_orders = from_truck.orders_in_vehicle(); while (!from_orders.empty()) { /* * removing an order decreases the duration */ auto order = from_truck.orders()[from_orders.front()]; from_orders -= order.idx(); /* * insert it in the "to" truck */ to_truck.insert(order); if (to_truck.is_feasable()) { msg.log << "\n Move order " << order.pickup().id() << " from truck " << from_truck.idx() << " to truck " << to_truck.idx(); #ifndef NDEBUG msg.dbg_log << "\nMove before:"; msg.dbg_log << "\n" << fleet[to_pos].tau(); msg.dbg_log << "\n" << fleet[from_pos].tau(); #endif #if 1 from_truck.erase(order); #else to_truck.insert(order); move_order(order, fleet[from_pos], fleet[to_pos]); #endif moved = true; save_if_best(); #ifndef NDEBUG msg.dbg_log << "\nMove after:"; msg.dbg_log << "\n" << fleet[to_pos].tau(); msg.dbg_log << "\n" << fleet[from_pos].tau(); #endif } else { to_truck.erase(order); } } return moved; }
/* * .. to ... from .... */ bool Optimize::swap_worse(Vehicle_pickDeliver &to, Vehicle_pickDeliver &from) { #if 0 pgassert(from.orders_in_vehicle().size() <= to.orders_in_vehicle().size()); #endif auto from_truck = from; auto to_truck = to; auto swapped = false; #if 0 auto best_from_order = from_truck.orders_in_vehicle().front(); auto best_to_order = to_truck.orders_in_vehicle().front(); #endif for (auto from_orders = from_truck.orders_in_vehicle(); !from_orders.empty(); from_orders.pop_front()) { auto from_order = from_truck.orders()[from_orders.front()]; #if 0 pgassert(from_truck.has_order(from_order)); msg.log << "\n" << from_orders; msg.log << "\n from " << from_order.idx() << "," << from_order.pickup().original_id(); pgassert(from_truck.has_order(from_order)); #endif auto curr_from_duration = from_truck.duration(); pgassert(from_truck.has_order(from_order)); for (auto to_orders = to_truck.orders_in_vehicle(); !to_orders.empty(); to_orders.pop_front()) { pgassert(from_truck.has_order(from_order)); auto to_order = to.orders()[to_orders.front()]; #if 0 msg.log << "\n" << to_orders; msg.log << "\n To " << to_order.idx(); #endif auto curr_to_duration = to_truck.duration(); /* * delete from_order, and to order from their trucks */ #if 0 pgassert(from_truck.has_order(from_order)); msg.log << "\n" << from_truck.tau(); msg.log << "\n" << from_order.idx(); pgassert(from_truck.has_order(from_order)); #endif from_truck.erase(from_order); to_truck.erase(to_order); /* * insert them in the other truck */ from_truck.insert(to_order); to_truck.insert(from_order); if (from_truck.is_feasable() && to_truck.is_feasable()) { /* * Can swap but: * - only swap when the total duration is reduced * - or from_truck duration is reduced */ #if 0 msg.log << "\n Can swap"; msg.log << "\n Curr_from_duration " << curr_from_duration; msg.log << " Curr_to_duration " << curr_to_duration; msg.log << "\n new_from_duration " << from_truck.duration(); msg.log << " new_to_duration " << to_truck.duration(); #endif auto estimated_delta = - (curr_from_duration + curr_to_duration) + (to_truck.duration() + from_truck.duration()); #if 1 auto estimated_duration = duration() + estimated_delta; if (from_truck.duration() < curr_from_duration || estimated_delta < 0 || estimated_duration < best_solution.duration()) { #endif msg.log << "\n Found Swap order " << from_order.pickup().id() << " from truck " << from_truck.idx() << " with order " << to_order.pickup().id() << " of truck " << to_truck.idx(); swapped = true; #if 0 best_to_order = to_order.idx(); best_from_order = from_order.idx(); #endif p_swaps.push( Swap_info( from, to, from_order.idx(), to_order.idx(), estimated_delta)); #if 1 } #endif } to_truck = to; from_truck = from; } from_truck = from; } return false && swapped; }