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