grb/
constr.rs

1//! This module contains the structs passed to the [`Model::add_constr(s)`](crate::Model::add_constr) and [`Model::add_range(s)`](crate::Model::add_constr) methods.
2//!
3//! The structs themselves are usually constructed using the [`c!(...)`](crate::c) macro.
4use crate::expr::{AttachModel, Attached, LinExpr, QuadExpr};
5use crate::prelude::*;
6use crate::Result;
7use std::fmt;
8/// A inequality constraint (linear or quadratic).  Creating this object does not automatically add the constraint to a model.
9/// Instead, it should be passed to [`Model::add_constr`](crate::Model::add_constr) or [`Model::add_constrs`](crate::Model::add_constrs).
10///
11/// Usually created with an invocation of [`c!`]`(...)`.
12#[derive(Debug, Clone)]
13pub struct IneqExpr {
14    /// Left-hand side
15    pub lhs: Expr,
16    /// Direction of the inequality, or if it the constraint is an equality
17    pub sense: ConstrSense,
18    /// Right-hand side
19    pub rhs: Expr,
20}
21
22impl IneqExpr {
23    pub(crate) fn into_normalised_linear(self) -> Result<(LinExpr, ConstrSense, f64)> {
24        let IneqExpr { lhs, rhs, sense } = self;
25        let mut lhs: LinExpr = (lhs - rhs).into_linexpr()?;
26        let rhs = -lhs.set_offset(0.0);
27        Ok((lhs, sense, rhs))
28    }
29
30    pub(crate) fn into_normalised_quad(self) -> (QuadExpr, ConstrSense, f64) {
31        let IneqExpr { lhs, rhs, sense } = self;
32        let mut lhs = (lhs - rhs).into_quadexpr();
33        let rhs = -lhs.set_offset(0.0);
34        (lhs, sense, rhs)
35    }
36}
37
38impl AttachModel for IneqExpr {}
39
40impl fmt::Debug for Attached<'_, IneqExpr> {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        let cmp = match self.inner.sense {
43            ConstrSense::Less => "≤",
44            ConstrSense::Greater => "≥",
45            ConstrSense::Equal => "=",
46        };
47        write!(
48            f,
49            "{:?} {} {:?}",
50            self.inner.lhs.attach(self.model),
51            cmp,
52            self.inner.rhs.attach(self.model)
53        )
54    }
55}
56
57/// A linear range constraint expression.  Creating this object does not automatically add the constraint to a model.
58/// Instead, it should be passed to [`Model::add_range`](crate::Model::add_range) or [`Model::add_ranges`](crate::Model::add_ranges).
59///
60/// Usually created with an invocation of `c!(...)`.
61/// Note that `expr` must be linear.
62#[derive(Debug, Clone)]
63pub struct RangeExpr {
64    /// The linear expression of variables to constrain
65    pub expr: Expr,
66    /// The maximum value of the expression
67    pub ub: f64,
68    /// The minimum value of the expression
69    pub lb: f64,
70}
71
72impl RangeExpr {
73    pub(crate) fn into_normalised(self) -> Result<(LinExpr, f64, f64)> {
74        let RangeExpr {
75            expr,
76            mut ub,
77            mut lb,
78        } = self;
79        let mut expr = expr.into_linexpr()?;
80        let offset = expr.set_offset(0.0);
81        ub -= offset;
82        lb -= offset;
83        Ok((expr, lb, ub))
84    }
85}
86
87impl AttachModel for RangeExpr {}
88
89impl fmt::Debug for Attached<'_, RangeExpr> {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        write!(
92            f,
93            "{:?} ∈ [{}, {}]",
94            self.inner.expr.attach(self.model),
95            self.inner.lb,
96            self.inner.ub
97        )
98    }
99}
100
101// TODO: support for general PWL constraints