Skip to main content

solverforge_core/domain/
variable.rs

1// Variable type definitions
2
3use std::any::TypeId;
4
5// The type of a planning variable.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum VariableType {
8    // A genuine planning variable that the solver optimizes.
9    Genuine,
10    /* A chained planning variable where entities form chains rooted at anchors.
11
12    Chained variables are used for problems like vehicle routing where:
13    - Each entity points to either an anchor (problem fact) or another entity
14    - Entities form chains: Anchor ← Entity1 ← Entity2 ← Entity3
15    - No cycles or branching allowed
16    */
17    Chained,
18    // A list variable containing multiple values.
19    List,
20    // A shadow variable computed from other variables.
21    Shadow(ShadowVariableKind),
22}
23
24// The kind of shadow variable.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub enum ShadowVariableKind {
27    // Custom shadow variable with user-defined listener.
28    Custom,
29    // Inverse of another variable (bidirectional relationship).
30    InverseRelation,
31    // Index within a list variable.
32    Index,
33    // Next element in a list variable.
34    NextElement,
35    // Previous element in a list variable.
36    PreviousElement,
37    // Anchor in a chained variable.
38    Anchor,
39    // Cascading update from other shadow variables.
40    Cascading,
41    // Piggyback on another shadow variable's listener.
42    Piggyback,
43}
44
45// The type of value range for a planning variable.
46#[derive(Debug, Clone, PartialEq, Eq)]
47pub enum ValueRangeType {
48    // A collection of discrete values.
49    Collection,
50    // A countable range (e.g., integers from 1 to 100).
51    CountableRange {
52        // Inclusive start of the range.
53        from: i64,
54        // Exclusive end of the range.
55        to: i64,
56    },
57    // An entity-dependent value range.
58    EntityDependent,
59}
60
61impl VariableType {
62    /// Returns true if this is a genuine (non-shadow) variable.
63    ///
64    /// Genuine variables include basic, chained, and list variables.
65    pub fn is_genuine(&self) -> bool {
66        matches!(
67            self,
68            VariableType::Genuine | VariableType::Chained | VariableType::List
69        )
70    }
71
72    pub fn is_shadow(&self) -> bool {
73        matches!(self, VariableType::Shadow(_))
74    }
75
76    pub fn is_list(&self) -> bool {
77        matches!(self, VariableType::List)
78    }
79
80    /// Returns true if this is a chained variable.
81    ///
82    /// Chained variables form chains rooted at anchor problem facts.
83    pub fn is_chained(&self) -> bool {
84        matches!(self, VariableType::Chained)
85    }
86
87    pub fn is_basic(&self) -> bool {
88        matches!(self, VariableType::Genuine)
89    }
90}
91
92impl ShadowVariableKind {
93    pub fn requires_listener(&self) -> bool {
94        matches!(
95            self,
96            ShadowVariableKind::Custom | ShadowVariableKind::Cascading
97        )
98    }
99
100    pub fn is_automatic(&self) -> bool {
101        matches!(
102            self,
103            ShadowVariableKind::InverseRelation
104                | ShadowVariableKind::Index
105                | ShadowVariableKind::NextElement
106                | ShadowVariableKind::PreviousElement
107                | ShadowVariableKind::Anchor
108        )
109    }
110
111    /// Returns true if this shadow variable piggybacks on another
112    /// shadow variable's listener rather than having its own.
113    pub fn is_piggyback(&self) -> bool {
114        matches!(self, ShadowVariableKind::Piggyback)
115    }
116}
117
118/* Information about a chained variable's configuration.
119
120Chained variables require knowledge of the anchor type to distinguish
121between anchor values (chain roots) and entity values (chain members).
122*/
123#[derive(Debug, Clone, PartialEq, Eq)]
124pub struct ChainedVariableInfo {
125    // The TypeId of the anchor type (problem fact at chain root).
126    pub anchor_type_id: TypeId,
127    // The TypeId of the entity type (chain members).
128    pub entity_type_id: TypeId,
129    // Whether this variable has an associated anchor shadow variable.
130    pub has_anchor_shadow: bool,
131}
132
133impl ChainedVariableInfo {
134    /// Creates new chained variable info.
135    pub fn new<Anchor: 'static, Entity: 'static>() -> Self {
136        Self {
137            anchor_type_id: TypeId::of::<Anchor>(),
138            entity_type_id: TypeId::of::<Entity>(),
139            has_anchor_shadow: false,
140        }
141    }
142
143    /// Creates new chained variable info with anchor shadow variable.
144    pub fn with_anchor_shadow<Anchor: 'static, Entity: 'static>() -> Self {
145        Self {
146            anchor_type_id: TypeId::of::<Anchor>(),
147            entity_type_id: TypeId::of::<Entity>(),
148            has_anchor_shadow: true,
149        }
150    }
151
152    pub fn is_anchor_type(&self, type_id: TypeId) -> bool {
153        self.anchor_type_id == type_id
154    }
155
156    pub fn is_entity_type(&self, type_id: TypeId) -> bool {
157        self.entity_type_id == type_id
158    }
159}