Skip to content

Conversation

@jd-lara
Copy link
Collaborator

@jd-lara jd-lara commented Aug 23, 2019

This is pretty much work in progress to update the solver. See jump-dev/MathOptInterface.jl#736

@jd-lara
Copy link
Collaborator Author

jd-lara commented Aug 23, 2019

@odow what's the new implementation of LQOI.VecLin?

    (LQOI.VecLin, MOI.Nonnegatives),
    (LQOI.VecLin, MOI.Nonpositives),
    (LQOI.VecLin, MOI.Zeros)

@odow
Copy link
Member

odow commented Aug 23, 2019

They are removed. Use the full_bridge_optimizer instead.

@jd-lara
Copy link
Collaborator Author

jd-lara commented Aug 23, 2019

Thanks, I haven't get there yet. The current changes are at Line 1361 of MOIWrapper

Copy link
Member

@joaquimg joaquimg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add another pass in a few hours!

MOI.supports(::Optimizer, ::MOI.ObjectiveFunctionType) = true

MOI.supports(::Optimizer, ::MOI.Name) = true
MOI.supports(::Optimizer, ::MOI.Silent) = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work on Windows.
We can add a operational system check and send a warning explaning that the C API does not allow it. A callback must be implemented of the external file must be used.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs testing

end

function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, limit::Real)
MOI.set(model, MOI.RawParameter("TimeLimit"), limit)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this won't work right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs testing


return
end
=#
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is (TODO)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can see docs of XPRSchgobj
the constant is the values associated with the index -1

to add the objective function: 25 + 5.3 * x_2 + 0.1 * x_5

mindex[0] = -1; mindex[1] = 2; mindex[2] = 5;
obj[0] = 25.0; obj[1] = 5.3; obj[2] = 0.1;
XPRSchgobj(prob,3,mindex,obj);

We can query this value with the OBJRHS attribute

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joaquimg can you confirm here please?

MOI.Semicontinuous{Float64}
else
nothing # Also covers `NONE` and `LESS_THAN`.
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need a specific value for existing_set ? cc @odow
we seem to be allowing type instability without necessity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

existing_set is used in the LowerBoundAlreadySet error. We could hard-code the throw into each branch, but it doesn't seem necessary. The compiler is probably smart enough. You could benchmark if interested.

@blegat
Copy link
Member

blegat commented Aug 26, 2019

Call the file MOI_wrapper, not MOIWrapper

Copy link
Member

@odow odow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to look at the recent changes to Gurobi and GLPK.

Once I had written Gurobi, my approach to write GLPK was to comment everything out, and then slowly add a function at a time re-running the tests every couple of minutes. Then you can have something that consistently compiles, but just fails a heap of tests and slowly improve.

@jd-lara
Copy link
Collaborator Author

jd-lara commented Aug 28, 2019

Made updates up to line 1718 and addressed most comments.

Copy link
Contributor

@frapac frapac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This review adresses minor typos in the new MOI wrapper of Xpress.

end

# ==============================================================================
# Callbacks in Gurobi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gurobi -> Xpress?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't got this far currently still at line 1718

throw(MOI.InvalidIndex(c))
end

