solverforge_solver/heuristic/selector/
dynamic_scalar_nearby_swap.rs1use std::fmt::{self, Debug};
4
5use solverforge_core::domain::{DynamicScalarVariableSlot, PlanningSolution};
6use solverforge_core::score::Score;
7use solverforge_scoring::Director;
8
9use crate::heuristic::r#move::{DynamicScalarSwapMove, MoveArena};
10
11use super::move_selector::{MoveSelector, MoveStreamContext};
12use super::scalar_neighborhood::{
13 dynamic_slot, emit_dynamic_scalar_swap_move, RuntimeScalarFacadeCursor,
14 ScalarNeighborhoodBindingError, ScalarNeighborhoodLeaf, ScalarNeighborhoodSpec,
15};
16
17pub struct DynamicScalarNearbySwapMoveSelector<S> {
22 leaf: ScalarNeighborhoodLeaf<S>,
23}
24
25pub type DynamicScalarNearbySwapMoveCursor<S> =
26 RuntimeScalarFacadeCursor<S, DynamicScalarSwapMove<S>>;
27
28impl<S> DynamicScalarNearbySwapMoveSelector<S>
29where
30 S: PlanningSolution,
31{
32 pub fn new(
33 slot: DynamicScalarVariableSlot<S>,
34 max_nearby: usize,
35 ) -> Result<Self, ScalarNeighborhoodBindingError> {
36 Ok(Self {
37 leaf: ScalarNeighborhoodLeaf::from_spec(
38 ScalarNeighborhoodSpec::NearbySwap { max_nearby },
39 dynamic_slot(slot),
40 None,
41 )?,
42 })
43 }
44}
45
46impl<S> Debug for DynamicScalarNearbySwapMoveSelector<S>
47where
48 S: PlanningSolution,
49{
50 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
51 formatter
52 .debug_struct("DynamicScalarNearbySwapMoveSelector")
53 .field("leaf", &self.leaf)
54 .finish()
55 }
56}
57
58impl<S> MoveSelector<S, DynamicScalarSwapMove<S>> for DynamicScalarNearbySwapMoveSelector<S>
59where
60 S: PlanningSolution,
61 S::Score: Score,
62{
63 type Cursor<'a>
64 = DynamicScalarNearbySwapMoveCursor<S>
65 where
66 Self: 'a;
67
68 fn open_cursor<'a, D: Director<S>>(&'a self, director: &D) -> Self::Cursor<'a> {
69 self.open_cursor_with_context(director, MoveStreamContext::default())
70 }
71
72 fn open_cursor_with_context<'a, D: Director<S>>(
73 &'a self,
74 director: &D,
75 context: MoveStreamContext,
76 ) -> Self::Cursor<'a> {
77 let mut stream_state = self.leaf.new_stream_state();
78 RuntimeScalarFacadeCursor::new(
79 self.leaf
80 .open_cursor_with_stream_state(&mut stream_state, director, context),
81 emit_dynamic_scalar_swap_move::<S>,
82 )
83 }
84
85 fn size<D: Director<S>>(&self, director: &D) -> usize {
86 self.open_cursor(director).count()
87 }
88
89 fn append_moves<D: Director<S>>(
90 &self,
91 director: &D,
92 arena: &mut MoveArena<DynamicScalarSwapMove<S>>,
93 ) {
94 arena.extend(self.open_cursor(director));
95 }
96}