Skip to content
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

Update to MOI v1 #53

Closed
ericphanson opened this issue Apr 2, 2022 · 9 comments · Fixed by #66
Closed

Update to MOI v1 #53

ericphanson opened this issue Apr 2, 2022 · 9 comments · Fixed by #66
Labels
help wanted Extra attention is needed

Comments

@ericphanson
Copy link
Owner

Probably needs changes similar to jump-dev/SDPA.jl#35 and jump-dev/SDPA.jl#36 to account for the breaking changes from https://jump.dev/MathOptInterface.jl/latest/release_notes/#v0.10.0-(September-6,-2021)

@ericphanson ericphanson added the help wanted Extra attention is needed label Apr 2, 2022
@FHoltorf
Copy link

Hey,

I'd be happy to help out as I would really like to use SDPA gmp in my work and not be tied to old versions of various packages. That said, my knowledge of MOI is rather limited and after looking through the release notes, it seems that most of the issue lies in the use of the discontinued load-allocate API. Are there any docs that could help me figure out which methods need to be defined (and how) for default_copy_to to work now that this is discontinued? I suppose the corresponding PR for SDPA.jl follows a different approach but after looking at it, it doesn't occur to me that one can just mindlessly follow that here? Any suggestions on the angle of attack?

Also, this might be a better job for someone already very familiar with the details of MOI. If so, just lmk and I'll wait. It is not critical.

Thanks!
Flemming

@ericphanson
Copy link
Owner Author

ericphanson commented Sep 17, 2022

I looked a little bit but also wasn’t sure all the changes needed — but I also don’t fully understand the current implementation, to be honest. I think there are some parts we are doing incorrectly (edit: that is, I do think we get the correct answers, but I think in some less important ways we aren’t hooked up fully correctly to how MOI is supposed to work).

I wonder if @odow or @blegat might be able to provide some guidance?

@blegat
Copy link
Contributor

blegat commented Sep 19, 2022

One way to simplify the MOI wrapper is to remove the Allocate-Load API implementation and replace it with a single MOI.copy_to implementation that would look like

function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
    full_input_path = joinpath(m.tempdir, inputname)
    sdpa = MOI.FileFormats.SDPA.Model()
    index_map = MOI.copy_to(sdpa, src)
    open(full_input_path, "w") do io
        write(io, sdpa)
    end
    return index_map
end

@FHoltorf
Copy link

Thanks for offering help so quickly! I tried to adjust the wrapper accordingly (see fork here). However, I am even running into issues building the model in SDPA format. Specifically, when executing

using SDPAFamily, JuMP

opt = () -> SDPAFamily.Optimizer()
m = Model(opt)
@variable(m, x)
@constraint(m, x >= 0)
@objective(m, Min, x)
optimize!(m)

I get an error (message below) suggesting that the SDPA format does not support non-negativity constraints on vector variables. I suspect that is unintended behavior as SDPA format typically supports LP blocks (right?). But before I go down the rabbit hole to understand what is happening there in greater detail, I meant to ask @blegat if this is potentially bug or if I am doing something silly.

