This question has come up a few times recently (Suggestions for documentation improvements · Issue #2348 · jump-dev/JuMP.jl · GitHub), so I definitely need to write some guidance on transitioning from GAMS to JuMP.
Can you provide a reproducible example of what you currently have, as well as the input data file? I’ll have a go to see how I would write your model.
Transitioning from GAMS to JuMP is a little complicated, because of the way we differ in handling data.
For example, GAMS lets you create “dense” sets and variables, and then index them using for-if loops. This means a direct translation of your GAMS code would try to look like:
model = Model()
@variable(model, x[A, B])
@constraint(model, [a in A], sum(x[a, b] for b in B if something(a, b)) == 1)
If there are very few values of a
and b
for which something(a, b)
is true
(that is, x
is sparse), then this approach is inefficient because it requires a loop over every element in B
for every element in A
, just to throw away most of the work because something(a, b) == false
.
The for-if approach works in GAMS because behind the scenes, GAMS translates this into a much more efficient format using relational algebra. But the for-if approach doesn’t work in JuMP because we don’t do the translation.
One approach is to only create variables for which the result is non-zero:
a_to_b = Dict(a => [] for a in A)
for a in A, b in B
if something(a, b)
push!(a_to_b[a], b)
end
end
model = Model()
@variable(model, x[a in A, b in a_to_b[a]])
@constraint(model, [a in A], sum(x[a, b] for b in a_to_b[a]) == 1)
The other approach is to change your data structure to something like a DataFrame
:
import DataFrames
df = DataFrames.DataFrame([(a = a, b = b) for a in A, b in B if something(a, b)])
model = Model()
df.x = @variable(model, x[1:size(df, 1)])
for gdf in DataFrames.groupby(df, [:a])
@constraint(model, sum(gdf.x) == 1)
end
Here are some other links: