dirkschumacher / ompr

R package to model Mixed Integer Linear Programs
https://dirkschumacher.github.io/ompr/
Other
269 stars 35 forks source link

Unbounded LPs reported as Infeasible #248

Open prof-anderson opened 5 years ago

prof-anderson commented 5 years ago

Here is a simple two variable problem that returns a status of infeasible when it should be unbounded. I tested this three solver (glpk, lpsolve, and symphony). All packages are up to date from CRAN.

library (ROI, quietly = TRUE)      
library (ROI.plugin.glpk, quietly = TRUE) 
library (ompr, quietly = TRUE)   
library (ompr.roi, quietly = TRUE)
library (magrittr)

model_unbounded <- MIPModel() %>%
  add_variable(x, type = "continuous", lb = 0) %>%
  add_variable(y, type = "continuous",lb = 0) %>%

  set_objective(x+y, "max") %>%

  add_constraint(x+y >= 2000) #fabrication

result_unbounded <-  solve_model(model_infeas, with_ROI(solver = "glpk"))
print(solver_status(result_unbounded))

library (ROI.plugin.symphony, quietly = TRUE) # Plugin for solving

result_unbounded <-  solve_model(model_infeas, with_ROI(solver = "glpk"))
print(solver_status(result_unbounded))

library (ROI.plugin.lpsolve, quietly = TRUE) # Plugin for solving

result_unbounded <-  solve_model(model_infeas, with_ROI(solver = "glpk"))
print(solver_status(result_unbounded))
prof-anderson commented 5 years ago

Minor correction to last two solves but it does still return [1] "infeasible" for all three solvers. (This is a minimal code example from a larger case where I ran into the problem.)

`library (ROI, quietly = TRUE) # R Optimization Interface library (ROI.plugin.glpk, quietly = TRUE) # Plugin for solving library (ompr, quietly = TRUE) # Allows specifying model algebraically library (ompr.roi, quietly = TRUE) # Glue for ompr to solve with ROI library (magrittr)

model_unbounded <- MIPModel() %>% add_variable(x, type = "continuous", lb = 0) %>% add_variable(y, type = "continuous",lb = 0) %>%

set_objective(x+y, "max") %>%

add_constraint(x+y >= 2000) #fabrication

result_unbounded <- solve_model(model_infeas, with_ROI(solver = "glpk")) print(solver_status(result_unbounded))

library (ROI.plugin.symphony, quietly = TRUE) # Plugin for solving

result_unbounded <- solve_model(model_infeas, with_ROI(solver = "symphony")) print(solver_status(result_unbounded))

library (ROI.plugin.lpsolve, quietly = TRUE) # Plugin for solving

result_unbounded <- solve_model(model_infeas, with_ROI(solver = "lpsolve")) print(solver_status(result_unbounded)) `

dirkdegel commented 5 years ago

Hi prof-anderson,

I'm not 100% sure but you solve the "model_infeas" in the solve statement, which is not defined in the code you are providing. I assume it was used before and is still in memory. If you are using "solve_model(model_unbounded , with_ROI(solver = "glpk"))" it should be fine.

prof-anderson commented 5 years ago

Good spot. I had typos from trying to simplify and come up with a short example. Thanks.

I fixed the typos and it is still returning infeasible rather than unbounded.

library (ROI, quietly = TRUE)      # R Optimization Interface
library (ROI.plugin.glpk, quietly = TRUE) # Plugin for solving
library (ompr, quietly = TRUE)     # Allows specifying model algebraically
library (ompr.roi, quietly = TRUE) # Glue for ompr to solve with ROI
library (magrittr)

model_unbounded <- MIPModel() %>%
  add_variable(x, type = "continuous", lb = 0) %>%
  add_variable(y, type = "continuous",lb = 0) %>%

  set_objective(x+y, "max") %>%

  add_constraint(x+y >= 2000) #fabrication

result_unbounded <-  solve_model(model_unbounded, with_ROI(solver = "glpk"))
print(solver_status(result_unbounded))

library (ROI.plugin.symphony, quietly = TRUE) # Plugin for solving

result_unbounded <-  solve_model(model_unbounded, with_ROI(solver = "symphony"))
print(solver_status(result_unbounded))

library (ROI.plugin.lpsolve, quietly = TRUE) # Plugin for solving

result_unbounded <-  solve_model(model_unbounded, with_ROI(solver = "lpsolve"))
print(solver_status(result_unbounded))
hugolarzabal commented 5 years ago

Hello What version of ompr are you using ? When I try your example, the status is "unbounded" with every solver.

Edit: I think your problem is related with that post in ompr.ROI https://github.com/dirkschumacher/ompr.roi/issues/17 I am currently using the pull request versions of ompr and ompr.ROI used by rickyars after he noticed those problems so I see the true status from the solver:

$code [1] 1

$msg solver symphony code 237 symbol TM_UNBOUNDED message TM_UNBOUNDED roi_code 1

the current version of ompr.roi only use two status "optimal" and "infeasible" which actually mean "success" and "failure" and are the direct translation of code = 0 or code = 1.

Edit2: If you want to use the pull request version of rickyars, you may need to merge it manually with ompr master first since it is not based on the most recent version of ompr.

sbmack commented 5 years ago

Re: Dirk:

Edit2: If you want to use the pull request version of rickyars, you may need to merge it manually with ompr master first since it is not based on the most recent version of ompr.

Do you have instructions for how to do that?

Thanks,

SteveM

hugolarzabal commented 5 years ago

You have to create a new branch of the project from rickyars pull request in your own repository in github and then merge it with the master.

I made it myself a few months ago, it is not really dificult but I don't remember the exact steps.

prof-anderson commented 5 years ago

Thanks. I thought I was going a little crazy. That seems like it is the exact source of the problem.

I am using 0.8.0 from CRAN. Using an unreleased version isn't really an option for me since I have students using a mix of platforms (PC, Mac, RStudio.cloud) and R proficiency.

If the issue is interpretation of the 0 status, a quick and dirty hack would be to change the returned message from "Infeasible" to "Infeasible/Unbounded" or "No Optimal Solution Found" and let the analyst infer the situation.

A more full fix could then be incorporated later, perhaps using part of the fork mentioned above.

Thanks again!

dirkschumacher commented 5 years ago

Is this an immediate need for an ongoing course? I will try to work on this and the PR's of @rickyars next.

hugolarzabal commented 5 years ago

If the issue is interpretation of the 0 status, a quick and dirty hack would be to change the returned message from "Infeasible" to "Infeasible/Unbounded" or "No Optimal Solution Found" and let the analyst infer the situation.

Yes, it is exactly that. The meaning of 0 and 1 thought may differ slightly between solver:

Also solvers have verbosity options and print their results. It is hard to recover this information to use in a script but you can at least see it on your screen.

dirkschumacher commented 2 years ago

ROI's status code is documented to be the following:

The status code is 0 on success (no error occurred) 1 otherwise.

So what we could do is add another status code called success and let ompr.roi return success if code = 0 and error if code = 1.

dirkschumacher commented 2 years ago

We should probably do two things in the future:

A recent addition to ompr.roi now also returns the full solver specific message/status. So that can be used as well.