Skip to main content

solverforge_solver/heuristic/selector/move_selector/
iter.rs

1pub struct MoveSelectorIter<S, M, C>
2where
3    S: PlanningSolution,
4    M: Move<S>,
5    C: MoveCursor<S, M>,
6{
7    cursor: C,
8    _phantom: PhantomData<(fn() -> S, fn() -> M)>,
9}
10
11impl<S, M, C> MoveSelectorIter<S, M, C>
12where
13    S: PlanningSolution,
14    M: Move<S>,
15    C: MoveCursor<S, M>,
16{
17    fn new(cursor: C) -> Self {
18        Self {
19            cursor,
20            _phantom: PhantomData,
21        }
22    }
23}
24
25impl<S, M, C> Iterator for MoveSelectorIter<S, M, C>
26where
27    S: PlanningSolution,
28    M: Move<S>,
29    C: MoveCursor<S, M>,
30{
31    type Item = M;
32
33    fn next(&mut self) -> Option<Self::Item> {
34        let index = {
35            let (index, _) = self.cursor.next_candidate()?;
36            index
37        };
38        Some(self.cursor.take_candidate(index))
39    }
40}
41
42/// A typed move selector that yields stable candidate indices plus borrowable
43/// move views. Ownership is transferred only via `take_candidate`.
44pub trait MoveSelector<S: PlanningSolution, M: Move<S>>: Send + Debug {
45    type Cursor<'a>: MoveCursor<S, M> + 'a
46    where
47        Self: 'a;
48
49    fn open_cursor<'a, D: Director<S>>(&'a self, score_director: &D) -> Self::Cursor<'a>;
50
51    fn iter_moves<'a, D: Director<S>>(
52        &'a self,
53        score_director: &D,
54    ) -> MoveSelectorIter<S, M, Self::Cursor<'a>> {
55        MoveSelectorIter::new(self.open_cursor(score_director))
56    }
57
58    fn size<D: Director<S>>(&self, score_director: &D) -> usize;
59
60    fn append_moves<D: Director<S>>(&self, score_director: &D, arena: &mut MoveArena<M>) {
61        let mut cursor = self.open_cursor(score_director);
62        for index in collect_cursor_indices::<S, M, _>(&mut cursor) {
63            arena.push(cursor.take_candidate(index));
64        }
65    }
66
67    fn is_never_ending(&self) -> bool {
68        false
69    }
70}
71