function MOI.add_constraint(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it could be worthwile to add a bridge SOCToQuadBridge in MOI?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, Xpress supports both SOC and Quad and we could get to a point of supporting both

@joaquimg
Copy link
Member

Any plans for updates here?

@jd-lara
Copy link
Collaborator Author

jd-lara commented Sep 10, 2019

@joaquimg I made some progress, I pretty much ended up copying and pasting the code from the old wrapper for the Termination Status and found the equivalent in three different places for the raw strings. Please take a look, If I got the logic right from the old wrapper then the stop status is only used when specific termination status are triggered.

I am sort of stuck implementing the get_primal and get_dual functions starting in line 1922. My impression is that in Gurobi the values can be queried by individual variable and constraint (@odow?). However, in the old MOI wrapper (both in Gurobi and Xpress) the strategy was to return all of the primals into a container (get_linear_primal_solution!(m, x::Vector{Float64})) and Xpress doesn't seem to have the capability to get an attribute for a specific row and column as Gurobi has. Any pointers on how to proceed in this case? My first inclination would be to return all the solutions into a vector and then index into it. But, this will allocate a vector of all the solutions every time a specific variable or constraint gets queried.

Also looked into GLPK.jl and GLPK supports querying individual rows and constraints. Xpress seems to be limited to getting the solutions through getlpsol

@jd-lara
Copy link
Collaborator Author

jd-lara commented Sep 10, 2019

The last line modified is 2020, this leaves the new wrapper pretty much at the same place as the old. The following sections are about problem modification and callbacks.

@joaquimg
Copy link
Member

Lets get the entire solution vector from Xpress right after solve and then access it.
This is pretty reasonable and probably even more efficient.

@odow
Copy link
Member

odow commented Sep 10, 2019

@odow should I copy the tests from Gurobi.jl as well and go from there?

Yes. The Gurobi tests, especially the MOI.Test ones are pretty comprehensive.

Copy link
Member

@joaquimg joaquimg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the raw status I would map the actual xpress internal status to the string in the manual. And not the MOI statuses into detailed strings.

if length(f) != length(s)
error("Number of functions does not equal number of sets.")
end
canonicalized_functions = MOI.Utilities.canonical.(f)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we need to cannonicalize. Might worth check in the manual

throw(MOI.ScalarFunctionConstantNotZero{Float64, eltype(f), eltype(s)}(fi.constant))
end
nnz += length(fi.terms)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding zeros might be faster than filtering

@jd-lara
Copy link
Collaborator Author

jd-lara commented Sep 11, 2019

Lets get the entire solution vector from Xpress right after solve and then access it.
This is pretty reasonable and probably even more efficient.

My thinking about this is then to create a new field in model (previously names instance) struct with the complete solution and then query from there.

@joaquimg
Copy link
Member

Vectors in the optimizer are ok. Struct with vector inside optimizer is also ok.

At some point I plan to only grab part of the solution. For instance, not querying slacks e not even duals, only primals. Then maybe do that in que lazy way. Just query the primal vector when the first primal is asked for. (None os this is needed now, just a heads up on future plans)

@joaquimg
Copy link
Member

Let me know if you have more questions

@jd-lara
Copy link
Collaborator Author

jd-lara commented Sep 22, 2019

I need to experiment more with the return objects of the get solution from Xpress. Also, the PSCC deadline is coming. I will get back to this after that.

@joaquimg
Copy link
Member

Nice! I did imagine you could be distracted by PSCC, hope we can meet there next year ;)

@jd-lara
Copy link
Collaborator Author

jd-lara commented Oct 9, 2019

@joaquimg is this needed in Xpress? I commented out for now to look for the Xpress equivalent of these settings.

    Note that we set the parameter `InfUnbdInfo` to `1` rather than the default
    of `0` so that we can query infeasibility certificates. Users are, however,
    free to over-ride this as follows `Optimizer(InfUndbInfo=0)`. In addition,
    we also set `QCPDual` to `1` to enable duals in QCPs. Users can override
    this by passing `Optimizer(QCPDual=0)`.

@odow
Copy link
Member

odow commented Oct 9, 2019

is this needed in Xpress?

I think it's just a Gurobi specific thing

@joaquimg
Copy link
Member

Exactly, that is a Gurobi thing.
The related xpress detail is that the presolve must be disabled if you want to query infeasibility certificates. I to that explicitly on MOI_Wrapper tests

error("Invalid Xpress license")
else
error("Failed to create environment (error $ret).")
mutable struct Env
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure we should keep this...
it does not hold info like gurobi's, its just a boot in the library

@jd-lara
Copy link
Collaborator Author

jd-lara commented Oct 28, 2019

closed in favor of #43

@jd-lara jd-lara closed this Oct 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants