///|
/// Controls deterministic neighborhood improvement after construction or ALNS.
pub struct LocalSearchConfig {
max_rounds : Int
use_two_opt : Bool
use_relocate : Bool
use_swap : Bool
use_reverse : Bool
} derive(Debug, ToJson)
///|
pub fn LocalSearchConfig::default() -> LocalSearchConfig {
{
max_rounds: 1,
use_two_opt: true,
use_relocate: true,
use_swap: true,
use_reverse: false,
}
}
///|
pub fn LocalSearchConfig::tune(
self : LocalSearchConfig,
max_rounds? : Int = self.max_rounds,
use_two_opt? : Bool = self.use_two_opt,
use_relocate? : Bool = self.use_relocate,
use_swap? : Bool = self.use_swap,
use_reverse? : Bool = self.use_reverse,
) -> LocalSearchConfig {
{ max_rounds, use_two_opt, use_relocate, use_swap, use_reverse }
}
///|
pub fn LocalSearchConfig::max_rounds(self : LocalSearchConfig) -> Int {
self.max_rounds
}
///|
pub fn LocalSearchConfig::uses_two_opt(self : LocalSearchConfig) -> Bool {
self.use_two_opt
}
///|
pub fn LocalSearchConfig::uses_relocate(self : LocalSearchConfig) -> Bool {
self.use_relocate
}
///|
pub fn LocalSearchConfig::uses_swap(self : LocalSearchConfig) -> Bool {
self.use_swap
}
///|
pub fn LocalSearchConfig::uses_reverse(self : LocalSearchConfig) -> Bool {
self.use_reverse
}
///|
fn local_search_pass(
instance : @core.VrpInstance,
solution : @core.Solution,
solve_config : @core.SolveConfig,
options : LocalSearchConfig,
) -> @core.Solution {
let mut current = solution
if options.use_two_opt {
current = @core.improve_with_two_opt(instance, current, solve_config)
}
if options.use_relocate {
current = @operators.best_relocate(instance, current, solve_config)
}
if options.use_swap {
current = @operators.best_swap(instance, current, solve_config)
}
if options.use_reverse {
current = @operators.best_reverse(instance, current, solve_config)
}
current
}
///|
/// Performs bounded deterministic improvement and never accepts a worse solution.
pub fn local_search(
instance : @core.VrpInstance,
solution : @core.Solution,
solve_config : @core.SolveConfig,
options : LocalSearchConfig,
) -> @core.Solution {
let mut current = solution
let rounds = options.max_rounds.max(0)
for _ in 0.. @operators.ImprovementReport {
let candidate = local_search(instance, solution, solve_config, options)
let start = solution.objective_value()
let finish = candidate.objective_value()
@operators.ImprovementReport::new(
candidate,
options.max_rounds.max(0),
if finish < start {
1
} else {
0
},
start,
finish,
)
}