Yibo Liu
Yibo Liu

Reputation: 81

Same code doesn't work consistently in Julia

I created a model to solve linear programs in Julia. I solved the linear program first time but the same code doesn't work for a modified program. Can you figure out what's going on? Thank you! The code that works fine:

m = Model()
@variable(m, x[1:77] >= 0)
for i in nutrients 
    @constraint(m, dot(data[:, i], x) >= lower[i])
end
@objective(m, Min, sum(dot(c, x)))
status = solve(m)
for i in 1:77
    if getvalue(x[i]) > 0
        println("Take ", getvalue(x[i]), " dollars of ", foods[i], " every day.")
    end
end
println("The total cost for each day is ", getobjectivevalue(m), " dollars.")
println("The total cost for the whole year is ", getobjectivevalue(m) * 365, " dollars.")

This is the result:

Take 0.02951906167648827 dollars of Wheat Flour (Enriched) every day.
Take 0.0018925572907052643 dollars of Liver (Beef) every day.
Take 0.011214435246144865 dollars of Cabbage every day.
Take 0.005007660466725203 dollars of Spinach every day.
Take 0.061028563526693246 dollars of Navy Beans, Dried every day.
The total cost for each day is 0.10866227820675685 dollars.
The total cost for the whole year is 39.66173154546625 dollars.

This is the code that doesn't work:

m1 = Model()
for i in 1:77
    if i == a
        @variable(m1, x[i] == 0)
    elseif i == b
        @variable(m1, x[i] == 0)
    else 
        @variable(m1, x[i] >= 0)
    end
end
for i in nutrients 
    @constraint(m1, dot(data[:, i], x) >= lower[i])
end
@objective(m1, Min, sum(dot(c, x)))
status = solve(m1)
for i in 1:77
    if getvalue(x[i]) > 0
        println("Take ", getvalue(x[i]), " dollars of ", foods[i], " every day.")
    end
end
println("The total cost for each day is ", getobjectivevalue(m1), " dollars.")
println("The total cost for the whole year is ", getobjectivevalue(m1) * 365, " dollars.")

Here is the error message:

MethodError: no method matching dot(::NamedArrays.NamedArray{Any,1,Array{Any,1},Tuple{DataStructures.OrderedDict{Any,Int64}}}, ::JuMP.JuMPArray{JuMP.Variable,1,Tuple{Int64}})
Closest candidates are:
  dot(::AbstractArray{T,1}, ::AbstractArray{T,1}) at linalg/generic.jl:302
  dot{T,S,N}(::Array{T,N}, ::JuMP.JuMPArray{S,N,NT<:Tuple{Vararg{T,N}}}) at /Users/yiboliu/.julia/v0.5/JuMP/src/operators.jl:299
  dot{T,S,N}(::JuMP.JuMPArray{T,N,NT<:Tuple{Vararg{T,N}}}, ::JuMP.JuMPArray{S,N,NT<:Tuple{Vararg{T,N}}}) at /Users/yiboliu/.julia/v0.5/JuMP/src/operators.jl:301

 in macro expansion; at /Users/yiboliu/.julia/v0.5/JuMP/src/macros.jl:400 [inlined]
 in macro expansion; at ./In[23]:13 [inlined]
 in anonymous at ./<missing>:?

I know the problem is at constraints, but that part of code are identical, and doesn't work. Can you give me any idea what's going on?

Upvotes: 3

Views: 206

Answers (2)

Dario
Dario

Reputation: 2723

You cannot have two @variable method calls in the same model, as they will define different variables each time. So, the whole first for ... end loop in m1 has to be replaced by

@variable(m1, x[1:77] >= 0)
@constraint(m1, x[a] == 0)
@constraint(m1, x[b] == 0)

(I suppose a and b have been defined elsewhere)

Upvotes: 0

Colin Beckingham
Colin Beckingham

Reputation: 525

The error messages are saying that the attempt to call a dot() function doesn't fit with what the function has been told to expect. This could be because the count of inputs is wrong, or that their type is not what is expected. Since the code is identical at the top level we can assume it is the latter explanation, that maybe there is a problem with types.

First examine the error output to see exactly which call to the dot function is responsible (you seem to have two), and then insert a line just before the call to output information about the inputs that will be used. You might use the typeof() function. Then compare what you are sending to what dot() really wants.

Upvotes: 2

Related Questions