solverforge_solver/heuristic/move/
traits.rs

1//! Move trait definition.
2
3use std::fmt::Debug;
4
5use solverforge_core::domain::PlanningSolution;
6use solverforge_scoring::ScoreDirector;
7
8/// A move that modifies one or more planning variables.
9///
10/// Moves are fully typed for maximum performance - no boxing, no virtual dispatch.
11/// Undo is handled by `RecordingScoreDirector`, not by move return values.
12///
13/// # Type Parameters
14/// * `S` - The planning solution type
15///
16/// # Implementation Notes
17/// - Moves should be lightweight
18/// - Use `RecordingScoreDirector` to wrap the score director for automatic undo
19/// - Moves are NEVER cloned - ownership transfers via arena indices
20/// - Methods are generic over D to allow use with both concrete directors and RecordingScoreDirector
21pub trait Move<S: PlanningSolution>: Send + Sync + Debug {
22    /// Returns true if this move can be executed in the current state.
23    ///
24    /// A move is not doable if:
25    /// - The source value equals the destination value (no change)
26    /// - Required entities are pinned
27    /// - The move would violate hard constraints that can be detected early
28    fn is_doable<D: ScoreDirector<S>>(&self, score_director: &D) -> bool;
29
30    /// Executes this move, modifying the working solution.
31    ///
32    /// This method modifies the planning variables through the score director.
33    /// Use `RecordingScoreDirector` to enable automatic undo via `undo_changes()`.
34    fn do_move<D: ScoreDirector<S>>(&self, score_director: &mut D);
35
36    /// Returns the descriptor index of the entity type this move affects.
37    fn descriptor_index(&self) -> usize;
38
39    /// Returns the entity indices involved in this move.
40    fn entity_indices(&self) -> &[usize];
41
42    /// Returns the variable name this move affects.
43    fn variable_name(&self) -> &str;
44}