Detailed error message:
ERROR: MathOptInterface.UnsupportedConstraint{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}: MathOptInterface.VectorOfVariables-in-MathOptInterface.Nonnegatives constraint is not supported by the model.
Stacktrace:
[1] add_constraint(model::MathOptInterface.FileFormats.SDPA.ModelVectorConstraints{Float64, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.PositiveSemidefiniteConeTriangle}}, func::MathOptInterface.VectorOfVariables, set::MathOptInterface.Nonnegatives)
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/lHZJh/src/Utilities/struct_of_constraints.jl:63
[2] add_constraint(model::MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, MathOptInterface.FileFormats.SDPA.ModelVectorConstraints{Float64, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.PositiveSemidefiniteConeTriangle}}}, func::MathOptInterface.VectorOfVariables, set::MathOptInterface.Nonnegatives)
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/lHZJh/src/Utilities/model.jl:379
[3] add_constrained_variables(model::MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, MathOptInterface.FileFormats.SDPA.ModelVectorConstraints{Float64, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.PositiveSemidefiniteConeTriangle}}}, set::MathOptInterface.Nonnegatives)
@ MathOptInterface ~/.julia/packages/MathOptInterface/lHZJh/src/variables.jl:209
[4] _try_constrain_variables_on_creation(dest::MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, MathOptInterface.FileFormats.SDPA.ModelVectorConstraints{Float64, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.PositiveSemidefiniteConeTriangle}}}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}, index_map::MathOptInterface.Utilities.IndexMap, #unused#::Type{MathOptInterface.Nonnegatives})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/lHZJh/src/Utilities/copy.jl:183
[5] default_copy_to(dest::MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, MathOptInterface.FileFormats.SDPA.ModelVectorConstraints{Float64, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.PositiveSemidefiniteConeTriangle}}}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/lHZJh/src/Utilities/copy.jl:487
[6] copy_to
@ ~/.julia/packages/MathOptInterface/lHZJh/src/Utilities/model.jl:496 [inlined]
[7] copy_to
@ ~/.julia/dev/SDPAFamily.jl/src/MOI_wrapper.jl:235 [inlined]
[8] optimize!(dest::SDPAFamily.Optimizer{BigFloat}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}})
@ MathOptInterface ~/.julia/packages/MathOptInterface/lHZJh/src/MathOptInterface.jl:86
[9] optimize!(m::MathOptInterface.Utilities.CachingOptimizer{SDPAFamily.Optimizer{BigFloat}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/lHZJh/src/Utilities/cachingoptimizer.jl:316
[10] optimize!
@ ~/.julia/packages/MathOptInterface/lHZJh/src/Bridges/bridge_optimizer.jl:376 [inlined]
[11] optimize!
@ ~/.julia/packages/MathOptInterface/lHZJh/src/MathOptInterface.jl:87 [inlined]
[12] optimize!(m::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{SDPAFamily.Optimizer{BigFloat}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/lHZJh/src/Utilities/cachingoptimizer.jl:316
[13] optimize!(model::Model; ignore_optimize_hook::Bool, kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ JuMP ~/.julia/packages/JuMP/Y4piv/src/optimizer_interface.jl:161
[14] optimize!(model::Model)
@ JuMP ~/.julia/packages/JuMP/Y4piv/src/optimizer_interface.jl:143
[15] top-level scope
@ ~/.julia/dev/SDPAFamily.jl/test/basic_test.jl:12

@odow
Copy link
Contributor

odow commented Sep 20, 2022

Do we just write out a file to send to the binaries? If so, we can probably greatly simplify things.

@FHoltorf
Copy link

We essentially do.

I did consider as a workaround using write_to_file to write the SDPA input file which does seem to work perfectly fine. But then I suspected it to be too much of pain to parse the output back from geometric conic form to whatever the original model was (say an SOS program or suchlike). Is there MOI functionality that could help with that inversion?

@odow
Copy link
Contributor

odow commented Sep 20, 2022

The example to follow is: https://github.com/jump-dev/AmplNLWriter.jl/blob/master/src/AmplNLWriter.jl. We just need to replace all the NL file bits with SDPA, and then replace the parsing of the .sol file with the appropriate SDPA equivalent.

If you have time/interest, it's probably a nice project to understand how MOI fits together, how to call binaries, and the intricacies of the SDPA file format.

Start by replacing
https://github.com/jump-dev/AmplNLWriter.jl/blob/b792051810f338c6d194c9c8bc470041594eac76/src/AmplNLWriter.jl#L81
with MOI.FileFormats.SDPA.Model{T}

the write happens here:
https://github.com/jump-dev/AmplNLWriter.jl/blob/b792051810f338c6d194c9c8bc470041594eac76/src/AmplNLWriter.jl#L254

For the tests, we can use a caching optimizer ad a bridge to map between the conic forms:
https://github.com/jump-dev/AmplNLWriter.jl/blob/b792051810f338c6d194c9c8bc470041594eac76/test/MOI_wrapper.jl#L25-L43

@FHoltorf
Copy link

That sounds like a good guideline! I will look into it!

@blegat
Copy link
Contributor

blegat commented Sep 20, 2022

I get an error (message below) suggesting that the SDPA format does not support non-negativity constraints on vector variables. I suspect that is unintended behavior as SDPA format typically supports LP blocks (right?)

Currently, the MOI wrapper supports: VectorOfVariables in Nonnegatives or PSD and equality constraints.
The FileFormats.SDPA.Model supports free variables and VectorAffineFunction in Nonnegatives and PSD because it's the dual
Since your supports constraint don't say the right things then you received constraints of the wrong type.
So remove the supports_constraint and supports_add_constrained_variables and replace them by the same as FileFormats.SDPA.Model
You'll need to update getting dual and primal solution since it's now dual to the previous MOI wrapper

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants