@@ -27,20 +27,42 @@ pub struct Engine {
2727 listeners : HashMap < usize , Vec < Callback > > ,
2828}
2929impl Engine {
30+ /// Creates a new empty constraint engine.
31+ ///
32+ /// The returned engine has no variables, no constraints, and no listeners.
3033 pub fn new ( ) -> Self {
3134 Self { values : Vec :: new ( ) , constraints : HashMap :: new ( ) , listeners : HashMap :: new ( ) }
3235 }
3336
37+ /// Adds a variable with the provided initial domain.
38+ ///
39+ /// Returns the variable ID that can be used with methods like
40+ /// [`Engine::val`], [`Engine::new_eq`], and [`Engine::new_neq`].
41+ ///
42+ /// All inserted values start as active (not suppressed).
3443 pub fn add_var ( & mut self , values : Vec < i32 > ) -> usize {
3544 let id = self . values . len ( ) ;
3645 self . values . push ( values. into_iter ( ) . map ( |v| ValueState { value : v, suppressed_by : None } ) . collect ( ) ) ;
3746 id
3847 }
3948
49+ /// Returns the currently active domain values of a variable.
50+ ///
51+ /// Suppressed values are excluded from the returned vector.
52+ ///
53+ /// Panics if `var` is not a valid variable ID.
4054 pub fn val ( & self , var : usize ) -> Vec < i32 > {
4155 self . values [ var] . iter ( ) . filter ( |s| s. suppressed_by . is_none ( ) ) . map ( |s| s. value ) . collect ( )
4256 }
4357
58+ /// Adds an equality constraint between two variables and propagates it.
59+ ///
60+ /// On success, returns the newly assigned constraint ID.
61+ ///
62+ /// On failure, returns `(constraint_id, explanation)` where `explanation`
63+ /// contains IDs of constraints involved in the domain wipeout.
64+ /// The newly created constraint remains in the engine and can be removed
65+ /// with [`Engine::retract_constraint`].
4466 pub fn new_eq ( & mut self , var1 : usize , var2 : usize ) -> Result < usize , ( usize , Vec < usize > ) > {
4567 let id = self . constraints . len ( ) ;
4668 self . constraints . insert ( id, ( var1, var2, ConstraintKind :: Equality ) ) ;
@@ -50,6 +72,14 @@ impl Engine {
5072 Ok ( id)
5173 }
5274
75+ /// Adds an inequality constraint between two variables and propagates it.
76+ ///
77+ /// On success, returns the newly assigned constraint ID.
78+ ///
79+ /// On failure, returns `(constraint_id, explanation)` where `explanation`
80+ /// contains IDs of constraints involved in the domain wipeout.
81+ /// The newly created constraint remains in the engine and can be removed
82+ /// with [`Engine::retract_constraint`].
5383 pub fn new_neq ( & mut self , var1 : usize , var2 : usize ) -> Result < usize , ( usize , Vec < usize > ) > {
5484 let id = self . constraints . len ( ) ;
5585 self . constraints . insert ( id, ( var1, var2, ConstraintKind :: Inequality ) ) ;
@@ -59,6 +89,13 @@ impl Engine {
5989 Ok ( id)
6090 }
6191
92+ /// Retracts a constraint by ID and incrementally restores consistency.
93+ ///
94+ /// If the ID is present, the constraint is removed, values suppressed by
95+ /// that exact constraint are released, and only the affected neighborhood is
96+ /// re-propagated. If the ID does not exist, this method is a no-op.
97+ ///
98+ /// Panics if re-propagation unexpectedly causes a domain wipeout.
6299 pub fn retract_constraint ( & mut self , id : usize ) {
63100 if let Some ( ( var1, var2, _) ) = self . constraints . remove ( & id) {
64101 // 1. Free only values that were killed *by this exact constraint*
0 commit comments