From 8186482db5dee64ef517112f0bdd7d941aaf29f1 Mon Sep 17 00:00:00 2001 From: Kavitha G Menon Date: Wed, 26 Nov 2025 00:34:34 -0600 Subject: [PATCH] Adding product demand constraints --- docs/src/problem.md | 17 +++++++++++++++++ src/model/build.jl | 27 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/docs/src/problem.md b/docs/src/problem.md index 933a4cd..8bc0e8b 100644 --- a/docs/src/problem.md +++ b/docs/src/problem.md @@ -66,6 +66,8 @@ The mathematical model employed by RELOG is based on three main components: | $K^\text{out-var}_{cmi}$ | Factor used to calculate variable amount of material $m$ collected at center $c$. See `eq_z_collected` for more details. | -- | | $K^\text{output}_{pmt}$ | Amount of material $m$ produced by plant $p$ at time $t$ for each tonne of input material processed | tonne | | $K^\text{storage-limit}_{pm}$ | Maximum amount of material $m$ that can be stored at plant $p$ at any time | tonne | +| $K^\text{dem-min}_{mt}$ | Minimum demand of material $m$ at time $t$ | tonne | +| $K^\text{dem-max}_{mt}$ | Maximum demand of material $m$ at time $t$ | tonne | | $R^\text{collect}_{cmt}$ | Cost of collecting material $m$ at center $c$ at time $t$ | \$/tonne | | $R^\text{disp}_{umt}$ | Cost to dispose of material at plant/center $u$ at time $t$ | \$/tonne | | $R^\text{em}_{gt}$ | Penalty cost per tonne of greenhouse gas $g$ emitted at time $t$ | \$/tonne | @@ -326,6 +328,21 @@ The goal is to minimize a linear objective function with the following terms: \end{align*} ``` +- Minimum product demands for products at centers: +```math +\begin{align*} +& \sum_{c : m \in M^-_c} \sum_{u : (u,m) \in E^-(c)} y_{ucmt} \geq K^\text{dem-min}_{mt} +& \forall m \in M, t \in T +\end{align*} +``` +- Maximum product demands for products at centers: +```math +\begin{align*} +& \sum_{c : m \in M^-_c} \sum_{u : (u,m) \in E^-(c)} y_{ucmt} \leq K^\text{dem-max}_{mt} +& \forall m \in M, t \in T +\end{align*} +``` + - Calculation of amount collected by the center (`eq_z_collected[c.name, m.name, t]`). In the equation below, $K^\text{out-var-len}$ is the length of the $K^\text{out-var}_{c,m,*}$ vector. diff --git a/src/model/build.jl b/src/model/build.jl index 04a4e0a..74124f4 100644 --- a/src/model/build.jl +++ b/src/model/build.jl @@ -356,6 +356,33 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false ) end + + # Demand bounds (only when active: > 0 for min; finite and > 0 for max) + eq_min_demand = _init(model, :eq_min_demand) + eq_max_demand = _init(model, :eq_max_demand) + for m in products, t in T + if m.minimum_demand[t] > 0 + eq_min_demand[m.name, t] = @constraint( + model, + sum( + y[src.name, c.name, m.name, t] + for c in centers if c.input == m + for (src, m2) in E_in[c] if m2 == m + ) >= m.minimum_demand[t] + ) + end + if isfinite(m.maximum_demand[t]) && m.maximum_demand[t] > 0 + eq_max_demand[m.name, t] = @constraint( + model, + sum( + y[src.name, c.name, m.name, t] + for c in centers if c.input == m + for (src, m2) in E_in[c] if m2 == m + ) <= m.maximum_demand[t] + ) + end + end + # Plants: Disposal limit eq_disposal_limit = _init(model, :eq_disposal_limit) for p in plants, m in keys(p.output), t in T