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}