Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RouteShift operator #799

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 108 additions & 48 deletions src/algorithms/local_search/local_search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ All rights reserved (see LICENSE).
#include "problems/vrptw/operators/relocate.h"
#include "problems/vrptw/operators/reverse_two_opt.h"
#include "problems/vrptw/operators/route_exchange.h"
#include "problems/vrptw/operators/route_shift.h"
#include "problems/vrptw/operators/swap_star.h"
#include "problems/vrptw/operators/two_opt.h"
#include "problems/vrptw/operators/unassigned_exchange.h"
Expand All @@ -46,7 +47,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
LocalSearch<Route,
UnassignedExchange,
SwapStar,
Expand All @@ -63,10 +65,11 @@ LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::LocalSearch(const Input& input,
std::vector<Route>& sol,
unsigned max_nb_jobs_removal,
const Timeout& timeout)
RouteExchange,
RouteShift>::LocalSearch(const Input& input,
std::vector<Route>& sol,
unsigned max_nb_jobs_removal,
const Timeout& timeout)
: _input(input),
_nb_vehicles(_input.vehicles.size()),
_max_nb_jobs_removal(max_nb_jobs_removal),
Expand Down Expand Up @@ -129,7 +132,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
void LocalSearch<Route,
UnassignedExchange,
SwapStar,
Expand All @@ -146,9 +150,10 @@ void LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::try_job_additions(const std::vector<Index>&
routes,
double regret_coeff) {
RouteExchange,
RouteShift>::try_job_additions(const std::vector<Index>&
routes,
double regret_coeff) {

bool job_added;

Expand Down Expand Up @@ -303,7 +308,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
void LocalSearch<Route,
UnassignedExchange,
SwapStar,
Expand All @@ -320,7 +326,8 @@ void LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::run_ls_step() {
RouteExchange,
RouteShift>::run_ls_step() {
// Store best move involving a pair of routes.
std::vector<std::vector<std::unique_ptr<Operator>>> best_ops(_nb_vehicles);
for (std::size_t v = 0; v < _nb_vehicles; ++v) {
Expand Down Expand Up @@ -930,6 +937,46 @@ void LocalSearch<Route,
}
}

// RouteShift stuff
for (const auto& s_t : s_t_pairs) {
if (s_t.first == s_t.second or best_priorities[s_t.first] > 0 or
best_priorities[s_t.second] > 0 or _sol[s_t.first].size() <= 2 or
_sol[s_t.second].empty() or
_sol_state.bwd_skill_rank[s_t.first][s_t.second] != 0) {
// Moving a (pair of) job is already taken care of in other
// operators. Moving to an empty route is a
// RouteExchange. Whole route should be transferable.
continue;
}

// TODO stop if homogeneous vehicles and target size under 3.

const auto& t_v = _input.vehicles[s_t.second];

if (_sol[s_t.first].size() + _sol[s_t.second].size() > t_v.max_tasks) {
continue;
}

// TODO handle vehicles/jobs compatibility and ranks restrictions.

#ifdef LOG_LS_OPERATORS
++tried_moves[OperatorName::RouteShift];
#endif
RouteShift r(_input,
_sol_state,
_sol[s_t.first],
s_t.first,
_sol[s_t.second],
s_t.second);

auto& current_best = best_gains[s_t.first][s_t.second];
if (r.gain_upper_bound() > current_best and r.is_valid() and
r.gain() > current_best) {
current_best = r.gain();
best_ops[s_t.first][s_t.second] = std::make_unique<RouteShift>(r);
}
}

if (_input.has_jobs()) {
// Move(s) that don't make sense for shipment-only instances.

Expand Down Expand Up @@ -1756,7 +1803,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
void LocalSearch<Route,
UnassignedExchange,
SwapStar,
Expand All @@ -1773,7 +1821,8 @@ void LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::run() {
RouteExchange,
RouteShift>::run() {
bool try_ls_step = true;
bool first_step = true;

Expand Down Expand Up @@ -1860,7 +1909,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
std::array<OperatorStats, OperatorName::MAX>
LocalSearch<Route,
UnassignedExchange,
Expand All @@ -1878,7 +1928,8 @@ LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::get_stats() const {
RouteExchange,
RouteShift>::get_stats() const {
std::array<OperatorStats, OperatorName::MAX> stats;
for (auto op = 0; op < OperatorName::MAX; ++op) {
stats[op] = OperatorStats(tried_moves.at(op), applied_moves.at(op));
Expand All @@ -1904,7 +1955,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
Eval LocalSearch<Route,
UnassignedExchange,
SwapStar,
Expand All @@ -1921,9 +1973,8 @@ Eval LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::job_route_cost(Index v_target,
Index v,
Index r) {
RouteExchange,
RouteShift>::job_route_cost(Index v_target, Index v, Index r) {
assert(v != v_target);

Eval eval(INFINITE_COST, 0);
Expand Down Expand Up @@ -1975,7 +2026,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
Eval LocalSearch<Route,
UnassignedExchange,
SwapStar,
Expand All @@ -1992,7 +2044,8 @@ Eval LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::relocate_cost_lower_bound(Index v, Index r) {
RouteExchange,
RouteShift>::relocate_cost_lower_bound(Index v, Index r) {
Eval best_bound(INFINITE_COST, 0);

for (std::size_t other_v = 0; other_v < _sol.size(); ++other_v) {
Expand Down Expand Up @@ -2023,7 +2076,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
Eval LocalSearch<Route,
UnassignedExchange,
SwapStar,
Expand All @@ -2040,9 +2094,10 @@ Eval LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::relocate_cost_lower_bound(Index v,
Index r1,
Index r2) {
RouteExchange,
RouteShift>::relocate_cost_lower_bound(Index v,
Index r1,
Index r2) {
Eval best_bound(INFINITE_COST, 0);

for (std::size_t other_v = 0; other_v < _sol.size(); ++other_v) {
Expand Down Expand Up @@ -2075,7 +2130,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
void LocalSearch<Route,
UnassignedExchange,
SwapStar,
Expand All @@ -2092,7 +2148,8 @@ void LocalSearch<Route,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::remove_from_routes() {
RouteExchange,
RouteShift>::remove_from_routes() {
// Store nearest job from and to any job in any route for constant
// time access down the line.
for (std::size_t v1 = 0; v1 < _nb_vehicles; ++v1) {
Expand Down Expand Up @@ -2223,25 +2280,26 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
utils::SolutionIndicators<Route>
LocalSearch<Route,
UnassignedExchange,
SwapStar,
CrossExchange,
MixedExchange,
TwoOpt,
ReverseTwoOpt,
Relocate,
OrOpt,
IntraExchange,
IntraCrossExchange,
IntraMixedExchange,
IntraRelocate,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange>::indicators() const {
class RouteExchange,
class RouteShift>
utils::SolutionIndicators<Route> LocalSearch<Route,
UnassignedExchange,
SwapStar,
CrossExchange,
MixedExchange,
TwoOpt,
ReverseTwoOpt,
Relocate,
OrOpt,
IntraExchange,
IntraCrossExchange,
IntraMixedExchange,
IntraRelocate,
IntraOrOpt,
IntraTwoOpt,
PDShift,
RouteExchange,
RouteShift>::indicators() const {
return _best_sol_indicators;
}

Expand All @@ -2261,7 +2319,8 @@ template class LocalSearch<TWRoute,
vrptw::IntraOrOpt,
vrptw::IntraTwoOpt,
vrptw::PDShift,
vrptw::RouteExchange>;
vrptw::RouteExchange,
vrptw::RouteShift>;

template class LocalSearch<RawRoute,
cvrp::UnassignedExchange,
Expand All @@ -2279,7 +2338,8 @@ template class LocalSearch<RawRoute,
cvrp::IntraOrOpt,
cvrp::IntraTwoOpt,
cvrp::PDShift,
cvrp::RouteExchange>;
cvrp::RouteExchange,
cvrp::RouteShift>;

} // namespace ls
} // namespace vroom
3 changes: 2 additions & 1 deletion src/algorithms/local_search/local_search.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ template <class Route,
class IntraOrOpt,
class IntraTwoOpt,
class PDShift,
class RouteExchange>
class RouteExchange,
class RouteShift>
class LocalSearch {
private:
const Input& _input;
Expand Down
4 changes: 3 additions & 1 deletion src/problems/cvrp/cvrp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ All rights reserved (see LICENSE).
#include "problems/cvrp/operators/relocate.h"
#include "problems/cvrp/operators/reverse_two_opt.h"
#include "problems/cvrp/operators/route_exchange.h"
#include "problems/cvrp/operators/route_shift.h"
#include "problems/cvrp/operators/swap_star.h"
#include "problems/cvrp/operators/two_opt.h"
#include "problems/cvrp/operators/unassigned_exchange.h"
Expand Down Expand Up @@ -54,7 +55,8 @@ using LocalSearch = ls::LocalSearch<RawRoute,
cvrp::IntraOrOpt,
cvrp::IntraTwoOpt,
cvrp::PDShift,
cvrp::RouteExchange>;
cvrp::RouteExchange,
cvrp::RouteShift>;
} // namespace cvrp

const std::vector<HeuristicParameters> CVRP::homogeneous_parameters =
Expand Down
Loading