-
-
Notifications
You must be signed in to change notification settings - Fork 398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor JuMP macros #3513
Comments
Maybe precluded by the "no user-facing changes", but it would be great if macro changes could make it easier to use JuMP "programmatically". Possibly that could be a separate roadmap item. I don't know what needs to be done really because I'm no expert on macros etc, but I have had to resort to generating low level MOI code to build complex models programmatically. |
I think the non-macro version is just a documentation issue. We already have all of the machinery available in JuMP. Given: using JuMP
model = Model()
@variable(model, 0 <= x[1:I, 1:T] <= 100)
@constraint(model, [i in 1:I, t in 2:T], x[i, t] - x[i, t-1] <= 10)
@constraint(model, [i in 1:I, t in 2:T], x[i, t] - x[i, t-1] >= -10)
@objective(model, Min, sum(x)) One version of the non-macro version is model = Model()
x = [VariableRef(model) for i in 1:I, t in 1:T]
set_lower_bound.(x, 0)
set_upper_bound.(x, 1000)
for i in 1:I, t in 2:T
add_constraint(model, ScalarConstraint(x[i, t] - x[i, t-1], MOI.LessThan(10.0)))
add_constraint(model, ScalarConstraint(x[i, t] - x[i, t-1], MOI.GreaterThan(-10.0)))
end
set_objective(model, MOI.MIN_SENSE, sum(x)) It's also possible to minimally use the macros: model = Model()
x = [@variable(model) for i in 1:I, t in 1:T]
set_lower_bound.(x, 0)
set_upper_bound.(x, 1000)
for i in 1:I, t in 2:T
f, set = x[i, t] - x[i, t-1], MOI.LessThan(10.0)
@constraint(model, f in set)
f, set = x[i, t] - x[i, t-1], MOI.GreaterThan(-10.0)
@constraint(model, f in set)
end
sense, f = MOI.MIN_SENSE, sum(x)
@objective(model, sense, f) But these don't give good names, and it's a bit more complicated if you want to construct containers that are not arrays, etc. There's the much more complicated But I also don't think users gain much by using the non-macro JuMP syntax. If you're doing it programmatically, what's wrong with MOI? |
I think JuMP is still a bit more convenient, even for programatic use, mainly because the model is stored inside a |
From the extension side of things, it would be nice to have some of the common macro tooling be accessible. Specifically, I encounter macros of the form
Currently, JuMP provides |
I have been making reasonable progress. The Once I have things under control, I'll think about how we could expose some public API for building related calls. |
@pulsipher interested in your feedback on these changes. The two most useful new additions are:
and
I haven't made any larger structural changes, or introduced a "simple" way to write macros. There's still a lot of fluff around error checking the number of arguments, and dealing with optional keyword arguments. But I don't know if there is a good universal design. The |
Actually. I've simplified to https://jump.dev/JuMP.jl/previews/PR3620/api/JuMP.Containers/#Containers.container_code |
Perhaps the best way to look at the new code is https://github.com/jump-dev/JuMP.jl/tree/od/container-name/src/macros Here's the JuMP.jl/src/macros/@expression.jl Lines 66 to 104 in ea44fe4
Here's what it used to look like Lines 1923 to 1975 in 419c334
|
Hi @odow, you've been busy! I definitely like the direction these are going in. Some suggestions to improve things further:
To guide refining the API, perhaps you could make a PR in JuMP that I could use to make an InfiniteOpt PR that tests out the new API. |
|
Yes
For instance, right now in args, kwargs = Containers.parse_macro_arguments(error_fn, input_args)
# PUT CODE HERE to derive the code to define `index_vars`, `indices`, `code`
container = get(kwargs, :container, :Auto)
container_code = Containers.container_code(index_vars, indices, code, container) By allowing the 4th argument of args, kwargs = Containers.parse_macro_arguments(error_fn, input_args)
# PUT CODE HERE to derive the code to define `index_vars`, `indices`, `code`
container_code = Containers.container_code(index_vars, indices, code, kwargs)
Awesome! |
One last suggestion that I forgot would be to make |
Try #3620. I haven't made |
@pulsipher I've been thinking about It seems like a a weird function to export from JuMP. But it also can't go in |
We have a roadmap item for this: https://github.com/jump-dev/JuMP.jl/blob/master/docs/src/developers/roadmap.md, but it'd be useful to have an issue tracking it (x-ref #3500 (comment)).
I don't have any suggestions for what a "good"
macros.jl
file would look like, but it would be cleaner, with less code being run in the macros, and no user-facing changes.The text was updated successfully, but these errors were encountered: