I have tested your suggestion of making the variable assignment inside the loop local
. On another model with actual data this gives incorrect results. If a race condition arises then use of local
may be not be a good idea. It may have worked for your specific case, but in the MWE above it is mixing up something.
Locks can be used in a race condition, but this tend to slowdown the program. If possible, I would prefer to code it in a way that race condition is avoided. I also got into problem with my workaround code above when I tried to use it on another problem.
This is my code for the MWE that works well and avoids race condition. I believe this is exactly what @odow suggested using.
using JuMP
using Clp
function generate_data()
# Generate random data
InitialValue= float(rand(80:140,1,5))
FutureValue = float(rand(40:150,100,5))
Demand = float(rand(40:50,100))
nscen = size(FutureValue,1)
nproducts = size(FutureValue,2)
prob = 1/nscen*ones(nscen)
Loss = zeros(Float64,nscen,nproducts)
Loss = -FutureValue.+InitialValue
return FutureValue, Loss, Demand,nproducts, prob, nscen
end
function build_model(FutureValue,Loss,Demand,nproducts,prob,nscen,α)
model = Model(Clp.Optimizer)
set_optimizer_attribute(model, MOI.Silent(), true)
@variable(model,x[b=1:nproducts]>=0)
@variable(model,y[b=1:nscen]>=0)
@variable(model,γ>=0)
@constraint(model,budget,sum(x[i] for i =1:nproducts) == 1)
@constraint(model,constraint2[j in 1:nscen], y[j]-sum(Loss[j,i]*x[i] for i in 1:nproducts) + γ >= 0)
@constraint(model,constraint3[j in 1:nscen], sum(FutureValue[j,i]*x[i] for i in 1:nproducts)-Demand[j] >= 0)
@objective(model,Min,γ+1/(α)*sum(y[j]*prob[j] for j =1:nscen))
optimize!(model)
γ_result = JuMP.value.(γ)
Objective_result = objective_value(model)
DecisionVariable_result = JuMP.value.(x)
return γ_result, Objective_result, DecisionVariable_result
end
function run_modelthreading(;n=10,α=0.05)
FutureValue, Loss, Demand,nproducts, prob, nscen = generate_data()
γ_result, Objective_result, DecisionVariable_result = build_model(FutureValue,Loss,Demand,nproducts,prob,nscen,α)
Limit = Objective_result
VaR = Vector{Float64}(undef,n)
CVaR = Vector{Float64}(undef,n)
Product = Array{Float64,2}(undef, nproducts,n)
Threads.@threads for i in 1:n
α = (n-(i-1))/Limit
γ_result, Objective_result, DecisionVariable_result =
build_model(FutureValue,Loss,Demand,nproducts,prob,nscen,α)
VaR[i] = γ_result
CVaR[i] = Objective_result
Product[:,i] = DecisionVariable_result
end
return VaR, CVaR, Product
end
run_modelthreading(;n=10,α=0.05)