Skip to main content

cnvx_core/
objective.rs

1use crate::LinExpr;
2use std::fmt::Display;
3
4/// The optimization direction of an objective function.
5#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6pub enum Sense {
7    /// Minimize the objective function.
8    Minimize,
9
10    /// Maximize the objective function.
11    Maximize,
12}
13
14/// Represents an objective function in a model.
15///
16/// Contains the linear expression to optimize, the optimization sense (min/max),
17/// an optional name, and an optional priority (useful for multi-objective problems).
18///
19/// # Examples
20///
21/// ```rust
22/// # use cnvx_core::{Objective, LinExpr, Model};
23/// # let mut model = Model::new();
24///
25/// let x = model.add_var().finish(); // VarId
26/// let objective = Objective::maximize(3.0 * x).name("Profit");
27/// ```
28#[derive(Clone, Debug)]
29pub struct Objective {
30    /// Whether to minimize or maximize the objective.
31    pub sense: Sense,
32
33    /// The linear expression representing the objective.
34    pub expr: LinExpr,
35
36    /// Optional human-readable name.
37    pub name: Option<String>,
38
39    /// Optional priority for multi-objective optimization (not used)
40    pub priority: Option<u32>,
41}
42
43/// Builder for ergonomic creation of objectives.
44///
45/// Returned by [`Objective::minimize`] or [`Objective::maximize`],
46/// allows setting optional fields like `name` or `priority`.
47pub struct ObjectiveBuilder {
48    objective: Objective,
49}
50
51impl ObjectiveBuilder {
52    /// Sets a priority for multi-objective optimization.
53    ///
54    /// Higher priority objectives are optimized first.
55    ///
56    /// # Example
57    ///
58    /// ```rust, no_run
59    /// # use cnvx_core::{Objective, LinExpr, Model};
60    /// # let mut model = Model::new();
61    /// let x = model.add_var().finish(); // VarId
62    /// let obj = Objective::maximize(2.0 * x).priority(1);
63    /// ```
64    pub fn priority(mut self, p: u32) -> Self {
65        self.objective.priority = Some(p);
66        unimplemented!(
67            "Multi-objective optimization is not yet implemented, so priority has no effect"
68        );
69    }
70
71    /// Sets a human-readable name for the objective and returns the final [`Objective`].
72    ///
73    /// # Example
74    ///
75    /// ```rust
76    /// # use cnvx_core::{Objective, LinExpr, Model};
77    /// # let mut model = Model::new();
78    /// let x = model.add_var().finish(); // VarId
79    /// let obj = Objective::maximize(2.0 * x).name("Profit");
80    /// ```
81    pub fn name<S: Into<String>>(mut self, name: S) -> Objective {
82        self.objective.name = Some(name.into());
83        self.objective
84    }
85}
86
87impl Objective {
88    /// Creates a minimization objective.
89    ///
90    /// Returns an [`ObjectiveBuilder`] to optionally set name or priority.
91    ///
92    /// # Example
93    ///
94    /// ```rust
95    /// # use cnvx_core::{Objective, LinExpr, Model};
96    /// # let mut model = Model::new();
97    /// let x = model.add_var().finish(); // VarId
98    /// let obj = Objective::minimize(3.0 * x).name("Cost");
99    /// ```
100    pub fn minimize(expr: LinExpr) -> ObjectiveBuilder {
101        ObjectiveBuilder {
102            objective: Objective {
103                sense: Sense::Minimize,
104                expr,
105                name: None,
106                priority: None,
107            },
108        }
109    }
110
111    /// Creates a maximization objective.
112    ///
113    /// Returns an [`ObjectiveBuilder`] to optionally set name or priority.
114    ///
115    /// # Example
116    ///
117    /// ```rust
118    /// # use cnvx_core::{Objective, LinExpr, Model};
119    /// # let mut model = Model::new();
120    /// let x = model.add_var().finish(); // VarId
121    /// let obj = Objective::maximize(3.0 * x).name("Profit");
122    /// ```
123    pub fn maximize(expr: LinExpr) -> ObjectiveBuilder {
124        ObjectiveBuilder {
125            objective: Objective {
126                sense: Sense::Maximize,
127                expr,
128                name: None,
129                priority: None,
130            },
131        }
132    }
133}
134
135impl Display for Objective {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        let sense_str = match self.sense {
138            Sense::Minimize => "Minimize",
139            Sense::Maximize => "Maximize",
140        };
141        if let Some(name) = &self.name {
142            write!(f, "{} {}: {}", sense_str, name, self.expr)
143        } else {
144            write!(f, "{}: {}", sense_str, self.expr)
145        }
146    }
147}