### Set Initial Starting Conditions Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/FOBP_example3 Configures starting values for primal and dual variables to assist the solver. ```julia JuMP.set_start_value.(x, 0) JuMP.set_start_value.(ya, 1) JuMP.set_start_value.(yb, 0) JuMP.set_start_value(z, 1) for i in 1:I JuMP.set_dual_start_value.(b1, 0) JuMP.set_dual_start_value.(b2, 0) JuMP.set_dual_start_value.(b3, -1) end ``` -------------------------------- ### Install BilevelJuMP Source: https://joaquimg.github.io/BilevelJuMP.jl/stable Use the Julia package manager to add the BilevelJuMP package. ```julia julia> import Pkg julia> Pkg.add("BilevelJuMP") ``` -------------------------------- ### Initialize QuadraticToBinary with HiGHS Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/quad_to_bin Standard setup for using QuadraticToBinary with the HiGHS solver in a BilevelModel. ```julia using BilevelJuMP, QuadraticToBinary, HiGHS SOLVER = HiGHS.Optimizer() Q_SOLVER = QuadraticToBinary.Optimizer{Float64}(SOLVER, lb = -10, ub = 10) model = BilevelModel(()->Q_SOLVER, mode = BilevelJuMP.ProductMode(1e-6)) @variable(Lower(model), x) @variable(Upper(model), y) @objective(Upper(model), Min, 3x + y) @constraints(Upper(model), begin x <= 5 y <= 8 y >= 0 end) @objective(Lower(model), Min, -x) @constraints(Lower(model), begin x + y <= 8 4x + y >= 8 2x + y <= 13 2x - 7y <= 0 end) optimize!(model) objective_value(model) @assert abs(objective_value(model) - (3 * (3.5 * 8/15) + 8/15)) < 1e-1 # src ``` -------------------------------- ### set_pass_start(model::BilevelModel) Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Manages passing start values to the solver. ```APIDOC ## set_pass_start(model::BilevelModel) ## get_pass_start(model::BilevelModel) ## unset_pass_start(model::BilevelModel) ### Description Functions to activate, check, or deactivate passing start values (primal and dual) to the solver. ``` -------------------------------- ### Setting JuMP Start Values Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/conic_lower Alternative syntax for defining initial values for variables and duals in JuMP. ```julia set_start_value(x, 6) set_dual_start_value(con2, 0) ``` ```julia 0 ``` -------------------------------- ### Manage pass start values attribute Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Controls whether primal and dual start values are passed to the solver. ```julia set_pass_start(model::BilevelModel) ``` ```julia get_pass_start(model::BilevelModel) ``` ```julia unset_pass_start(model::BilevelModel) ``` -------------------------------- ### IPOPT Solver Output Log Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/conic_lower Example of an iterative solver log showing objective values, infeasibility metrics, and final convergence statistics. ```text 22r 7.1782285e+00 9.24e-01 1.00e+03 0.1 0.00e+00 - 0.00e+00 4.09e-07R 3 23r 7.2536425e+00 9.25e-01 1.21e+03 0.1 1.19e+03 - 9.06e-03 1.17e-03f 1 24 7.2536348e+00 9.25e-01 1.10e+05 -1.0 9.53e-01 -0.1 9.22e-01 1.70e-05h 1 25r 7.2536348e+00 9.25e-01 1.00e+03 -0.0 0.00e+00 - 0.00e+00 2.59e-07R 6 26r 7.5343972e+00 9.34e-01 1.22e+03 -0.0 9.54e+01 - 8.79e-03 3.97e-03f 1 27r 7.5327092e+00 9.46e-01 9.90e+02 -0.0 1.70e+00 2.0 1.33e-01 1.52e-02f 1 28r 7.5181606e+00 9.80e-01 9.71e+02 -0.0 7.28e-01 2.4 2.49e-03 1.46e-01f 1 29r 7.5135600e+00 9.88e-01 9.55e+02 -0.0 7.04e-01 2.9 6.85e-02 2.06e-01f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 30r 7.5135662e+00 9.88e-01 2.66e+03 -0.0 8.57e-02 3.3 1.00e+00 1.86e-02h 1 31r 7.5227783e+00 9.94e-01 9.97e+00 -0.0 1.58e-02 2.8 1.00e+00 1.00e+00f 1 32r 7.5237814e+00 1.00e+00 1.29e+00 -1.4 6.12e-03 2.3 1.00e+00 1.00e+00f 1 33r 7.5248565e+00 1.00e+00 1.37e-01 -2.1 1.95e-03 1.8 1.00e+00 1.00e+00f 1 34r 7.5265535e+00 1.00e+00 7.02e+01 -3.2 3.47e-03 - 1.00e+00 7.46e-01f 1 35r 9.2295707e+00 1.00e+00 6.44e+02 -3.2 2.52e+00 - 4.06e-01 9.10e-01f 1 36r 9.1585683e+00 1.00e+00 2.89e+02 -3.2 2.61e-01 1.4 6.81e-01 1.00e+00h 1 37r 9.1584002e+00 1.00e+00 8.13e+01 -3.2 1.15e-03 1.8 5.41e-01 8.53e-01h 1 38r 9.1611165e+00 1.00e+00 4.80e+01 -3.2 3.20e-03 1.3 1.57e-01 1.00e+00f 1 39r 9.1870694e+00 9.90e-01 5.54e+01 -3.2 3.68e-02 1.7 3.29e-02 8.23e-01f 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 40r 9.1893066e+00 9.72e-01 4.56e+01 -3.2 1.82e-02 3.1 6.00e-01 1.00e+00f 1 41r 9.1979046e+00 9.52e-01 2.81e+01 -3.2 6.66e-02 2.6 3.62e-01 3.05e-01f 1 42r 9.3297133e+00 8.04e-01 7.97e+01 -3.2 1.08e+00 2.1 5.48e-02 1.62e-01f 1 43 9.3307037e+00 8.04e-01 6.64e+03 -1.0 2.93e+01 -0.6 6.97e-02 4.51e-05f 1 44 9.9071010e+00 7.70e-01 1.39e+04 -1.0 1.82e+01 -1.1 1.23e-01 4.22e-02f 2 45 1.1984910e+01 5.61e-01 2.05e+04 -1.0 1.22e+01 -0.6 3.78e-01 2.72e-01H 1 46 1.2009065e+01 3.55e-01 9.73e+04 -1.0 5.61e-01 0.7 1.00e+00 3.66e-01h 1 47 1.2007891e+01 2.63e-01 2.24e+05 -1.0 3.55e-01 1.1 1.00e+00 2.59e-01h 1 48 1.2015766e+01 1.20e-01 2.26e+05 -1.0 2.63e-01 0.6 1.00e+00 5.43e-01h 1 49 1.2021975e+01 5.78e-02 3.75e+05 -1.0 1.20e-01 1.1 1.00e+00 5.20e-01h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 50 1.2032201e+01 2.04e-02 4.94e+05 -1.0 7.12e-02 0.6 1.00e+00 6.46e-01h 1 51 1.2053842e+01 6.82e-03 8.67e+05 -1.0 7.96e-02 0.1 1.00e+00 6.66e-01h 1 52 1.2068410e+01 8.41e-04 4.74e+05 -1.0 3.85e-02 0.5 1.00e+00 8.77e-01h 1 53 1.2084847e+01 0.00e+00 5.33e+00 -1.0 3.41e-02 0.1 1.00e+00 1.00e+00f 1 54 1.2023010e+01 2.22e-16 1.51e+05 -5.7 1.26e-01 -0.4 9.84e-01 1.00e+00f 1 55 1.1999979e+01 0.00e+00 2.91e+02 -5.7 5.58e-02 - 9.98e-01 8.16e-01h 1 56 1.1999973e+01 0.00e+00 4.25e-06 -5.7 3.02e-04 - 1.00e+00 1.00e+00h 1 57 1.1999970e+01 0.00e+00 5.91e+00 -8.6 5.01e-06 - 9.68e-01 1.00e+00h 1 58 1.1999970e+01 0.00e+00 2.61e-10 -8.6 1.18e-07 - 1.00e+00 1.00e+00h 1 Number of Iterations....: 58 (scaled) (unscaled) Objective...............: 1.1999969855039765e+01 1.1999969855039765e+01 Dual infeasibility......: 2.6066093158514153e-10 2.6066093158514153e-10 Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00 Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00 Complementarity.........: 2.5705110524677697e-09 2.5705110524677697e-09 Overall NLP error.......: 2.5705110524677697e-09 2.5705110524677697e-09 Number of objective function evaluations = 77 Number of objective gradient evaluations = 43 Number of equality constraint evaluations = 77 Number of inequality constraint evaluations = 77 Number of equality constraint Jacobian evaluations = 62 Number of inequality constraint Jacobian evaluations = 62 Number of Lagrangian Hessian evaluations = 58 Total seconds in IPOPT = 0.039 EXIT: Optimal Solution Found. ``` -------------------------------- ### Configure SCIP for QuadraticToBinary Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/quad_to_bin Setup required for solvers like SCIP that require a CachingOptimizer wrapper. ```julia using SCIP ``` ```julia SOLVER = SCIP.Optimizer() CACHED_SOLVER = MOI.Utilities.CachingOptimizer( MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()), SOLVER) Q_SOLVER = QuadraticToBinary.Optimizer{Float64}(CACHED_SOLVER) BilevelModel(()->Q_SOLVER, mode = BilevelJuMP.ProductMode(1e-5)) ``` -------------------------------- ### Install HiGHS solver Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/getting_started Add the HiGHS solver package to enable solving the optimization models. ```julia import Pkg Pkg.add("HiGHS") ``` -------------------------------- ### Get model build time Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Returns the duration taken to build the bilevel model. ```julia build_time(model::BilevelModel) ``` -------------------------------- ### Define Variables Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/FOBP_example2 Defines variables for the upper and lower levels with initial start values. ```julia @variable(Upper(model), y, start = 8 / 15) @variable(Lower(model), x, start = 3.5 * 8 / 15) ``` -------------------------------- ### Get bilevel component mode Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Retrieves the current mode for a constraint or variable bounds. ```julia get_mode(ci::BilevelConstraintRef) ``` ```julia get_mode(vi::BilevelVariableRef) ``` -------------------------------- ### Get dual upper bound hint Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Retrieves the dual upper bound hint previously set for a constraint. ```julia get_dual_upper_bound_hint(cref) ``` -------------------------------- ### Get dual lower bound hint Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Retrieves the dual lower bound hint previously set for a constraint. ```julia get_dual_lower_bound_hint(cref) ``` -------------------------------- ### Get primal upper bound hint Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Retrieves the primal upper bound hint previously set for a constraint. ```julia get_primal_upper_bound_hint(cref) ``` -------------------------------- ### Get primal lower bound hint Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Retrieves the primal lower bound hint previously set for a constraint. ```julia get_primal_lower_bound_hint(cref) ``` -------------------------------- ### Initialize Bilevel Model Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/FOBP_example4 Sets up the BilevelModel using the Ipopt solver and ProductMode. ```julia using BilevelJuMP using Ipopt model = BilevelModel(Ipopt.Optimizer; mode = BilevelJuMP.ProductMode(1e-9)) ``` -------------------------------- ### Initialize Bilevel Model Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/SOCBLP_example1 Sets up the BilevelModel with the required SOCtoNonConvexQuad bridge and Ipopt optimizer. ```julia using BilevelJuMP using Ipopt model = BilevelModel( () -> MOI.Bridges.Constraint.SOCtoNonConvexQuad{Float64}(Ipopt.Optimizer()); mode = BilevelJuMP.ProductMode(1e-9), ) ``` -------------------------------- ### Configure BilevelModel step-by-step Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/getting_started Initializes an empty model and configures the optimizer and mode sequentially. ```julia julia> model = BilevelModel() julia> set_optimizer(model, HiGHS.Optimizer) julia> BilevelJuMP.set_mode(model, BilevelJuMP.FortunyAmatMcCarlMode(primal_big_M = 100, dual_big_M = 100)) ``` -------------------------------- ### get_mode(ci::BilevelConstraintRef) Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Gets the mode of a constraint or variable bounds. ```APIDOC ## get_mode(ci::BilevelConstraintRef) ## get_mode(vi::BilevelVariableRef) ### Description Get the mode of a constraint or the bounds of a variable. Used in MixedMode reformulations. ``` -------------------------------- ### Configure and Optimize with ProductMode Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/modes Sets the optimizer to Ipopt and the bilevel mode to ProductMode before running the optimization. ```julia set_optimizer(model, Ipopt.Optimizer) BilevelJuMP.set_mode(model, BilevelJuMP.ProductMode()) optimize!(model) objective_value(model) @assert abs(objective_value(model) - (3 * (7/2 * 8/15) + 8/15)) < 1e-1 # src ``` -------------------------------- ### Initialize Bilevel Model Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/MibS_example1 Imports necessary packages and initializes a new BilevelModel. ```julia using BilevelJuMP using Test using MibS_jll model = BilevelModel() ``` -------------------------------- ### Load required packages Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/lower_duals Imports the necessary libraries for bilevel modeling and optimization. ```julia using BilevelJuMP using Ipopt using QuadraticToBinary using HiGHS ``` -------------------------------- ### Configure Solver and Solution Method Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/lower_duals Set the optimizer to use the QuadraticToBinary wrapper with HiGHS and apply the Fortuny-Amat and McCarl solution mode. ```julia set_optimizer(model, ()->QuadraticToBinary.Optimizer{Float64}(HiGHS.Optimizer())) BilevelJuMP.set_mode(model, BilevelJuMP.FortunyAmatMcCarlMode(dual_big_M = 100)) optimize!(model) ``` -------------------------------- ### Get dual variable of a constraint Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Retrieves the dual variable associated with a constraint in the upper level. ```julia julia> m = BilevelModel(); julia> @variable(Lower(m), x >= 0); julia> @constraint(Lower(m), c, x <= 1); julia> @variable(Upper(m), y, DualOf(c)); ``` -------------------------------- ### Create a BilevelModel with solver and mode Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Initializes a BilevelModel with a specific solver and solve mode. ```julia julia> model = BilevelModel( HiGHS.Optimizer, mode = BilevelJuMP.FortunyAmatMcCarlMode(primal_big_M = 1e6, dual_big_M = 1e6)) ``` ```julia julia> model = BilevelModel( ()->HiGHS.Optimizer(), mode = BilevelJuMP.FortunyAmatMcCarlMode(primal_big_M = 1e6, dual_big_M = 1e6)) ``` ```julia 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)) ``` -------------------------------- ### Get lower level objective value Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Retrieves the objective function value of the lower level problem. ```julia lower_objective_value(model::BilevelModel; result::Int = 1) ``` -------------------------------- ### Create an empty BilevelModel Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Initializes a BilevelModel with default settings. ```julia julia> model = BilevelModel() ``` -------------------------------- ### Display Model Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/getting_started Print the structure of the bilevel model to verify the levels and constraints. ```julia julia> print(model) ``` -------------------------------- ### Configure and Optimize with StrongDualityMode Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/modes Sets the optimizer to Ipopt and the bilevel mode to StrongDualityMode before running the optimization. ```julia set_optimizer(model, Ipopt.Optimizer) BilevelJuMP.set_mode(model, BilevelJuMP.StrongDualityMode()) optimize!(model) objective_value(model) @assert abs(objective_value(model) - (3 * (7/2 * 8/15) + 8/15)) < 1e-1 # src ``` -------------------------------- ### Define and solve a bilevel optimization problem Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/getting_started Initializes a bilevel model using the Fortuny-Amat-McCarl reformulation, defines hierarchical levels, and retrieves the optimal solution. ```julia julia> using BilevelJuMP julia> using HiGHS julia> model = BilevelModel( HiGHS.Optimizer, mode = BilevelJuMP.FortunyAmatMcCarlMode(primal_big_M = 100, dual_big_M = 100)) An Abstract JuMP Model Feasibility problem with: Variables: 0 Upper Constraints: 0 Lower Constraints: 0 Bilevel Model Solution method: BilevelJuMP.BigMMode{Float64}(false, 100.0, 100.0, BilevelJuMP.ComplementBoundCache(Dict{MathOptInterface.VariableIndex, BilevelJuMP.BilevelVariableInfo}(), Dict{MathOptInterface.VariableIndex, BilevelJuMP.BilevelVariableInfo}(), Dict{MathOptInterface.ConstraintIndex, BilevelJuMP.BilevelConstraintInfo}(), Dict{MathOptInterface.VariableIndex, BilevelJuMP.BilevelVariableInfo}())) Solver name: HiGHS julia> @variable(Lower(model), x) x julia> @variable(Upper(model), y) y julia> @objective(Upper(model), Min, 3x + y) 3 x + y julia> @constraint(Upper(model), u1, x <= 5) u1 : x ≤ 5 julia> @constraint(Upper(model), u2, y <= 8) u2 : y ≤ 8 julia> @constraint(Upper(model), u3, y >= 0) u3 : y ≥ 0 julia> @objective(Lower(model), Min, -x) -x julia> @constraint(Lower(model), l1, x + y <= 8) l1 : x + y ≤ 8 julia> @constraint(Lower(model), l2, 4x + y >= 8) l2 : 4 x + y ≥ 8 julia> @constraint(Lower(model), l3, 2x + y <= 13) l3 : 2 x + y ≤ 13 julia> @constraint(Lower(model), l4, 2x - 7y <= 0) l4 : 2 x - 7 y ≤ 0 julia> print(model) Upper level: Min 3 x + y Subject to u3 : y ≥ 0 u1 : x ≤ 5 u2 : y ≤ 8 Lower level: Min -x Subject to l2 : 4 x + y ≥ 8 l1 : x + y ≤ 8 l3 : 2 x + y ≤ 13 l4 : 2 x - 7 y ≤ 0 julia> optimize!(model) ┌ Warning: primal_var_dual_quad_slack field is deprecated, use primal_var_in_quad_obj_to_dual_slack_var instead └ @ Dualization ~/.julia/packages/Dualization/ihzlf/src/structures.jl:268 ┌ Warning: primal_parameter field is deprecated, use primal_parameter_to_dual_parameter instead └ @ Dualization ~/.julia/packages/Dualization/ihzlf/src/structures.jl:265 Running HiGHS 1.5.1 [date: 1970-01-01, git hash: 93f1876e4] Copyright (c) 2023 HiGHS under MIT licence terms WARNING: Row 0 has infeasibility of 1 from [lower, value, upper] = [ -1; 0; -1] WARNING: Row 2 has infeasibility of 8 from [lower, value, upper] = [ 8; 0; inf] Solution has num max sum Col infeasibilities 0 0 0 Integer infeasibilities 0 0 0 Row infeasibilities 4 13 30 Row residuals 0 0 0 Attempting to find feasible solution of continuous variables for user-supplied values of discrete variables Presolving model 13 rows, 6 cols, 24 nonzeros Problem status detected on presolve: Infeasible Model status : Infeasible Objective value : 0.0000000000e+00 HiGHS run time : 0.00 Presolving model 13 rows, 10 cols, 32 nonzeros 13 rows, 10 cols, 32 nonzeros Solving MIP model with: 13 rows 10 cols (4 binary, 0 integer, 0 implied int., 6 continuous) 32 nonzeros Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time 0 0 0 0.00% 0 inf inf 0 0 0 0 0.0s R 0 0 0 0.00% 6.133333333 6.133333333 0.00% 0 0 0 5 0.0s Solving report Status Optimal Primal bound 6.13333333333 Dual bound 6.13333333333 Gap 0% (tolerance: 0.01%) Solution status feasible 6.13333333333 (objective) 0 (bound viol.) 0 (int. viol.) 0 (row viol.) Timing 0.00 (total) 0.00 (presolve) 0.00 (postsolve) Nodes 1 LP iterations 6 (total) 0 (strong br.) 0 (separation) 0 (heuristics) julia> termination_status(model) OPTIMAL::TerminationStatusCode = 1 julia> primal_status(model) FEASIBLE_POINT::ResultStatusCode = 1 julia> dual_status(Lower(model)) FEASIBLE_POINT::ResultStatusCode = 1 julia> dual_status(Upper(model)) NO_SOLUTION::ResultStatusCode = 0 julia> objective_value(model) 6.133333333333333 julia> objective_value(Lower(model)) -1.8666666666666667 julia> objective_value(Upper(model)) 6.133333333333333 julia> value(x) 1.8666666666666667 julia> value(y) 0.5333333333333332 julia> dual(l1) 1-element Vector{Float64}: 0.0 julia> dual(l2) 1-element Vector{Float64}: 49.75 ``` -------------------------------- ### Load BilevelJuMP and Solver Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/getting_started Load the BilevelJuMP package and a compatible solver like HiGHS. ```julia julia> using BilevelJuMP ``` ```julia julia> using HiGHS ``` -------------------------------- ### Verify Solution Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/MibS_example2 Run tests to verify the solution status and objective value. ```julia @test solution.status == true @test solution.objective ≈ -8.0 @test solution.nonzero_upper == Dict(0 => 6.0) @test solution.nonzero_lower == Dict(0 => 5.0) @test solution.all_upper["x"] == 6.0 @test solution.all_upper["z"] == 0 @test solution.all_lower["y"] == 5.0 ``` -------------------------------- ### Solve and Verify Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/SOCBLP_example1 Executes the optimization and retrieves the results. ```julia optimize!(model) primal_status(model) termination_status(model) objective_value(model) value.(y) ``` -------------------------------- ### Configure and Solve Bilevel Model Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/lower_duals Sets the reformulation mode to Strong Duality and optimizes the model using the Ipopt solver. ```julia BilevelJuMP.set_mode(model, BilevelJuMP.StrongDualityMode()) set_optimizer(model, Ipopt.Optimizer) optimize!(model) ``` -------------------------------- ### Solve Bilevel Model with Ipopt and SOC Bridge Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/conic_lower Configures the model to use the ProductMode and the SOCtoNonConvexQuad bridge to handle second-order cones with Ipopt. ```julia using Ipopt BilevelJuMP.set_mode(model, BilevelJuMP.ProductMode(1e-5)) set_optimizer(model, ()->MOI.Bridges.Constraint.SOCtoNonConvexQuad{Float64}(Ipopt.Optimizer())) optimize!(model) ``` -------------------------------- ### Initialize BilevelModel with optimizer attributes Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/getting_started Passes solver attributes directly during the construction of the BilevelModel using optimizer_with_attributes. ```julia julia> model = BilevelModel( optimizer_with_attributes(HiGHS.Optimizer, "output_flag" => false)) An Abstract JuMP Model Feasibility problem with: Variables: 0 Upper Constraints: 0 Lower Constraints: 0 Bilevel Model Solution method: BilevelJuMP.SOS1Mode{Float64}() Solver name: HiGHS ``` -------------------------------- ### Configure BilevelJuMP with SOS1Mode and SCIP Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/modes Sets the optimizer to SCIP and configures the model to use SOS1Mode for bilevel optimization. ```julia set_optimizer(model, SCIP.Optimizer) BilevelJuMP.set_mode(model, BilevelJuMP.SOS1Mode()) optimize!(model) objective_value(model) @assert abs(objective_value(model) - (3 * (3.5 * 8/15) + 8/15)) < 1e-1 # src ``` -------------------------------- ### Verify Solution Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/MibS_example1 Performs automated tests to verify the solver output. ```julia @test solution.status == true @test solution.objective ≈ -53 @test solution.nonzero_upper == Dict(0 => 6.0) @test solution.nonzero_lower == Dict(0 => 5.0) @test solution.all_upper["x"] == 6.0 @test solution.all_lower["y"] == 5.0 ``` -------------------------------- ### Product Reformulation Mode Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Converts complementarity constraints into non-convex quadratic constraints using products. ```julia ProductMode(epsilon = 0.0; with_slack = false, aggregation_group = nothing) ``` -------------------------------- ### BilevelModel Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Constructs a new BilevelModel instance, optionally specifying a solver and solve mode. ```APIDOC ## BilevelModel() ### Description Creates an empty BilevelModel with default settings, no solver, and no solve mode. ### Signature `BilevelModel()` ## BilevelModel(solver::Function; mode, add_bridges) ### Description Creates a BilevelModel with the specified solver and solve mode. ### Parameters - **solver** (Function) - A function that takes no arguments and returns a JuMP solver object. - **mode** (Any) - A solve mode object defining how the model is solved (default: BilevelJuMP.SOS1Mode()). - **add_bridges** (Bool) - If true, bridges are added to the model (default: true). ``` -------------------------------- ### Configure BilevelJuMP with SCIP IndicatorMode Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/modes Sets the optimizer to SCIP and configures the model to use IndicatorMode for solving bilevel problems. ```julia set_optimizer(model, SCIP.Optimizer) BilevelJuMP.set_mode(model, BilevelJuMP.IndicatorMode()) optimize!(model) objective_value(model) @assert abs(objective_value(model) - (3 * (3.5 * 8/15) + 8/15)) < 1e-1 # src ``` -------------------------------- ### Cite the BilevelJuMP paper Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/background BibTeX entry for referencing the BilevelJuMP.jl modeling and solving framework. ```bibtex @article{diasgarcia2022bileveljump, title={{BilevelJuMP. jl}: {M}odeling and solving bilevel optimization in {J}ulia}, author={{Dias Garcia}, Joaquim and Bodin, Guilherme and Street, Alexandre}, journal={arXiv preprint arXiv:2205.02307}, year={2022} } ``` -------------------------------- ### build_time(model::BilevelModel) Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Returns the time taken to build the model. ```APIDOC ## build_time(model::BilevelModel) ### Description Return the time it took to build the model. ### Parameters - **model** (BilevelModel) - Required - The bilevel model instance. ``` -------------------------------- ### Define a bilevel model Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/modes Construct a bilevel model and define variables, objectives, and constraints for both upper and lower levels. ```julia model = BilevelModel() @variable(Lower(model), x) @variable(Upper(model), y) @objective(Upper(model), Min, 3x + y) @constraints(Upper(model), begin x <= 5 y <= 8 y >= 0 end) @objective(Lower(model), Min, -x) @constraints(Lower(model), begin c1, x + y <= 8 c2, 4x + y >= 8 c3, 2x + y <= 13 c4, 2x - 7y <= 0 end) ``` -------------------------------- ### Define a bilevel model with DualOf Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/lower_duals Constructs a bilevel model where the upper-level variable lambda is linked to the lower-level demand_equilibrium constraint. ```julia model = BilevelModel() @variable(Upper(model), 0 <= qS <= 100) @variable(Lower(model), 0 <= gS <= 100) @variable(Lower(model), 0 <= gR1 <= 40) @variable(Lower(model), 0 <= gR2 <= 40) @variable(Lower(model), 0 <= gD <= 100) @objective(Lower(model), Min, 50gR1 + 100gR2 + 1000gD) @constraint(Lower(model), gS <= qS) @constraint(Lower(model), demand_equilibrium, gS + gR1 + gR2 + gD == 100) @variable(Upper(model), lambda, DualOf(demand_equilibrium)) @objective(Upper(model), Max, lambda*gS) ``` -------------------------------- ### Configure BigMMode with HiGHS Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/modes Sets the solver to HiGHS and configures the BigMMode parameters for a bilevel model. ```julia set_optimizer(model, HiGHS.Optimizer) BilevelJuMP.set_mode(model, BilevelJuMP.BigMMode(primal_big_M = 100, dual_big_M = 100)) optimize!(model) objective_value(model) @assert abs(objective_value(model) - (3 * (7/2 * 8/15) + 8/15)) < 1e-1 # src ``` -------------------------------- ### Solve with MibS Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/MibS_example1 Executes the solver using the MibS backend. ```julia solution = BilevelJuMP.solve_with_MibS(model, MibS_jll.mibs) ``` -------------------------------- ### Define a Bilevel Model with Conic Constraints Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/conic_lower Uses BilevelJuMP to define a bilevel program where the lower level includes a SecondOrderCone constraint. ```julia using BilevelJuMP model = BilevelModel() @variable(Upper(model), x) @variable(Lower(model), y[i=1:3]) @objective(Upper(model), Min, x + 3y[1]) @constraint(Upper(model), x >= 2) @constraint(Upper(model), x <= 6) @objective(Lower(model), Min, - y[1]) @constraint(Lower(model), con1, x + y[1] <= 8) @constraint(Lower(model), con2, x + 4y[1] >= 8) @constraint(Lower(model), con3, x + 2y[1] <= 12) @constraint(Lower(model), con4, y in SecondOrderCone()) ``` -------------------------------- ### Model Status Queries Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/PHTP_example1 Commands to retrieve the primal and termination status of the optimization model. ```julia primal_status(model) ``` ```text FEASIBLE_POINT::ResultStatusCode = 1 ``` ```julia termination_status(model) ``` ```text LOCALLY_SOLVED::TerminationStatusCode = 4 ``` -------------------------------- ### Set Dual Hints Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/FOBP_example2 Provides dual bound hints for the lower level constraints to assist the solver. ```julia for c in [l1, l2, l3, l4] BilevelJuMP.set_dual_upper_bound_hint(c, 15) BilevelJuMP.set_dual_lower_bound_hint(c, -15) end ``` -------------------------------- ### Optimize the Bilevel Model Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/FOBP_example4 Executes the optimization process for the defined model. ```julia optimize!(model) ``` -------------------------------- ### Solver Statistics Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/PHTP_example2 Final summary of the optimization run, including objective value, constraint violations, and evaluation counts. ```text Number of Iterations....: 33 (scaled) (unscaled) Objective...............: -3.2290220275399406e-08 -3.2290220275399406e-08 Dual infeasibility......: 1.0289546992225951e-12 1.0289546992225951e-12 Constraint violation....: 1.4210854715202004e-14 1.4210854715202004e-14 Variable bound violation: 4.8166666662694828e-09 4.8166666662694828e-09 Complementarity.........: 2.5157965842376463e-09 2.5157965842376463e-09 Overall NLP error.......: 2.5157965842376463e-09 2.5157965842376463e-09 Number of objective function evaluations = 40 Number of objective gradient evaluations = 34 Number of equality constraint evaluations = 40 Number of inequality constraint evaluations = 40 Number of equality constraint Jacobian evaluations = 34 Number of inequality constraint Jacobian evaluations = 34 Number of Lagrangian Hessian evaluations = 33 Total seconds in IPOPT = 0.017 EXIT: Optimal Solution Found. ``` -------------------------------- ### Set Primal Hints Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/FOBP_example2 Provides primal bound hints for variables to assist the solver. ```julia BilevelJuMP.set_primal_lower_bound_hint(x, -10) BilevelJuMP.set_primal_upper_bound_hint(x, 6) BilevelJuMP.set_primal_lower_bound_hint(y, -1) BilevelJuMP.set_primal_upper_bound_hint(y, 9) ``` -------------------------------- ### SOS1 Reformulation Mode Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/reference Uses SOS1 constraints to convert complementarity constraints into mixed-integer constraints. ```julia SOS1Mode() ``` -------------------------------- ### Set Dual Bounds Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/SOCBLP_example1 Provides dual bound hints for the lower level constraints to assist the solver. ```julia BilevelJuMP.set_dual_upper_bound_hint(soc_lw, +[5.0, 5.0]) BilevelJuMP.set_dual_lower_bound_hint(soc_lw, -[5.0, 5.0]) ``` ```julia for con in [con1, con3] BilevelJuMP.set_dual_lower_bound_hint(con, -15) end ``` ```julia for con in [lb_y_1, lb_y_2, con2] BilevelJuMP.set_dual_upper_bound_hint(con, +15) end ``` -------------------------------- ### Solve MISOCP with Mixed Mode Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/conic_lower Configures a MISOCP solver with binary expansions and sets specific reformulation modes for conic and non-conic constraints. ```julia using Xpress using QuadraticToBinary set_optimizer(model, ()->QuadraticToBinary.Optimizer{Float64}(Xpress.Optimizer(),lb=-10,ub=10)) BilevelJuMP.set_mode(model, BilevelJuMP.MixedMode(default = BilevelJuMP.IndicatorMode())) BilevelJuMP.set_mode(con4, BilevelJuMP.ProductMode(1e-5)) optimize!(model) ``` -------------------------------- ### Obtain Primal and Dual Solutions Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/getting_started Extracts the primal variable values and dual values for specific constraints. ```julia julia> value(x) 1.8666666666666667 julia> value(y) 0.5333333333333332 julia> dual(l1) 1-element Vector{Float64}: 0.0 julia> dual(l2) 1-element Vector{Float64}: 49.75 ``` -------------------------------- ### IPOPT Final Statistics Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/examples/PHTP_example1 Summary of the final objective value, constraint violations, and solver performance metrics. ```text Number of Iterations....: 33 (scaled) (unscaled) Objective...............: 1.6999999980907578e+01 1.6999999980907578e+01 Dual infeasibility......: 8.9958831495096092e-09 8.9958831495096092e-09 Constraint violation....: 2.2204460492503131e-16 2.2204460492503131e-16 Variable bound violation: 4.0833333485561435e-09 4.0833333485561435e-09 Complementarity.........: 4.8883842466698459e-09 4.8883842466698459e-09 Overall NLP error.......: 8.9958831495096092e-09 8.9958831495096092e-09 Number of objective function evaluations = 38 Number of objective gradient evaluations = 34 Number of equality constraint evaluations = 38 Number of inequality constraint evaluations = 38 Number of equality constraint Jacobian evaluations = 34 Number of inequality constraint Jacobian evaluations = 34 Number of Lagrangian Hessian evaluations = 33 Total seconds in IPOPT = 0.015 EXIT: Optimal Solution Found. ``` -------------------------------- ### Create anonymous dual variables Source: https://joaquimg.github.io/BilevelJuMP.jl/stable/tutorials/lower_duals Iteratively create anonymous dual variables for constraints using a loop. ```julia my_duals = [] for i in 1:3 var = @variable(Upper(model), variable_type = DualOf(reserves[i])) push!(my_duals, var) end my_duals # a vector of anonimous variables ```