pub trait ListVariableSolution: PlanningSolution {
type Element: Copy + Send + Sync;
// Required methods
fn entity_count(&self) -> usize;
fn list_len(&self, entity_idx: usize) -> usize;
fn list_get(&self, entity_idx: usize, position: usize) -> Self::Element;
fn list_push(&mut self, entity_idx: usize, elem: Self::Element);
fn list_insert(
&mut self,
entity_idx: usize,
position: usize,
elem: Self::Element,
);
fn list_remove(
&mut self,
entity_idx: usize,
position: usize,
) -> Self::Element;
fn list_reverse(&mut self, entity_idx: usize, start: usize, end: usize);
fn unassigned_elements(&self) -> Vec<Self::Element>;
}Expand description
Trait for solutions with list-based planning variables.
Used for problems like VRP where entities (vehicles) have ordered lists of elements (visits) that can be inserted, removed, or reordered.
§Examples
use solverforge_core::domain::ListVariableSolution;
use solverforge_core::PlanningSolution;
use solverforge_core::score::SoftScore;
#[derive(Clone)]
struct Vehicle {
visits: Vec<usize>,
}
#[derive(Clone)]
struct VrpSolution {
vehicles: Vec<Vehicle>,
visit_count: usize,
score: Option<SoftScore>,
}
impl PlanningSolution for VrpSolution {
type Score = SoftScore;
fn score(&self) -> Option<Self::Score> { self.score }
fn set_score(&mut self, score: Option<Self::Score>) { self.score = score; }
}
impl ListVariableSolution for VrpSolution {
type Element = usize;
fn entity_count(&self) -> usize {
self.vehicles.len()
}
fn list_len(&self, entity_idx: usize) -> usize {
self.vehicles[entity_idx].visits.len()
}
fn list_get(&self, entity_idx: usize, position: usize) -> Self::Element {
self.vehicles[entity_idx].visits[position]
}
fn list_push(&mut self, entity_idx: usize, elem: Self::Element) {
self.vehicles[entity_idx].visits.push(elem);
}
fn list_insert(&mut self, entity_idx: usize, position: usize, elem: Self::Element) {
self.vehicles[entity_idx].visits.insert(position, elem);
}
fn list_remove(&mut self, entity_idx: usize, position: usize) -> Self::Element {
self.vehicles[entity_idx].visits.remove(position)
}
fn list_reverse(&mut self, entity_idx: usize, start: usize, end: usize) {
self.vehicles[entity_idx].visits[start..end].reverse();
}
fn unassigned_elements(&self) -> Vec<Self::Element> {
use std::collections::HashSet;
let assigned: HashSet<usize> = self.vehicles
.iter()
.flat_map(|v| v.visits.iter().copied())
.collect();
(0..self.visit_count)
.filter(|i| !assigned.contains(i))
.collect()
}
}Required Associated Types§
Required Methods§
fn entity_count(&self) -> usize
fn list_len(&self, entity_idx: usize) -> usize
fn list_get(&self, entity_idx: usize, position: usize) -> Self::Element
fn list_push(&mut self, entity_idx: usize, elem: Self::Element)
fn list_insert( &mut self, entity_idx: usize, position: usize, elem: Self::Element, )
fn list_remove(&mut self, entity_idx: usize, position: usize) -> Self::Element
fn list_reverse(&mut self, entity_idx: usize, start: usize, end: usize)
fn unassigned_elements(&self) -> Vec<Self::Element>
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.