martinbiel / StochasticPrograms.jl

Julia package for formulating and analyzing stochastic recourse models.
MIT License
75 stars 25 forks source link

Undefined variable error when defining integer variables #11

Closed maramos874 closed 3 years ago

maramos874 commented 3 years ago

Hi, I did a quick test by modifying the farmer example, transforming it to integer form. However, UndefVarError is thrown when trying to instantiate the model. I've done other tests and the error is thrown with binary variables too and with all solvers. Is this a bug or are integer variables not supported yet?

Thanks!

using Gurobi using StochasticPrograms farmer_model = @stochastic_model begin @stage 1 begin @parameters begin Crops = [:wheat, :corn, :beets] Cost = Dict(:wheat=>150, :corn=>230, :beets=>260) Budget = 500 end @decision(model, x[c in Crops] >=0, integer=true) @objective(model, Min, sum(Cost[c]x[c] for c in Crops)) @constraint(model, sum(x[c] for c in Crops) <= Budget) @constraint(model, sum(x[c] for c in Crops) <= Budget) end @stage 2 begin @parameters begin Crops = [:wheat, :corn, :beets] 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] @variable(model, y[p in setdiff(Crops, [:beets])] >= 0) @variable(model, w[s in Crops ∪ [:extra_beets]] >= 0) @objective(model, Min, sum(PurchasePrice[p] y[p] for p in setdiff(Crops, [:beets]))

ξ₁ = Scenario(wheat = 3.0, corn = 3.6, beets = 24.0, probability = 1/3) ξ₂ = Scenario(wheat = 2.5, corn = 3.0, beets = 20.0, probability = 1/3) ξ₃ = Scenario(wheat = 2.0, corn = 2.4, beets = 16.0, probability = 1/3)

farmer = instantiate(farmer_model, [ξ₁,ξ₂,ξ₃], optimizer = LShaped.Optimizer) print(farmer)

set_optimizer_attribute(farmer, MasterOptimizer(), Gurobi.Optimizer) set_optimizer_attribute(farmer, SubproblemOptimizer(), Gurobi.Optimizer)

optimize!(farmer) x = optimal_decision(farmer) println("Wheat: $(x[1])") println("Corn: $(x[2])") println("Beets: $(x[3])") println("Profit: $(objective_value(farmer))") println("EVPI: $(EVPI(farmer))") println("VSS: $(VSS(farmer))")

ERROR: UndefVarError: x not defined Stacktrace: [1] macro expansion at /mnt/workspace/.julia/packages/MutableArithmetics/NuiNA/src/rewrite.jl:227 [inlined] [2] macro expansion at /mnt/workspace/.julia/packages/JuMP/YXK4e/src/macros.jl:416 [inlined] [3] (::var"#71#84"{Model,Dict{Symbol,Int64},JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{Array{Symbol,1}},Tuple{Dict{Symbol,Int64}}},JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{Array{Symbol,1}},Tuple{Dict{Symbol,Int64}}}})(::Symbol) at /mnt/workspace/.julia/packages/JuMP/YXK4e/src/Containers/macro.jl:183 [4] #28 at /mnt/workspace/.julia/packages/JuMP/YXK4e/src/Containers/container.jl:85 [inlined] [5] iterate at ./generator.jl:47 [inlined] [6] collect(::Base.Generator{JuMP.Containers.VectorizedProductIterator{Tuple{Array{Symbol,1}}},JuMP.Containers.var"#28#29"{var"#71#84"{Model,Dict{Symbol,Int64},JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{Array{Symbol,1}},Tuple{Dict{Symbol,Int64}}},JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{Array{Symbol,1}},Tuple{Dict{Symbol,Int64}}}}}}) at ./array.jl:665 [7] map(::Function, ::JuMP.Containers.VectorizedProductIterator{Tuple{Array{Symbol,1}}}) at ./abstractarray.jl:2098 [8] container(::Function, ::JuMP.Containers.VectorizedProductIterator{Tuple{Array{Symbol,1}}}, ::Type{JuMP.Containers.DenseAxisArray}) at /mnt/workspace/.julia/packages/JuMP/YXK4e/src/Containers/container.jl:85 [9] container at /mnt/workspace/.julia/packages/JuMP/YXK4e/src/Containers/container.jl:65 [inlined] [10] #67 at /mnt/workspace/.julia/packages/JuMP/YXK4e/src/macros.jl:79 [inlined] [11] (::var"#67#80")(::Model, ::NamedTuple{(:Crops, :Required, :PurchasePrice, :SellPrice),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Dict{Symbol,Int64},Dict{Symbol,Int64}}}, ::Scenario{NamedTuple{(:wheat, :corn, :beets),Tuple{Float64,Float64,Float64}}}) at ./none:0 [12] generate_vertical!(::StochasticPrograms.ScenarioProblems{Scenario{NamedTuple{(:wheat, :corn, :beets),Tuple{Float64,Float64,Float64}}}}, ::var"#60#73", ::var"#67#80", ::NamedTuple{(:Crops, :Cost, :Budget),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Int64}}, ::NamedTuple{(:Crops, :Required, :PurchasePrice, :SellPrice),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Dict{Symbol,Int64},Dict{Symbol,Int64}}}, ::Decisions, ::Nothing) at /mnt/workspace/.julia/packages/StochasticPrograms/g8Qnj/src/methods/vertical/generation.jl:66 [13] generate!(::StochasticProgram{2,Tuple{StochasticPrograms.Stage{NamedTuple{(:Crops, :Cost, :Budget),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Int64}}},StochasticPrograms.Stage{NamedTuple{(:Crops, :Required, :PurchasePrice, :SellPrice),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Dict{Symbol,Int64},Dict{Symbol,Int64}}}}},VerticalStructure{2,1,Tuple{StochasticPrograms.ScenarioProblems{Scenario{NamedTuple{(:wheat, :corn, :beets),Tuple{Float64,Float64,Float64}}}}}}}, ::VerticalStructure{2,1,Tuple{StochasticPrograms.ScenarioProblems{Scenario{NamedTuple{(:wheat, :corn, :beets),Tuple{Float64,Float64,Float64}}}}}}, ::Int64) at /mnt/workspace/.julia/packages/StochasticPrograms/g8Qnj/src/methods/vertical/generation.jl:40 [14] generate! at /mnt/workspace/.julia/packages/StochasticPrograms/g8Qnj/src/methods/vertical/generation.jl:6 [inlined] [15] generate!(::StochasticProgram{2,Tuple{StochasticPrograms.Stage{NamedTuple{(:Crops, :Cost, :Budget),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Int64}}},StochasticPrograms.Stage{NamedTuple{(:Crops, :Required, :PurchasePrice, :SellPrice),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Dict{Symbol,Int64},Dict{Symbol,Int64}}}}},VerticalStructure{2,1,Tuple{StochasticPrograms.ScenarioProblems{Scenario{NamedTuple{(:wheat, :corn, :beets),Tuple{Float64,Float64,Float64}}}}}}}) at /mnt/workspace/.julia/packages/StochasticPrograms/g8Qnj/src/methods/generation.jl:92 [16] instantiate(::StochasticModel{2,Tuple{StageParameters{NamedTuple{(:Crops, :Cost, :Budget),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Int64}}},StageParameters{NamedTuple{(:Crops, :Required, :PurchasePrice, :SellPrice),Tuple{Array{Symbol,1},Dict{Symbol,Int64},Dict{Symbol,Int64},Dict{Symbol,Int64}}}}}}, ::Array{Scenario{NamedTuple{(:wheat, :corn, :beets),Tuple{Float64,Float64,Float64}}},1}; instantiation::StochasticPrograms.UnspecifiedInstantiation, optimizer::Type{T} where T, defer::Bool, direct_model::Bool, kw::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /mnt/workspace/.julia/packages/StochasticPrograms/g8Qnj/src/methods/api.jl:37 [17] top-level scope at /mnt/workspace/projects/targets/src/example_stochprogs.jl:50 [18] include(::String) at ./client.jl:439

martinbiel commented 3 years ago

Hey,

Both yes and no. Integer and binary restrictions were not being parsed correctly. This should be fixed on master now, so you can try it out again. The current L-shaped implementation does not account for integer/binary restrictions, so most problems will not be solved correctly. It could work out fine if only the first-stage variables are integer/binary (It seems to work for the farmer problem variant you posted). Solving the deterministic equivalent with an integer-capable solver (such as Gurobi) should hopefully work fine now.

maramos874 commented 3 years ago

It works now, thanks!