# coding:utf-8
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2021-2026 Peng-Hui Guo <[email protected]>
from ..core import BendersParams, MasterProblem, SubProblem, BendersSolver
from ..cuts import GeneralizedOCGen, GeneralizedFCGen
[docs]
class GeneralizedBenders(BendersSolver):
"""An implementation of :doc:`../tutorials/gbd`.
It builds a Benders decomposition framework using the provided master problem,
subproblem, and complicating variables.
The optimality cut is defined by :class:`GeneralizedOC` and generated by :class:`GeneralizedOCGen`;
the feasibility cut is defined by :class:`GeneralizedFC` and generated by :class:`GeneralizedFCGen`.
.. caution::
- Currently, the class :class:`GeneralizedBenders` requires the problem meets certain conditions.
- **Original Problem**: The original problem must be **linearly separable**, i.e., the objective
function can be written as :math:`f(x,y) = f_x(x) + f_y(y)`, and the constraints can be written as
:math:`g(x,y) = g_x(x) + g_y(y) \\leq 0`.
- **Master Problem**: Constraints must be **linear** in terms of the complicating variables (necessary for
linear Benders cuts).
There are no restrictions on the objective function or decision variable types from BendersLib's perspective.
- **Subproblem**: To derive *optimality cuts*, the subproblem must be a **convex optimization** problem
(with decision variables being continuous); to derive *feasibility cuts*,
the subproblem constraints must form a **linear system** with decision variables being continuous.
When you need both types of cuts, the subproblem must satisfy both conditions.
- There are also limitations from :doc:`solver backends <../manual/solvers>` regarding the types of problems
that can be handled, please refer to the documentation of each solver for details.
Parameters
----------
master_problem : MasterProblem
An instance of :class:`MasterProblem` representing the master problem.
sub_problem : SubProblem
An instance of :class:`SubProblem` representing the subproblem.
complicating_vars : list[str]
A list of names of the complicating variables.
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 GeneralizedBenders, MasterProblem, SubProblem
from benderslib.solvers import Gurobi
# Define master and subproblem models
master_model = ... # Define your linear master problem model here
sub_model = ... # Define your convex nonlinear subproblem model here
# Initialize master and subproblem
mp = MasterProblem(Gurobi(master_model))
sp = SubProblem(Gurobi(sub_model))
# Define complicating variables
complicating_vars = ['x1', 'x2', 'x3']
# Initialize and solve
BD = GeneralizedBenders(mp, sp, complicating_vars)
BD.solve()
"""
def __init__(
self,
master_problem: MasterProblem,
sub_problem: SubProblem,
complicating_vars: list[str],
optimality_cut=GeneralizedOCGen,
feasibility_cut=GeneralizedFCGen,
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=GeneralizedOCGen,
feasibility_cut=GeneralizedFCGen,
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
)