diff --git a/docs/make.jl b/docs/make.jl index 96c8d6491..83f5bed1d 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -33,7 +33,7 @@ Literate.markdown(TUTORIAL_STORAGE_API, OUTPUT_STORAGE_API, documenter=true) makedocs( modules = [Coluna, BlockDecomposition], checkdocs = :exports, - sitename = "Coluna User Guide", + sitename = "Coluna.jl", authors = "Atoptima & contributors", format = Documenter.HTML( prettyurls = get(ENV, "CI", nothing) == "true", diff --git a/docs/src/api/benders.md b/docs/src/api/benders.md index d93e7afe7..e77e99acd 100644 --- a/docs/src/api/benders.md +++ b/docs/src/api/benders.md @@ -112,7 +112,7 @@ The default implementation returns: ```@docs Coluna.Algorithm.BendersOutput - +``` **References**: @@ -127,7 +127,6 @@ Coluna.Benders.new_output ## Benders cut generation iteration - ```mermaid flowchart TB; id1(Optimize master) diff --git a/docs/src/man/decomposition.md b/docs/src/man/decomposition.md index 48104ec54..5fd9dc8df 100644 --- a/docs/src/man/decomposition.md +++ b/docs/src/man/decomposition.md @@ -1,15 +1,13 @@ # Dantzig-Wolfe and Benders decompositions Coluna is a framework to optimize mixed-integer programs that you can decompose. -In other words, if you remove the linking constraints or linking variables from you +In other words, if you remove the linking constraints or linking variables from your program, you'll get sets of constraints (blocks) that you can solve independently. -Decompositions are typically used on programs whose constraints or variables can be divided into a set of "easy" constraints (respectively easy variables) and a set of "hard" constraints (respectively hard variables). Decomposing on constraints leads to Dantzig-Wolfe tranformation while decomposing on variables leads to Benders transformation. Both of these decompositions are implemented in Coluna. +Decompositions are typically used on programs whose constraints or variables can be divided into a set of "easy" constraints (respectively easy variables) and a set of "hard" constraints (respectively hard variables). Decomposing on constraints leads to Dantzig-Wolfe transformation while decomposing on variables leads to the Benders transformation. Both of these decompositions are implemented in Coluna. ## Dantzig-Wolfe -### Classic Dantzig-Wolfe decomposition - Let's consider the following coefficient matrix that has a block diagonal structure in gray and some linking constraints in blue : @@ -34,54 +32,62 @@ two vectors $x_1$ and $x_2$ : \end{aligned} ``` -- $x_1$ and $x_2$ are the original variables of the problem -- $(1)$ are the linking constraints -- $(2)$ is the first subproblem -- $(3)$ is the second subproblem +- variables $x_1$ and $x_2$ are the original variables of the problem (duty: `OriginalVar`) +- constraints $(1)$ are the linking constraints (duty: `OriginalConstr`) +- constraints $(2)$ shapes the first subproblem (duty: `OriginalConstr`) +- constraints $(3)$ shapes the second subproblem (duty: `OriginalConstr`) When you apply a Dantzig-Wofe decomposition to this formulation, Coluna reformulates it into the following master problem : ```math \begin{aligned} -\min \quad& \sum\limits_{q \in Q_1} c_1' \tilde{x_1}^q \lambda_q + \sum\limits_{q \in Q_2} c_2' \tilde{x_2}^q \lambda_q\\ -\text{s.t.} \quad& \sum\limits_{q \in Q_1} A_1 \tilde{x_1}^q \lambda_q + \sum\limits_{q \in Q_2} A_2 \tilde{x_2}^q \lambda_q \geq b & (1)\\ -& L_1 \leq \sum\limits_{q \in Q_1} \lambda_q \leq U_1 & (2)\\ -& L_2 \leq \sum\limits_{q \in Q_2} \lambda_q \leq U_2 & (3)\\ +\min \quad& \sum\limits_{q \in Q_1} c_1' \tilde{x_1}^q \lambda_q + \sum\limits_{q \in Q_2} c_2' \tilde{x_2}^q \lambda_q + f'a \\ +\text{s.t.} \quad& \sum\limits_{q \in Q_1} A_1 \tilde{x_1}^q \lambda_q + \sum\limits_{q \in Q_2} A_2 \tilde{x_2}^q \lambda_q + a \geq b & (1)\\ +& L_1 \leq \sum\limits_{q \in Q_1} \tilde{z}_1\lambda_q \leq U_1 & (2)\\ +& L_2 \leq \sum\limits_{q \in Q_2} \tilde{z}_2\lambda_q \leq U_2 & (3)\\ & \lambda_q \geq 0, \quad q \in Q_1 \cup Q_2 \end{aligned} ``` -where $Q_1$ is the index-set of the solutions to the first subproblem and -$Q_2$ is the index-set of the solutions to the second subproblem. -The set of the solutions to the first and the second subproblems are $\{\tilde{x}^q_1\}_{q \in Q_1}$ and $\{\tilde{x}^q_2\}_{q \in Q_2}$ respectively. These solutions are expressed -in terms of the original variables. -The multiplicity of the subproblems is defined in the convexity constraints $(2)$ and $(3)$. $(1)$ is called the Master mixed constraint. -Lower and upper multiplicity are $1$ by default. +where: +- set $Q_1$ is the index set of the solutions to the first subproblem +- set $Q_2$ is the index set of the solutions to the second subproblem +- set of the solutions to the first is $\{\tilde{x}^q_1\}_{q \in Q_1}$ (duty: ` MasterRepPricingVar`) +- set of the solutions to the second subproblem is $\{\tilde{x}^q_2\}_{q \in Q_2}$ respectively (duty: ` MasterRepPricingVar`) +- constraint $(1)$ is the reformulation of the linking constraints (duty: `MasterMixedConstr`) +- constraint $(2)$ is the convexity constraint of the first subproblem and involves the lower $L_1$ and upper $U_1$ multiplicity of the subproblem (duty: `MasterConvexityConstr`) +- constraint $(3)$ is the convexity constraint of the second subproblem and involves the lower $L_2$ and upper $U_2$ multiplicity of the subproblem (duty: `MasterConvexityConstr`) +- variables $\tilde{z}_1$ and $\tilde{z}_2$ are representative of pricing setup variables in the master (always equal to $1$) (duty: `MasterRepPricingVar`) +- variables $\lambda_q$ are the columns (duty: `MasterCol`) +- variable $a$ is the artificial variable (duty: `MasterArtVar`) At the beginning of the column generation algorithm, the master formulation does not have any master columns. Therefore, the master may be infeasible. -To prevent this, Coluna adds a local artifical variable specific to each constraint of the master and a global artificial variable. -Costs of articial and global artificial variables can be defined in [Coluna.Params](@ref). +To prevent this, Coluna adds a local artificial variable $a$ specific to each constraint of the master and a global artificial variable. +Costs $f$ of artificial and global artificial variables can be defined in [Coluna.Params](@ref). Subproblems take the following form (here, it's the first subproblem) : ```math \begin{aligned} -\min \quad& \bar{c_1}' x_1\\ +\min \quad& \bar{c_1}' x_1 + z_1\\ \text{s.t.} \quad& D_1x_1 \geq d_1 & (1)\\ & \quad x_1 \geq 0 \end{aligned} - ``` -where $\bar{c}$ is the reduced cost of the original variables computed by the column generation algorithm. $(1)$ is called the Dantzig-Wolfe subproblem "pure constraint". +where: +- vector $\bar{c}$ is the reduced cost of the subproblem variables computed by the column generation algorithm. +- variables $x_1$ are the subproblem variables (duty: `DwSpPricingVar`) +- constraint $(1)$ is the subproblem constraint (duty: `DwSpPureConstr`) +- variable $z_1$ is the pricing setup variable (always equal to $1$) (duty: `DwSpSetupVar`) -### Dantzig-Wolfe with identical subproblems (alpha) -When some subproblems are identical (same coefficient matrix and right-hand side), +Lower and upper multiplicities of subproblems are $1$ by default. +However, when some subproblems are identical (same coefficient matrix and right-hand side), you can avoid solving all of them at each iteration by defining only one subproblem and -setting its multiplicity to the number of time it appears. See this [tutorial](@ref tuto_identical_sp) to get an example of Dantzig-Wolfe decomposition with identical subproblems. +setting its multiplicity to the number of times it appears. See this [tutorial](@ref tuto_identical_sp) to get an example of Dantzig-Wolfe decomposition with identical subproblems. ## Benders (alpha) @@ -94,7 +100,7 @@ in gray and some linking variables in blue : The intuition behind Benders decomposition is that some hard problems can become much easier with some of their variables fixed. Benders aims to divide the variables of the problem into two "levels": the 1st level variables which, once fixed, make it easier to find a solution for the remaining variables, the so-called 2nd-level variables. -The question is how to set the 1st level variables. Benders' theory proceeds by successive generation of cuts: given a 1st-level solution, we ask the following questions: +The question is how to set the 1st level variables. Benders' theory proceeds by the successive generation of cuts: given a 1st-level solution, we ask the following questions: - Is the subproblem infeasible? If so, then the 1st-level solution is not correct and must be eliminated. A feasibility cut will be derived from the dual subproblem and added to the master. - Does the aggregation of the master and subproblem solutions give rise to an optimal solution to the problem? It depends on a criterion that can be computed. If it is the case, we are done, else, we derive an optimality cut from the dual subproblem and add it into the master. @@ -136,7 +142,7 @@ and a subproblem: ``` with $\bar{x}$ a fixed solution for the master problem (i.e. valuations of the 1st-level variables) -Note that in the special case where the master problem is unbounded, the shape of the subproblem is slightly modified. See the [API](@ref api_benders) section to get more informations. +Note that in the special case where the master problem is unbounded, the shape of the subproblem is slightly modified. See the [API](@ref api_benders) section to get more information. This decomposition is an alpha feature.