1use oximo_expr::{ExprId, ModelId, VarId};
2use smol_str::SmolStr;
3
4use crate::model::Model;
5
6#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
8pub struct IndicatorConstraintId(pub u32);
9
10impl IndicatorConstraintId {
11 #[inline]
12 pub fn index(self) -> usize {
13 self.0 as usize
14 }
15}
16
17#[derive(Clone, Debug)]
20pub struct IndicatorConstraint {
21 pub name: SmolStr,
22 pub trigger: VarId,
23 pub active_value: bool,
24 pub lhs: ExprId,
25 pub lower: f64,
26 pub upper: f64,
27 pub active: bool,
28}
29
30impl IndicatorConstraint {
31 #[must_use]
32 pub fn is_range(&self) -> bool {
33 self.lower.is_finite()
34 && self.upper.is_finite()
35 && !self.lower.total_cmp(&self.upper).is_eq()
36 }
37
38 #[must_use]
39 pub fn as_single(&self) -> Option<(crate::Sense, f64)> {
40 match (self.lower.is_finite(), self.upper.is_finite()) {
41 (false, true) => Some((crate::Sense::Le, self.upper)),
42 (true, false) => Some((crate::Sense::Ge, self.lower)),
43 (true, true) if self.lower.total_cmp(&self.upper).is_eq() => {
44 Some((crate::Sense::Eq, self.lower))
45 }
46 _ => None,
47 }
48 }
49}
50
51#[derive(Copy, Clone)]
53pub struct IndicatorConstraintHandle<'a> {
54 pub(crate) model: &'a Model,
55 pub(crate) id: IndicatorConstraintId,
56}
57
58impl std::fmt::Debug for IndicatorConstraintHandle<'_> {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 f.debug_struct("IndicatorConstraintHandle").field("id", &self.id).finish()
61 }
62}
63
64impl IndicatorConstraintHandle<'_> {
65 #[must_use]
66 pub const fn id(self) -> IndicatorConstraintId {
67 self.id
68 }
69 #[must_use]
70 pub fn index(self) -> usize {
71 self.id.index()
72 }
73 #[must_use]
74 pub fn model_id(self) -> ModelId {
75 self.model.id()
76 }
77}
78
79impl From<IndicatorConstraintHandle<'_>> for IndicatorConstraintId {
80 fn from(value: IndicatorConstraintHandle<'_>) -> Self {
81 value.id
82 }
83}
84
85#[derive(Copy, Clone, Debug, PartialEq, Eq)]
87pub enum RangeIndicatorConstraintIds {
88 Interval(IndicatorConstraintId),
89 Split { lower: IndicatorConstraintId, upper: IndicatorConstraintId },
90}
91
92#[derive(Copy, Clone, Debug)]
94pub enum RangeIndicatorConstraintHandles<'a> {
95 Interval(IndicatorConstraintHandle<'a>),
96 Split { lower: IndicatorConstraintHandle<'a>, upper: IndicatorConstraintHandle<'a> },
97}
98
99impl RangeIndicatorConstraintHandles<'_> {
100 #[must_use]
101 pub const fn ids(self) -> RangeIndicatorConstraintIds {
102 match self {
103 Self::Interval(h) => RangeIndicatorConstraintIds::Interval(h.id()),
104 Self::Split { lower, upper } => {
105 RangeIndicatorConstraintIds::Split { lower: lower.id(), upper: upper.id() }
106 }
107 }
108 }
109}