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

Is it possible to read an MPS model? #25

Open
senhalil opened this issue Sep 19, 2022 · 10 comments
Open

Is it possible to read an MPS model? #25

senhalil opened this issue Sep 19, 2022 · 10 comments

Comments

@senhalil
Copy link

It looks like CBC has a function for this purpose Cbc_readMps, a similar function in ruby-cbc would make it possible to call problem.find_conflict with an MPS file.

@gverger
Copy link
Owner

gverger commented Sep 19, 2022

It is not possible to get the problem from a file (MPS or LP).

I totally get your usecase and why it would be helpful.
The issue I see is that ruby-cbc uses its own data model, and transmits it to cbc only at the moment it wants a computation done. The only communication from Cbc to Ruby is the result values, not the problem itself.

If I want to add something to read a MPS file, I see 2 options:

  1. Write the complete parser and not rely on Cbc to populate the ruby model.
  2. Find how to get the model from Cbc and map it to the ruby model, to be able to use Cbc_readMps.

Neither of these 2 options seem easy, and I don't think I will have time to do it. You would be very welcome to propose something though :)

I'll try and check how feasible it would be to have solution 2 done, but I can't promise anything.

@gverger
Copy link
Owner

gverger commented Sep 19, 2022

I got some time tonight and implemented a MPS reader: I really like the idea of initializing a problem from any file, it would allow someone who generated such a file to benefit from the conflict finder.

It is not fully tested and is probably inefficient at loading a file, but it seems to work well on the file I tested.

You can try the branch feature/fromfile #26 :

model = Cbc::Utils::Mps.new("path_to_file.mps").to_model
p = model.to_problem
p.solve #should be infeasible
p.proven_infeasible? # => true
p.find_conflict

Tell me if that works for you!

@senhalil
Copy link
Author

@gverger thanks a lot for the quick response and even quicker dev, I will try this afternoon.

@senhalil
Copy link
Author

senhalil commented Sep 20, 2022

@gverger hello again, I am not sure what went wrong but on my Mac, cbs-wrapper cannot find the cbc library. I guess something is changed since this comment and brew install cbc doesn't install the library files 🤷

Edit: I am actually not sure if the reason was brew install not installing the libraries or if it was due to gem install cbc-wrapper not being able to find the cbc libs -- because I continued to have problems after re-installing the cbc via coin-or-tools/coinor/cbc (which is the suggested way for Mac) which definitely installs the libcbcsolver.so. So I had to manually create a config set for cbc-wrapper installation and set the with-cbc-dir directory so that cbc-warpper can be installed -- i.e., bundle config set --global build.cbc-wrapper --with-cbc-dir=/opt/homebrew/opt/cbc.

@gverger
Copy link
Owner

gverger commented Sep 20, 2022

Hello, thanks for the feedback.
Unfortunately I am in the dark with the macos installation: I don't have a mac anymore...

It seems that for mac (Apple Silicon) the homebrew directory has changed compared to mac Intel: see here

@senhalil
Copy link
Author

I managed to get my setup working (sorry! my previous message didn't make that clear).

I just read my infeasible model; however, I am getting the following error even though the objective function is defined and OBJ exists in the model

No MAX/MIN found after OBJSENSE
No match for row OBJ at line #...
...
Coin0008I no_name read with 28 errors
/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/bundler/gems/ruby-cbc-6b1bab73cdbd/lib/ruby-cbc/problem.rb:102:
in `create_cbc_problem': undefined method `kind' for nil:NilClass (NoMethodError)

Screen Shot 2022-09-20 at 18 19 58

Screen Shot 2022-09-20 at 18 19 30

@gverger
Copy link
Owner

gverger commented Sep 20, 2022

I think it should be like

OBJSENSE
 MAX
ROWS
...

EDIT: but it seems cbc ignores OBJSENSE

MIN found after OBJSENSE - Coin ignores
MAX found after OBJSENSE - Coin ignores

@senhalil
Copy link
Author

It turns out OBJSENSE is a solver dependent construct and Gurobi implements it as a single line ref, Cplex does two lines ref (at least it used to do it like that) and it looks like CBC "fudges" it altogether (determining the sense and then discarding it is quite weird 🤷). This is quite okay for infeasibility detection but not very cool for reading MPS files dumped by other solvers.

If I remove OBJSENSE find_conflict returns the conflicting constraint correctly so the reader is working ✅ Thanks for the dev! Sorry I wasn't of much help.

Regarding OBJSENSE incompatibility, I guess a solution would be reading the MPS file and if it has OBJSENSE and it is maximization*, setting the direction via setObjSense function after CBC reader is completed. Or keeping this info inside the model side and passing it back again to the problem. Don't know what would be the easiest or if it would worth it 🤷

*: At least Cplex, Gurobi and CBC are on the same page about the default objective function direction being minimization I believe.

@gverger
Copy link
Owner

gverger commented Sep 21, 2022

Yes, it seems OBJSENSE is an extension of the original MPS format and they couldn't agree on how it should be written.

I'll think about how I want it to be dealt with here.
My first instinct would be to just use Cbc to read the MPS file since ruby-cbc is supposed to wrap cbc.
But then it is good if it can read models from Gurobi and CPLEX because if you use the mps file as an input, there are chances that it comes from either of these solvers.

Thanks for reporting the issue, I don't work on this gem a lot since I don't use it anymore, but I am very happy to keep it alive :)

I'll finalize the mps reader at some point and close this issue.

@senhalil
Copy link
Author

senhalil commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants