Skip to main content

solverforge_solver/heuristic/selector/
entity.rs

1// Entity selectors for iterating over planning entities
2
3use std::fmt::Debug;
4
5use solverforge_core::domain::PlanningSolution;
6use solverforge_scoring::Director;
7
8// A reference to an entity within a solution.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub struct EntityReference {
11    // Index of the entity descriptor.
12    pub descriptor_index: usize,
13    // Index of the entity within its collection.
14    pub entity_index: usize,
15}
16
17impl EntityReference {
18    pub fn new(descriptor_index: usize, entity_index: usize) -> Self {
19        Self {
20            descriptor_index,
21            entity_index,
22        }
23    }
24}
25
26/// Trait for selecting entities from a planning solution.
27///
28/// Entity selectors provide an iteration order over the entities that
29/// the solver will consider for moves.
30///
31/// # Type Parameters
32/// * `S` - The planning solution type
33pub trait EntitySelector<S: PlanningSolution>: Send + Debug {
34    /* Returns an iterator over entity references.
35
36    The iterator yields `EntityReference` values that identify entities
37    within the solution.
38    */
39    fn iter<'a, D: Director<S>>(
40        &'a self,
41        score_director: &'a D,
42    ) -> impl Iterator<Item = EntityReference> + 'a;
43
44    fn size<D: Director<S>>(&self, score_director: &D) -> usize;
45
46    // Returns true if this selector may return the same entity multiple times.
47    fn is_never_ending(&self) -> bool {
48        false
49    }
50}
51
52// An entity selector that iterates over all entities from the solution.
53#[derive(Clone, Debug)]
54pub struct FromSolutionEntitySelector {
55    // The descriptor index to select from.
56    descriptor_index: usize,
57}
58
59impl FromSolutionEntitySelector {
60    pub fn new(descriptor_index: usize) -> Self {
61        Self { descriptor_index }
62    }
63}
64
65impl<S: PlanningSolution> EntitySelector<S> for FromSolutionEntitySelector {
66    fn iter<'a, D: Director<S>>(
67        &'a self,
68        score_director: &'a D,
69    ) -> impl Iterator<Item = EntityReference> + 'a {
70        let count = score_director
71            .entity_count(self.descriptor_index)
72            .unwrap_or(0);
73        let desc_idx = self.descriptor_index;
74        (0..count).map(move |i| EntityReference::new(desc_idx, i))
75    }
76
77    fn size<D: Director<S>>(&self, score_director: &D) -> usize {
78        score_director
79            .entity_count(self.descriptor_index)
80            .unwrap_or(0)
81    }
82}
83
84// An entity selector that iterates over all entities from all descriptors.
85#[derive(Debug, Clone, Default)]
86pub struct AllEntitiesSelector;
87
88impl AllEntitiesSelector {
89    pub fn new() -> Self {
90        Self
91    }
92}
93
94impl<S: PlanningSolution> EntitySelector<S> for AllEntitiesSelector {
95    fn iter<'a, D: Director<S>>(
96        &'a self,
97        score_director: &'a D,
98    ) -> impl Iterator<Item = EntityReference> + 'a {
99        let desc = score_director.solution_descriptor();
100        let descriptor_count = desc.entity_descriptors.len();
101
102        let mut refs = Vec::new();
103        for desc_idx in 0..descriptor_count {
104            let count = score_director.entity_count(desc_idx).unwrap_or(0);
105            for entity_idx in 0..count {
106                refs.push(EntityReference::new(desc_idx, entity_idx));
107            }
108        }
109
110        refs.into_iter()
111    }
112
113    fn size<D: Director<S>>(&self, score_director: &D) -> usize {
114        score_director.total_entity_count().unwrap_or(0)
115    }
116}
117
118#[cfg(test)]
119#[path = "entity_tests.rs"]
120mod tests;