1use oximo_expr::{Expr, ExprId};
2use smol_str::SmolStr;
3
4#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6pub enum Sense {
7 Le,
8 Ge,
9 Eq,
10}
11
12#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
13pub struct ConstraintId(pub u32);
14
15impl ConstraintId {
16 #[inline]
17 pub fn index(self) -> usize {
18 self.0 as usize
19 }
20}
21
22#[derive(Clone, Debug)]
26pub struct Constraint {
27 pub name: SmolStr,
28 pub lhs: ExprId,
29 pub sense: Sense,
30 pub rhs: f64,
31 pub active: bool,
32}
33
34#[derive(Copy, Clone, Debug)]
37pub struct ConstraintExpr<'a> {
38 pub lhs: Expr<'a>,
39 pub sense: Sense,
40 pub rhs: f64,
41}
42
43pub trait Relate<'a> {
45 fn le<R: IntoRhs<'a>>(self, rhs: R) -> ConstraintExpr<'a>;
46 fn ge<R: IntoRhs<'a>>(self, rhs: R) -> ConstraintExpr<'a>;
47 fn eq<R: IntoRhs<'a>>(self, rhs: R) -> ConstraintExpr<'a>;
48}
49
50pub trait IntoRhs<'a> {
53 fn fold_rhs(self, lhs: Expr<'a>) -> (Expr<'a>, f64);
54}
55
56impl<'a> IntoRhs<'a> for f64 {
57 fn fold_rhs(self, lhs: Expr<'a>) -> (Expr<'a>, f64) {
58 (lhs, self)
59 }
60}
61
62impl<'a> IntoRhs<'a> for i32 {
63 fn fold_rhs(self, lhs: Expr<'a>) -> (Expr<'a>, f64) {
64 (lhs, f64::from(self))
65 }
66}
67
68impl<'a> IntoRhs<'a> for Expr<'a> {
69 fn fold_rhs(self, lhs: Expr<'a>) -> (Expr<'a>, f64) {
70 (lhs - self, 0.0)
71 }
72}
73
74impl<'a> Relate<'a> for Expr<'a> {
75 fn le<R: IntoRhs<'a>>(self, rhs: R) -> ConstraintExpr<'a> {
76 let (lhs, rhs) = rhs.fold_rhs(self);
77 ConstraintExpr { lhs, sense: Sense::Le, rhs }
78 }
79
80 fn ge<R: IntoRhs<'a>>(self, rhs: R) -> ConstraintExpr<'a> {
81 let (lhs, rhs) = rhs.fold_rhs(self);
82 ConstraintExpr { lhs, sense: Sense::Ge, rhs }
83 }
84
85 fn eq<R: IntoRhs<'a>>(self, rhs: R) -> ConstraintExpr<'a> {
86 let (lhs, rhs) = rhs.fold_rhs(self);
87 ConstraintExpr { lhs, sense: Sense::Eq, rhs }
88 }
89}