BilevelJuMP.ONE_ONEConstant

Activates the indicator constraint on the primal constraint if the auxiliaty binary is one and activates the indicator constraint on the dual variable if the auxiliary binary is one.

BilevelJuMP.ZERO_ONEConstant

Activates the indicator constraint on the primal constraint if the auxiliaty binary is zero and activates the indicator constraint on the dual variable if the auxiliary binary is one.

BilevelJuMP.ZERO_ZEROConstant

Activates the indicator constraint on the primal constraint if the auxiliaty binary is zero and activates the indicator constraint on the dual variable if the auxiliary binary is zero.

BilevelJuMP.BigMModeType
BigMMode(; with_slack = false, primal_big_M = Inf, dual_big_M = Inf)

Used to solve a bilevel problem with the MPEC reformulation using Fortuny-Amat and McCarl's big-M method to convert complementarity constraints to a mixed integer formulation.

• with_slack indicates whether to use slack variables to convert the complementarity constraints to a mixed integer formulation. If false, the reformulation of a constraint like expr <= 0 is expr <= big_M * (1 - binary) and var <= big_M * binary, where var is the associated dual variable. If true, the reformulation is expr == slack, slack <= big_M * (1 - binary) and var <= big_M * binary.

• primal_big_M is a big-M used to primal variables that have no bounds so we can compute the big-M for the primal constraint.

• dual_big_M is a big-M used to dual variables that have no bounds so we can compute the big-M for the dual constraint.

Also known as FortunyAmatMcCarlMode (which can be used interchangeably).

BilevelJuMP.BilevelModelType
BilevelModel()

Create an empty BilevelModel with default settings, no solver and no solve mode.

Example

julia> model = BilevelModel()
BilevelModel(solver::Function; mode = BilevelJuMP.SOS1Mode(), add_bridges::Bool = true)

Create a BilevelModel with the given solver and solve mode.

• solver: is a functions that takes no arguments and returns a JuMP solver object.
• mode: is a solve mode object that defines how the model is solved.
• add_bridges: if true (default) then bridges are added to the model. If false then bridges are not added and the model is not modified.

Example

julia> model = BilevelModel(
HiGHS.Optimizer,
mode = BilevelJuMP.FortunyAmatMcCarlMode(primal_big_M = 1e6, dual_big_M = 1e6))

which is equivalent to

julia> model = BilevelModel(
()->HiGHS.Optimizer(),
mode = BilevelJuMP.FortunyAmatMcCarlMode(primal_big_M = 1e6, dual_big_M = 1e6))

and equivalent to

julia> model = BilevelModel()

julia> BilevelJuMP.set_solver(model, HiGHS.Optimizer)

julia> BilevelJuMP.set_mode(model, BilevelJuMP.FortunyAmatMcCarlMode(primal_big_M = 1e6, dual_big_M = 1e6))
BilevelJuMP.ComplementModeType
ComplementMode(; with_slack = false)

Used to solve a bilevel problem with the MPEC reformulation using actual complementarity constraints. A limited number of solvers support this mode. One example is Knitro.

• with_slack indicates whether to use slack variables to reformulate the complementarity constraints. Given a pair expr and var, the reformulation is expr == slack and var ⟂ slack instead of expr ⟂ slack.
BilevelJuMP.DualOfType
DualOf(constraint::ConstraintRef)

Get the dual variable associated with a constraint. This is only valid for constraints in the upper level of a bilevel model.

Examples

julia> m = BilevelModel();

julia> @variable(Lower(m), x >= 0);

julia> @constraint(Lower(m), c, x <= 1);

julia> @variable(Upper(m), y, DualOf(c));
BilevelJuMP.IndicatorModeType
IndicatorMode(method::IndicatorSetting = BilevelJuMP.ONE_ONE)

Used to solve a bilevel problem with the MPEC reformulation using indicator constaints to convert complementarity constraints to a mixed integer formulation.

• method indicates how the indicator constraints are activated for primal cosntraints and dual variables. See IndicatorSetting for more details.
BilevelJuMP.MixedModeType
MixedMode(; default = SOS1Mode())

A mode that allows to mix different modes for different constraints and variables.

• default is the default mode to use for all constraints and variables that are not explicitly mapped to a mode.
BilevelJuMP.ProductModeType
ProductMode(epsilon = 0.0; with_slack = false, aggregation_group = nothing)

Used to solve a bilevel problem with the MPEC reformulation using products to convert complementarity constraints into non-convex quadratic constraints.

• with_slack indicates whether to use slack variables to reformulate the complementarity constraints. Given a pair expr and var, the reformulation is expr == slack and var * slack == 0 instead of expr * slack == 0.

• aggregation_group indicates whether to aggregate the products into a single quadratic constraint. If aggregation_group is nothing, then each product is converted into a quadratic constraint. If aggregation_group is a positive integer, then products with the same aggregation_group are aggregated into a single quadratic constraint.

BilevelJuMP.SOS1ModeType
SOS1Mode()

Used to solve a bilevel problem with the MPEC reformulation using SOS1 constraints to convert complementarity constraints into mixed-integer constraints.

BilevelJuMP.StrongDualityModeType
StrongDualityMode(eps = 0.0, inequality = true)

A mode that adds a strong duality constraint of the lower level problem instead of reformulating the complementarity constraints.

• eps: The tolerance for the strong duality constraint. Defaults to 0.0.

• inequality: If true the strong duality constraint is added as two inequality constraints. If false the strong duality constraint is added as an equality constraint. Defaults to true.

BilevelJuMP.LowerMethod
Lower(model::BilevelModel)

Create a reference to the lower level of a bilevel model.

Example

julia> model = BilevelModel();

julia> @variable(Lower(model), x >= 0)
BilevelJuMP.LowerOnlyMethod
LowerOnly(model::BilevelModel)

Create a special reference to the lower level of a bilevel model. Variables created with this reference will not be shared with the upper level.

BilevelJuMP.UpperMethod
Upper(model::BilevelModel)

Create a reference to the upper level of a bilevel model.

Example

julia> model = BilevelModel();

julia> @variable(Upper(model), x >= 0)
BilevelJuMP.UpperOnlyMethod
UpperOnly(model::BilevelModel)

Create a special reference to the upper level of a bilevel model. Variables created with this reference will not be shared with the lower level.

BilevelJuMP.get_dual_lower_bound_hintMethod
get_dual_lower_bound_hint(cref)

Get the lower bound to the dual variable of the constraint cref that was set with set_dual_lower_bound_hint.

BilevelJuMP.get_dual_upper_bound_hintMethod
get_dual_upper_bound_hint(cref)

Get the upper bound to the dual variable of the constraint cref that was set with set_dual_upper_bound_hint.

BilevelJuMP.get_modeMethod
get_mode(vi::BilevelVariableRef)

Get the mode of the bounds of a variable. This is used in MixedMode reformulations.

BilevelJuMP.get_modeMethod
get_mode(ci::BilevelConstraintRef)

Get the mode of a constraint. This is used in MixedMode reformulations.

BilevelJuMP.get_primal_lower_bound_hintMethod
get_primal_lower_bound_hint(cref)

Get the lower bound to the primal variable of the constraint cref that was set with set_primal_lower_bound_hint.

BilevelJuMP.get_primal_upper_bound_hintMethod
get_primal_upper_bound_hint(cref)

Get the upper bound to the primal variable of the constraint cref that was set with set_primal_upper_bound_hint.

BilevelJuMP.set_dual_lower_bound_hintMethod
set_dual_lower_bound_hint(cref, value)

Set a lower bound to the dual variable of the constraint cref to value. This bound will not be dualized. The dual lower bound hint is used to help the solution method.

Solution modes can be benefitted from this hint:

• BigMMode will use this information to compute a tighter bound for the dual variable.

• Other modes will be stabilized by the existence of the bounds on variables that would otherwise no be bounded.

• Bounds that are not dualized are also useful for binary expansions of products of variables that can be done with QuadraticToBinary.jl.

BilevelJuMP.set_dual_upper_bound_hintMethod
set_dual_upper_bound_hint(cref, value)

