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 )