TL;DR: Is there a way to use Gurobi.jl and distributed algorithms from StochasticPrograms.jl in a way that works on a cluster, given that StochasticPrograms.jl requires JuMP.jl version 1.2.1?
Hi everyone,
I’m planning to use StochasticPrograms.jl to solve a large two-stage stochastic optimization problem. I’d like to use a decomposition method such as L-Shaped or Progressive Hedging (both are implemented in StochasticPrograms) to solve this on my institution’s cluster.
However, I run into what, on the surface, seems like a licensing issue regarding Gurobi.jl:
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID
ERROR: LoadError: Gurobi Error 10024: Web license service only available for container environments
Stacktrace:
[1] _check_ret
@ ~/.julia/packages/Gurobi/VPomg/src/MOI_wrapper/MOI_wrapper.jl:393 [inlined]
[2] Gurobi.Env(; output_flag::Int64, memory_limit::Nothing, started::Bool)
@ Gurobi ~/.julia/packages/Gurobi/VPomg/src/MOI_wrapper/MOI_wrapper.jl:122
[3] Env
@ ~/.julia/packages/Gurobi/VPomg/src/MOI_wrapper/MOI_wrapper.jl:95 [inlined]
[4] Gurobi.Optimizer(env::Nothing; enable_interrupts::Bool)
@ Gurobi ~/.julia/packages/Gurobi/VPomg/src/MOI_wrapper/MOI_wrapper.jl:324
[5] Optimizer (repeats 2 times)
@ ~/.julia/packages/Gurobi/VPomg/src/MOI_wrapper/MOI_wrapper.jl:318 [inlined]
[6] #53
@ ~/ScenarioSelect/src/stoch_prog_examples/farmer_problem.jl:57 [inlined]
[7] bridge_type(optimizer::var"#53#54")
@ StochasticPrograms ~/.julia/packages/StochasticPrograms/pIScW/src/types/optimizer.jl:99
[8] StochasticPrograms.StochasticProgramOptimizer(optimizer_constructor::Function)
@ StochasticPrograms ~/.julia/packages/StochasticPrograms/pIScW/src/types/optimizer.jl:91
[9] StochasticProgram(stages::Tuple{StochasticPrograms.Stage{@NamedTuple{Crops::Vector{Symbol}, Cost::Dict{Symbol, Int64}, Budget::Int64}}, StochasticPrograms.Stage{@NamedTuple{Crops::Vector{Symbol}, Required::Dict{Symbol, Int64}, PurchasePrice::Dict{Symbol, Int64}, SellPrice::Dict{Symbol, Int64}}}}, scenarios::Tuple{Vector{Scenario{JuMP.Containers.DenseAxisArray{Float64, 1, Tuple{Vector{Symbol}}, Tuple{JuMP.Containers._AxisLookup{Dict{Symbol, Int64}}}}}}}, instantiation::UnspecifiedInstantiation, optimizer_constructor::Function)
@ StochasticPrograms ~/.julia/packages/StochasticPrograms/pIScW/src/types/stochasticprogram.jl:65
[10] StochasticProgram(first_stage_params::@NamedTuple{Crops::Vector{Symbol}, Cost::Dict{Symbol, Int64}, Budget::Int64}, second_stage_params::@NamedTuple{Crops::Vector{Symbol}, Required::Dict{Symbol, Int64}, PurchasePrice::Dict{Symbol, Int64}, SellPrice::Dict{Symbol, Int64}}, scenarios::Vector{Scenario{JuMP.Containers.DenseAxisArray{Float64, 1, Tuple{Vector{Symbol}}, Tuple{JuMP.Containers._AxisLookup{Dict{Symbol, Int64}}}}}}, instantiation::UnspecifiedInstantiation, optimizer_constructor::Function)
@ StochasticPrograms ~/.julia/packages/StochasticPrograms/pIScW/src/types/stochasticprogram.jl:143
[11] instantiate(sm::StochasticModel{2, Tuple{StageParameters{@NamedTuple{Crops::Vector{Symbol}, Cost::Dict{Symbol, Int64}, Budget::Int64}}, StageParameters{@NamedTuple{Crops::Vector{Symbol}, Required::Dict{Symbol, Int64}, PurchasePrice::Dict{Symbol, Int64}, SellPrice::Dict{Symbol, Int64}}}}}, scenarios::Vector{Scenario{JuMP.Containers.DenseAxisArray{Float64, 1, Tuple{Vector{Symbol}}, Tuple{JuMP.Containers._AxisLookup{Dict{Symbol, Int64}}}}}}; instantiation::UnspecifiedInstantiation, optimizer::var"#53#54", defer::Bool, direct_model::Bool, kw::@Kwargs{})
@ StochasticPrograms ~/.julia/packages/StochasticPrograms/pIScW/src/methods/api.jl:42
[12] top-level scope
@ ~/ScenarioSelect/src/stoch_prog_examples/farmer_problem.jl:55
in expression starting at /global/home/users/sunashsharma/ScenarioSelect/src/stoch_prog_examples/farmer_problem.jl:55
Running with 8 processes:
After some prodding, I think this is due to StochasticPrograms.jl requiring an old version of JuMP.jl (JuMP 1.2.1): This error occurs when I run the following SLURM script:
#!/bin/bash
#SBATCH --job-name=test
#SBATCH --partition=lr3
#SBATCH --qos=lr_normal
#SBATCH --account=pc_psidml
#SBATCH -N 1
#SBATCH --ntasks=20
#SBATCH -o %x-%j.out
#SBATCH --export=ALL
#SBATCH --time=00:05:00
module load gurobi/10.0.0
export GRB_LICENSE_FILE="/global/home/users/sunashsharma/gurobi.lic"
julia --project=/global/home/users/sunashsharma/ScenarioSelect farmer_problem.jl
farmer_problem.jl
is an example that comes with StochasticPrograms.jl, which I have modified to run using Gurobi on a cluster:
using Distributed
import Pkg
project = Pkg.project();
# Get the number of processes from the SLURM environment
nprocs = parse(Int, get(ENV, "SLURM_NTASKS", "4"))
workers = addprocs(nprocs; exeflags = "--project=$(project.path)")
println("Running with $(nprocs) processes:")
@everywhere begin
using StochasticPrograms
import Gurobi
end
Crops = [:wheat, :corn, :beets]
@stochastic_model farmer_model begin
@stage 1 begin
@parameters begin
Crops = Crops
Cost = Dict(:wheat=>150, :corn=>230, :beets=>260)
Budget = 500
end
@decision(farmer_model, x[c in Crops] >= 0)
@objective(farmer_model, Min, sum(Cost[c]*x[c] for c in Crops))
@constraint(farmer_model, sum(x[c] for c in Crops) <= Budget)
end
@stage 2 begin
@parameters begin
Crops = Crops
Required = Dict(:wheat=>200, :corn=>240, :beets=>0)
PurchasePrice = Dict(:wheat=>238, :corn=>210)
SellPrice = Dict(:wheat=>170, :corn=>150, :beets=>36, :extra_beets=>10)
end
@uncertain ξ[c in Crops]
@recourse(farmer_model, y[p in setdiff(Crops, [:beets])] >= 0)
@recourse(farmer_model, w[s in Crops ∪ [:extra_beets]] >= 0)
@objective(farmer_model, Min, sum(PurchasePrice[p] * y[p] for p in setdiff(Crops, [:beets]))
- sum(SellPrice[s] * w[s] for s in Crops ∪ [:extra_beets]))
@constraint(farmer_model, minimum_requirement[p in setdiff(Crops, [:beets])],
ξ[p] * x[p] + y[p] - w[p] >= Required[p])
@constraint(farmer_model, minimum_requirement_beets,
ξ[:beets] * x[:beets] - w[:beets] - w[:extra_beets] >= Required[:beets])
@constraint(farmer_model, beets_quota, w[:beets] <= 6000)
end
end
ξ₁ = @scenario ξ[c in Crops] = [3.0, 3.6, 24.0] probability = 1/2
ξ₂ = @scenario ξ[c in Crops] = [2.5, 3.0, 20.0] probability = 1/3
ξ₃ = @scenario ξ[c in Crops] = [2.0, 2.4, 16.0] probability = 1/3
farmer = instantiate(
farmer_model, [ξ₁,ξ₂,ξ₃],
optimizer = () -> LShaped.Optimizer(master_optimizer=() -> Gurobi.Optimizer()))
optimize!(farmer)
x = optimal_decision(farmer)
x = farmer[1,:x]
println("Wheat: $(value(x[:wheat]))")
println("Corn: $(value(x[:corn]))")
println("Beets: $(value(x[:beets]))")
println("Profit: $(objective_value(farmer))")
rmprocs(workers)
The main reason I think this is actually a StochasticPrograms.jl issue is that I can run a simple distributed example with the latest version of JuMP.jl just fine on my cluster:
using Distributed, ClusterManagers
import Pkg
project = Pkg.project();
# Get the number of processes from the SLURM environment
nprocs = parse(Int, get(ENV, "SLURM_NTASKS", "1"))
workers = addprocs(nprocs; exeflags = "--project=$(project.path)")
println("Running with $(nprocs) processes:")
@everywhere begin
using JuMP
import Gurobi
import MathOptInterface
end
@everywhere begin
function solve_model_with_right_hand_side(i)
model = Model(Gurobi.Optimizer)
set_attribute(model, MathOptInterface.NumberOfThreads(), 4)
set_silent(model)
@variable(model, x)
@objective(model, Min, x)
set_lower_bound(x, i)
optimize!(model)
@assert is_solved_and_feasible(model)
return objective_value(model)
end
end
solutions = pmap(solve_model_with_right_hand_side, 1:80)
println(solutions)
For this the SLURM script was:
#!/bin/bash
#SBATCH --job-name=test
#SBATCH --partition=lr3
#SBATCH --qos=lr_normal
#SBATCH --account=pc_psidml
#SBATCH -N 2
#SBATCH --ntasks=40
#SBATCH -o %x-%j.out
#SBATCH --export=ALL
#SBATCH --time=00:05:00
module load gurobi/10.0.0
export GRB_LICENSE_FILE="/global/home/users/sunashsharma/gurobi.lic"
julia --project=/global/home/users/sunashsharma/JuMPSandbox test_parallel.jl
StochasticPrograms.jl requires JuMP.jl 1.2.1, and holds back the version of Gurobi.jl to 0.11.3 as a result. I’m posting here though to see if I’m missing anything regarding Gurobi.jl or StochasticPrograms.jl usage that could be causing this error, or if there is a quick fix for the StochasticPrograms.jl dependency issue that anyone has found.
Thanks a lot for any help!
Sunash