Skip to main content

cnvx_core/
var.rs

1use crate::{Constraint, expr::LinExpr};
2use std::ops::Mul;
3
4/// A unique identifier for a variable in a model.
5///
6/// This is used internally by the solver and the model to index variable values.
7#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
8pub struct VarId(pub usize);
9
10impl VarId {
11    /// Creates a `<=` constraint: `self <= rhs`.
12    pub fn leq(self, rhs: f64) -> Constraint {
13        LinExpr::from(self).leq(rhs)
14    }
15
16    /// Creates a `>=` constraint: `self >= rhs`.
17    pub fn geq(self, rhs: f64) -> Constraint {
18        LinExpr::from(self).geq(rhs)
19    }
20
21    /// Creates a `==` constraint: `self == rhs`.
22    pub fn eq(self, rhs: f64) -> Constraint {
23        LinExpr::from(self).eq(rhs)
24    }
25}
26
27/// Represents a decision variable in a model.
28///
29/// Contains information about optional bounds, whether the variable is integer,
30/// and whether it is an artificial variable used in simplex initialization.
31#[derive(Clone, Debug)]
32pub struct Var {
33    /// Unique identifier for the variable.
34    pub id: VarId,
35
36    /// Optional lower bound.
37    pub lb: Option<f64>,
38
39    /// Optional upper bound.
40    pub ub: Option<f64>,
41
42    /// Whether the variable is restricted to integer values.
43    pub is_integer: bool,
44
45    /// Whether this is an artificial variable (used for inequality constraints in simplex initialization).
46    pub is_artificial: bool,
47}
48
49/// A builder for setting properties of a variable using a fluent API.
50///
51/// Returned by [`Model::add_var()`](crate::model::Model::add_var), this allows setting bounds, integrality,
52/// and other properties before finalizing the variable with [`finish()`](VarBuilder::finish).
53///
54/// # Examples
55///
56/// ```rust
57/// # use cnvx_core::{Model};
58/// let mut model = Model::new();
59/// let x = model
60///     .add_var()
61///     .integer()
62///     .finish();
63/// ```
64pub struct VarBuilder<'a> {
65    pub model: &'a mut crate::Model,
66    pub var: VarId,
67}
68
69/// Methods for configuring a variable using a fluent API.
70///
71/// Returned by [`Model::add_var()`](crate::model::Model::add_var). Use these methods to set bounds,
72/// integrality, or mark a variable as binary before calling [`finish()`](VarBuilder::finish).
73impl<'a> VarBuilder<'a> {
74    /// Sets a lower bound for the variable.
75    ///
76    /// This method currently panics because lower bounds are not yet implemented.
77    ///
78    /// # Examples
79    ///
80    /// ```rust, no_run
81    /// # use cnvx_core::{Model};
82    /// let mut model = Model::new();
83    /// let x = model.add_var().lower_bound(0.0).finish();
84    /// ```
85    pub fn lower_bound(self, lb: f64) -> Self {
86        _ = lb;
87        panic!("Lower bound not implemented yet");
88        // self.model.vars[self.var.0].lb = Some(lb);
89        // self
90    }
91
92    /// Sets an upper bound for the variable.
93    ///
94    /// This method currently panics because upper bounds are not yet implemented.
95    ///
96    /// # Examples
97    ///
98    /// ```rust, no_run
99    /// # use cnvx_core::{Model};
100    /// let mut model = Model::new();
101    /// let x = model.add_var().upper_bound(10.0).finish();
102    /// ```
103    pub fn upper_bound(self, ub: f64) -> Self {
104        _ = ub;
105        panic!("Upper bound not implemented yet");
106        // self.model.vars[self.var.0].ub = Some(ub);
107        // self
108    }
109
110    /// Mark the variable as an integer.
111    ///
112    /// # Examples
113    ///
114    /// ```rust
115    /// # use cnvx_core::{Model};
116    /// let mut model = Model::new();
117    /// let x = model.add_var().integer().finish();
118    /// ```
119    pub fn integer(self) -> Self {
120        self.model.vars[self.var.0].is_integer = true;
121        self
122    }
123
124    /// Mark the variable as binary (0 or 1).
125    ///
126    /// # Examples
127    ///
128    /// ```rust
129    /// # use cnvx_core::{Model};
130    /// let mut model = Model::new();
131    /// let x = model.add_var().binary().finish();
132    /// ```
133    pub fn binary(self) -> Self {
134        let var = &mut self.model.vars[self.var.0];
135        var.is_integer = true;
136        var.lb = Some(0.0);
137        var.ub = Some(1.0);
138        self
139    }
140
141    /// Finalizes the variable and returns its [`VarId`].
142    ///
143    /// Must be called after setting any desired properties on the variable.
144    ///
145    /// # Examples
146    ///
147    /// ```rust
148    /// # use cnvx_core::{Model};
149    /// let mut model = Model::new();
150    /// let x = model.add_var().integer().finish();
151    /// ```
152    pub fn finish(self) -> VarId {
153        self.var
154    }
155}
156
157/// Allows multiplying a variable by a constant to create a linear expression.
158///
159/// # Examples
160///
161/// ```rust
162/// # use cnvx_core::{Model};
163/// let mut model = Model::new();
164/// let x = model.add_var().finish();
165/// let expr = x * 3.0; // LinExpr representing 3*x
166/// ```
167impl Mul<f64> for VarId {
168    type Output = LinExpr;
169
170    fn mul(self, rhs: f64) -> LinExpr {
171        LinExpr::new(self, rhs)
172    }
173}
174
175/// Allows multiplying a constant by a variable to create a linear expression.
176///
177/// # Examples
178///
179/// ```rust
180/// # use cnvx_core::{Model};
181/// let mut model = Model::new();
182/// let x = model.add_var().finish();
183/// let expr = 3.0 * x; // LinExpr representing 3*x
184/// ```
185impl Mul<VarId> for f64 {
186    type Output = LinExpr;
187
188    fn mul(self, rhs: VarId) -> LinExpr {
189        rhs * self
190    }
191}