I agree. Most of the JuMP example models are not coded in a way that appeals to experienced modelers, especially AMPL users who are accustomed to clean syntax.
But clean syntax using “sets” is quite possible in JuMP right now. To teach myself JuMP last week, I rewrote the multi.jl model to be as close to AMPL syntax as possible. The trick is to use “dictionaries of tuples” for parameters and variables instead of arrays (matrices). Here is the JuMPy part of my modified model:
# index sets
orig = [:GARY, :CLEV, :PITT]
dest = [:FRA, :DET, :LAN, :WIN, :STL, :FRE, :LAF]
prod = [:bands, :coils, :plate]
@variables multi begin
Trans[p in prod, o in orig, d in dest] >= 0
end
@constraints multi begin
c_supply[p in prod, o in orig],
sum(Trans[p,o,d] for d in dest) == supply[p,o]
c_demand[p in prod, d in dest],
sum(Trans[p,o,d] for o in orig) == demand[p,d]
c_total_shipment[o in orig, d in dest],
sum(Trans[p,o,d] for p in prod) - limit[o,d] <= 0
end
@objective multi Max begin
sum(cost[p,o,d] * Trans[p,o,d] for p in prod, o in orig, d in dest)
end
I uploaded the complete model here. In addition to using dictionaries of tuples, I chose to use arrays of symbols instead of arrays of strings to represent the indexing sets. I also read input data directly into dataframes using the wsv"""..."""
syntax.
I think this approach is significantly more readable than the original version. It is also more fault tolerant. The original model does a 3-dimensional reshape
of the cost data, which is very easy to mess up. This is not needed when dictionaries are indexed by name in the equations.
But most importantly: when you use numerical indexes of multidimensional parameters and variables (as the original model does), a simple typo can cause your model to fail silently. If line 87 of the original model has been written cost[j,p,i]
instead of cost[j,i,p]
the model would solve and produce a reasonable looking but completely incorrect result. (No errors are produced because the orig and prod sets both have three elements.)