How to get lpsolveAPI to return all possible solutions?
Discovered that this was dupe with:
Get multiple solutions for 0/1-Knapsack MILP with lpSolveAPI
Here is the code I used to solve this adapted from the link:
# find first solution
status<-solve(lpmodel)
sols<-list() # create list for more solutions
obj0<-get.objective(lpmodel) # Find values of best solution (in this case four)
counter <- 0 #construct a counter so you wont get more than 100 solutions
# find more solutions
while(counter < 100) {
sol <- get.variables(lpmodel)
sols <- rbind(sols,sol)
add.constraint(lpmodel,2*sol-1,"<=", sum(sol)-1)
rc<-solve(lpmodel)
if (status!=0) break;
if (get.objective(lpmodel)<obj0) break;
counter <- counter + 1
}
sols
This finds all six solutions:
> sols
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
sol 1 0 0 1 0 1 0 1
sol 1 0 0 1 0 1 1 0
sol 0 1 0 1 0 1 0 1
sol 0 1 0 1 0 1 1 0
sol 0 1 0 0 1 1 1 0
sol 0 1 0 0 1 1 0 1
Sorry for the dupe everyone. If anyone knows another way built into the 'lpSolveAPI' package I'd still love to know.
All feasible solutions using lpSolveAPI in R
There are two different approaches to enumerate all feasible integer solutions.
The first is to add a cut to the constraints that forbids the previously found solution. I.e.
1. solve problem
2. if infeasible: done
3. record optimal solution x[i] into a[i]
4. add cut of the form
sum(i, (2*a[i]-1)*x[i]) <= sum(i,a[i])-1
5. go to step 1.
I assumed here the binary variables are x[i]
.
The second approach is to use the Cplex solution pool. This is much faster if there are many solutions.
PS: LpSolveApi
documents things like get.solutioncount
and select.solution
. I don't think that actually works.
Get multiple solutions for 0/1-Knapsack MILP with lpSolveAPI
Looks like that is broken. Here is a DIY approach for your specific model:
# first problem
rc<-solve(lp_model)
sols<-list()
obj0<-get.objective(lp_model)
# find more solutions
while(TRUE) {
sol <- round(get.variables(lp_model))
sols <- c(sols,list(sol))
add.constraint(lp_model,2*sol-1,"<=", sum(sol)-1)
rc<-solve(lp_model)
if (rc!=0) break;
if (get.objective(lp_model)<obj0-1e-6) break;
}
sols
The idea is to cut off the current integer solution by adding a constraint. Then resolve. Stop when no longer optimal or when the objective starts to deteriorate. Here is some math background.
You should see now:
> sols
[[1]]
[1] 1 0 1
[[2]]
[1] 0 1 1
Update
Below in the comments it was asked why coefficients of the cut have the form 2*sol-1. Again have a look at the derivation. Here is a counter example:
C1 C2
Maximize 0 10
R1 1 1 <= 10
Kind Std Std
Type Int Int
Upper 1 1
Lower 0 0
With "my" cuts this will yield:
> sols
[[1]]
[1] 0 1
[[2]]
[1] 1 1
while using the suggested "wrong" cuts will give just:
> sols
[[1]]
[1] 0 1
Related Topics
R Group By, Counting Non-Na Values
In R, How to Plot into a Memory Buffer Instead of a File
R + Ggplot2: How to Hide Missing Dates from X-Axis
Are Data Tables with More Than 2^31 Rows Supported in R with the Data Table Package Yet
3D Equivalent of the Curve Function in R
Change the Order of Stacked Fill Columns in Ggplot2
Reshaping Data to Plot in R Using Ggplot2
Combine Multiple PDF Plots into One File
How to Calculate Total Least Squares in R? (Orthogonal Regression)
Count Common Words in Two Strings
How to Rbind Only the Common Columns of Two Data Sets
How to Rearrange an Order of Matches Between Two Data Frames
How to Figure Third Friday of a Month in R
How to Color Entire Background in Ggplot2 When Using Coord_Fixed
Importing Data into R (Rdata) from Github
R Windows Os Choose.Dir() File Chooser Won't Open at Working Directory