pub struct ListCheapestInsertionPhase<S, E>{ /* private fields */ }Expand description
List construction phase using greedy cheapest insertion.
For each unassigned element (in index order), evaluates all possible insertion positions across all entities and inserts it at the position that yields the best score. This is significantly better than round-robin for VRP because:
- Routes are built incrementally with score feedback
- Capacity constraints influence which vehicle receives each visit
- Distance/duration constraints are optimized at the point of insertion
§Algorithm
for each unassigned element e:
for each entity r and each position p in r:
try insert(e, r, p), score, undo
permanently insert e at (r*, p*) with best scoreComplexity: O(E × N × M) where E = elements, N = entities, M = avg route length.
§Example
use solverforge_solver::ListCheapestInsertionPhase;
use solverforge_core::domain::PlanningSolution;
use solverforge_core::score::SoftScore;
#[derive(Clone)]
struct Vehicle { visits: Vec<usize> }
#[derive(Clone)]
struct Plan { vehicles: Vec<Vehicle>, n_visits: usize, score: Option<SoftScore> }
impl PlanningSolution for Plan {
type Score = SoftScore;
fn score(&self) -> Option<Self::Score> { self.score }
fn set_score(&mut self, score: Option<Self::Score>) { self.score = score; }
}
fn list_len(s: &Plan, e: usize) -> usize {
s.vehicles.get(e).map_or(0, |v| v.visits.len())
}
fn list_insert(s: &mut Plan, e: usize, pos: usize, val: usize) {
if let Some(v) = s.vehicles.get_mut(e) { v.visits.insert(pos, val); }
}
fn list_remove(s: &mut Plan, e: usize, pos: usize) -> usize {
s.vehicles.get_mut(e).map(|v| v.visits.remove(pos)).unwrap_or(0)
}
let phase = ListCheapestInsertionPhase::<Plan, usize>::new(
|p| p.n_visits,
|p| p.vehicles.iter().flat_map(|v| v.visits.iter().copied()).collect(),
|p| p.vehicles.len(),
list_len,
list_insert,
list_remove,
|_plan, idx| idx,
0,
);Implementations§
Source§impl<S, E> ListCheapestInsertionPhase<S, E>
impl<S, E> ListCheapestInsertionPhase<S, E>
pub fn new( element_count: fn(&S) -> usize, get_assigned: fn(&S) -> Vec<E>, entity_count: fn(&S) -> usize, list_len: fn(&S, usize) -> usize, list_insert: fn(&mut S, usize, usize, E), list_remove: fn(&mut S, usize, usize) -> E, index_to_element: fn(&S, usize) -> E, descriptor_index: usize, ) -> Self
Trait Implementations§
Source§impl<S, E> Debug for ListCheapestInsertionPhase<S, E>
impl<S, E> Debug for ListCheapestInsertionPhase<S, E>
Source§impl<S, E, D, BestCb> Phase<S, D, BestCb> for ListCheapestInsertionPhase<S, E>where
S: PlanningSolution,
E: Copy + PartialEq + Eq + Hash + Send + Sync + 'static,
D: Director<S>,
BestCb: BestSolutionCallback<S>,
impl<S, E, D, BestCb> Phase<S, D, BestCb> for ListCheapestInsertionPhase<S, E>where
S: PlanningSolution,
E: Copy + PartialEq + Eq + Hash + Send + Sync + 'static,
D: Director<S>,
BestCb: BestSolutionCallback<S>,
fn solve(&mut self, solver_scope: &mut SolverScope<'_, S, D, BestCb>)
fn phase_type_name(&self) -> &'static str
Auto Trait Implementations§
impl<S, E> Freeze for ListCheapestInsertionPhase<S, E>
impl<S, E> RefUnwindSafe for ListCheapestInsertionPhase<S, E>
impl<S, E> Send for ListCheapestInsertionPhase<S, E>
impl<S, E> Sync for ListCheapestInsertionPhase<S, E>
impl<S, E> Unpin for ListCheapestInsertionPhase<S, E>
impl<S, E> UnsafeUnpin for ListCheapestInsertionPhase<S, E>
impl<S, E> UnwindSafe for ListCheapestInsertionPhase<S, E>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more