Set a upper bound to the dual variable of the constraint cref to value. This bound will not be dualized. The dual upper bound hint is used to help the solution method.

Solution modes can be benefitted from this hint:

• BigMMode will use this information to compute a tighter bound for the dual variable.

• Other modes will be stabilized by the existence of the bounds on variables that would otherwise no be bounded.

• Bounds that are not dualized are also useful for binary expansions of products of variables that can be done with QuadraticToBinary.jl.

BilevelJuMP.set_modeMethod
set_mode(vi::BilevelVariableRef, mode::AbstractBilevelSolverMode)

Set the mode of the bounds of a variable. This is used in MixedMode reformulations.

BilevelJuMP.set_modeMethod
set_mode(ci::BilevelVariableRef, mode::AbstractBilevelSolverMode)

Set the mode of a constraint. This is used in MixedMode reformulations.

BilevelJuMP.set_primal_lower_bound_hintMethod
set_primal_lower_bound_hint(vref, value)

Set a lower bound to the prima variable vref to value. This bound will not be dualized. The lower bound hint is used to help the solution method.

Solution modes can be benefitted from this hint:

• BigMMode will use this information to compute a tighter bound for the primal constraint variable.

• Other modes will be stabilized by the existence of the bounds on variables that would otherwise no be bounded.

• Bounds that are not dualized are also useful for binary expansions of products of variables that can be done with QuadraticToBinary.jl.

BilevelJuMP.set_primal_upper_bound_hintMethod
set_primal_upper_bound_hint(vref, value)

Set a upper bound to the prima variable vref to value. This bound will not be dualized. The upper bound hint is used to help the solution method.

Solution modes can be benefitted from this hint:

• BigMMode will use this information to compute a tighter bound for the primal constraint variable.

• Other modes will be stabilized by the existence of the bounds on variables that would otherwise no be bounded.

• Bounds that are not dualized are also useful for binary expansions of products of variables that can be done with QuadraticToBinary.jl.

BilevelJuMP.solve_with_MibSMethod
solve_with_MibS(model::BilevelModel, mibs_call; kwargs...)

Inputs

• model::BilevelModel: the model to optimize
• mibs_call: shoul be MibS_jll.mibs remember to import MibS_jll before.
• verbose_results::Bool = false: controls the verbosity of the solver output.

If verbose_results=false, nothing is printed. Set to true to display the MibS output.

• verbose_file::Bool = false: Writes MibS input files to screen.
• keep_files::Bool = false: Saves MibS input files to pwd().

Outputs

This function returns a NamedTuple with fields:

• status::Bool: true if the problem is feasible and has an optimal solution. false otherwise.
• objective::Float64: objective value (cost) of the upper problem
• nonzero_upper::Dict{Int, Float64}: it returns Dict{index => value}, in which the index refers to the index of upper variables with non zero values and the index starts from 0. Here, the order of the variables is based on their order of appearance in the MPS file.
• nonzero_lower::Dict{Int, Float64}: it has the same structure as nonzero_upper, but it represents the index of non-zero variables in the lower problem.
• all_upper::Dict{String, Float64}: it returns Dict{name => value} which contains all upper variables values (zero and non-zero). For recalling the variables, you need to use the same name as you used to define the variables, e.g., for @variable(Upper(model), y, Int), we need to use all_upper["y"] to get the value of the variable y.
• all_lower::Dict{String, Float64}: it has the same structure as the all_upper but is defined for lower variables.
• all_var::Dict{MOI.VariableIndex, Float64}: it contains information on all variables (upper and lower) in the format of MOI.VariableIndex and their output values.
Warning

Currently, MibS is designed to solve MIP-MIP problems only. Thus, if you define LP-MIP, MIP-LP, or LP-LP, it will throw an error.

BilevelJuMP.unset_modeMethod
unset_mode(vi::BilevelVariableRef)

Unset the mode of the bounds of a variable. This will use the default mode for the bounds. This is used in MixedMode reformulations.

BilevelJuMP.unset_modeMethod
unset_mode(ci::BilevelConstraintRef)

Unset the mode of a constraint. This will use the default mode for the constraint. This is used in MixedMode reformulations.