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