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}