Skip to main content

Module sublist_change

Module sublist_change 

Source
Expand description

Sublist change move selector for segment relocation (Or-opt).

Generates SubListChangeMoves that relocate contiguous segments within or between list variables. The Or-opt family of moves (segments of size 1, 2, 3, …) is among the most effective VRP improvements after basic 2-opt.

§Complexity

For n entities with average route length m and max segment size k:

  • Intra-entity: O(n * m * k) sources × O(m) destinations
  • Inter-entity: O(n * m * k) sources × O(n * m) destinations
  • Total: O(n² * m² * k)

Use a forager that quits early (FirstAccepted, AcceptedCount) to keep iteration practical for large instances.

§Example

use solverforge_solver::heuristic::selector::sublist_change::SubListChangeMoveSelector;
use solverforge_solver::heuristic::selector::entity::FromSolutionEntitySelector;
use solverforge_solver::heuristic::selector::MoveSelector;
use solverforge_core::domain::PlanningSolution;
use solverforge_core::score::SimpleScore;

#[derive(Clone, Debug)]
struct Vehicle { visits: Vec<i32> }

#[derive(Clone, Debug)]
struct Solution { vehicles: Vec<Vehicle>, score: Option<SimpleScore> }

impl PlanningSolution for Solution {
    type Score = SimpleScore;
    fn score(&self) -> Option<Self::Score> { self.score }
    fn set_score(&mut self, score: Option<Self::Score>) { self.score = score; }
}

fn list_len(s: &Solution, entity_idx: usize) -> usize {
    s.vehicles.get(entity_idx).map_or(0, |v| v.visits.len())
}
fn sublist_remove(s: &mut Solution, entity_idx: usize, start: usize, end: usize) -> Vec<i32> {
    s.vehicles.get_mut(entity_idx)
        .map(|v| v.visits.drain(start..end).collect())
        .unwrap_or_default()
}
fn sublist_insert(s: &mut Solution, entity_idx: usize, pos: usize, items: Vec<i32>) {
    if let Some(v) = s.vehicles.get_mut(entity_idx) {
        for (i, item) in items.into_iter().enumerate() {
            v.visits.insert(pos + i, item);
        }
    }
}

// Or-opt: relocate segments of size 1..=3
let selector = SubListChangeMoveSelector::<Solution, i32, _>::new(
    FromSolutionEntitySelector::new(0),
    1, 3,
    list_len,
    sublist_remove,
    sublist_insert,
    "visits",
    0,
);

Structs§

ListMoveSubListChangeSelector
Wraps a SubListChangeMoveSelector to yield ListMoveImpl::SubListChange.
SubListChangeMoveSelector
A move selector that generates sublist change (Or-opt) moves.