Source code for benderslib.benders.ilshaped
# coding:utf-8
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2021-2026 Peng-Hui Guo <[email protected]>
from ..core import BendersParams, MasterProblem, SubProblems, BendersSolver
from ..cuts import IntegerLShapedOCGen, IntegerLShapedFCGen
[docs]
class IntegerLShaped(BendersSolver):
"""An implementation of :doc:`../tutorials/ilshaped`.
It is for two-stage stochastic programming with binary complicating variables and integer recourse.
It builds a Benders decomposition framework using the provided master problem,
subproblem, and complicating variables.
The optimality cut is defined by :class:`CombinatorialOC` and generated by :class:`IntegerLShapedOCGen`;
the feasibility cut is defined by :class:`NoGoodFC` and generated by :class:`IntegerLShapedFCGen`.
The integer L-shaped method is an extension of the L-shaped method and the Combinatorial Benders decomposition
to solve two-stage stochastic integer programming problems.
The cut used in this method are the same as those in Combinatorial Benders decomposition,
and the algorithmic framework is similar to that of the L-shaped method.
.. caution::
The class :class:`IntegerLShaped` requires the complicating variables to be **pure binary (0-1)**,
integer variables in the subproblems are allowed.
Parameters
----------
master_problem : MasterProblem
An instance of :class:`MasterProblem` representing the master problem.
sub_problem : SubProblems
An instance of :class:`SubProblems` representing the collection of subproblems.
complicating_vars : list[str]
A list of names of the binary complicating variables in the master problem.
params : BendersParams, optional
An instance of :class:`BendersParams` containing parameters for the Benders decomposition process.
If not provided, default parameters will be used.
Example
----------
.. code-block:: python
from benderslib import IntegerLShaped, MasterProblem, SubProblems
from benderslib.solvers import Gurobi
# Define master and subproblem models
master_model = ... # Define your master problem model here
sub_models = [...] # Define your list of subproblem models here
probs = [1/len(sub_models)] * len(sub_models) # Define probabilities for each scenario
# Initialize master and subproblems
mp = MasterProblem(Gurobi(master_model))
sp = SubProblems([Gurobi(sm) for sm in sub_models], prob=probs)
# Define complicating variables (must be binary)
complicating_vars = ['x1', 'x2', 'x3']
# Initialize and solve
BD = IntegerLShaped(mp, sp, complicating_vars)
BD.solve()
"""
def __init__(
self,
master_problem: MasterProblem,
sub_problem: SubProblems,
complicating_vars: list[str],
optimality_cut=IntegerLShapedOCGen,
feasibility_cut=IntegerLShapedFCGen,
params: BendersParams | None = None
):
super().__init__(
master_problem,
sub_problem,
complicating_vars,
optimality_cut,
feasibility_cut,
params
)
[docs]
@classmethod
def from_models(
cls,
master_model,
master_solver,
sub_model,
sub_solver,
complicating_vars,
optimality_cut=IntegerLShapedOCGen,
feasibility_cut=IntegerLShapedFCGen,
prob=None,
params: BendersParams | None = None
):
return super().from_models(
master_model,
master_solver,
sub_model,
sub_solver,
complicating_vars,
optimality_cut,
feasibility_cut,
prob,
params
)