conroylau / lpinfer

lpinfer: An R Package for Inference in Linear Programs
GNU General Public License v3.0
3 stars 5 forks source link

Write a wrapper for standard.form that is more tailored to our problem #64

Open a-torgovitsky opened 4 years ago

a-torgovitsky commented 4 years ago

Goal

Allow the user to input a linear program in a more natural form, and then have it converted directly into a standard form lpmodel

Problem

It is not clear to me how one would go about doing this with standard.form. I think we need something more expressive for the user.

lpmodel

An lpmodel has three components:

In addition, we have currently assumed that x >= 0 is always imposed, but in general we might prefer something different; either a different lower bound, or a different upper bound, or both.

A "natural form" lpmodel

Create a new class lpmodel.natural that has these components:

Write a function that converts an lpmodel.natural to an lpmodel

This could use most of the code/ideas already in standard.form, but would be easier for the user to understand, since it just requires specifying an lpmodel.natural.

conroylau commented 4 years ago

Done! I have added a new function standard.form, a new class lpmodel.natural and the corresponding unit test.

The new function will convert an lpmodel.natural object to an lpmodel object -- in particular, consolidating the inequalities from the shape constraints, the upper and lower bounds into a new A.shp and beta.shp matrix in standard form.

Below is an example:

# obs matrices
Aobs <- matrix(c(1,1,2,3,3,7), nrow = 2, byrow = TRUE)
bobs <- matrix(c(6,20), nrow = 2, byrow = TRUE)
sobs <- matrix(rep("=", 2), nrow = 2, byrow = TRUE)

# shp matrices
Ashp <- matrix(c(10,0,0,2,1,2), nrow = 2, byrow = TRUE)
bshp <- matrix(c(1,10), nrow = 2, byrow = TRUE)
sshp <- matrix(c(">=", "<="), nrow = 2, byrow = TRUE)

# tgt matrices
Atgt <- matrix(c(1,2,3), nrow = 1, byrow = TRUE)
btgt <- c(9)
stgt <- c("=")

# lb and ub
xlb <- c(0.01,0.02,0.03)
xub <- c(1000,2000,3000)

# Get `lpmodel.natural`
lpmn <- lpmodel.natural(A.obs = Aobs,
                        A.shp = Ashp,
                        A.tgt = Atgt,
                        beta.obs = bobs,
                        beta.shp = bshp,
                        sense.shp = sshp,
                        x.lb = xlb,
                        x.ub = xub)

Applying the standard.form function, i.e. it will give the following updated matrices.

> lpm <- standard.lpmodel(lpmn)
> lpm$A.shp
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,]    2    1    2    1    0    0    0    0    0     0     0
[2,]    1    0    0    0    1    0    0    0    0     0     0
[3,]    0    1    0    0    0    1    0    0    0     0     0
[4,]    0    0    1    0    0    0    1    0    0     0     0
[5,]   10    0    0    0    0    0    0   -1    0     0     0
[6,]    1    0    0    0    0    0    0    0   -1     0     0
[7,]    0    1    0    0    0    0    0    0    0    -1     0
[8,]    0    0    1    0    0    0    0    0    0     0    -1
> lpm$beta.shp
      [,1]
[1,] 1e+01
[2,] 1e+03
[3,] 2e+03
[4,] 3e+03
[5,] 1e+00
[6,] 1e-02
[7,] 2e-02
[8,] 3e-02

In addition, printing the lpmn object above (with class lpmodel.natural) will give the following message (similar to printing a lpmodel object):

Object     Class    Dimension   Length 
A.obs      matrix   2x3     1
A.shp      matrix   2x3     1
A.tgt      matrix   1x3     1
beta.obs   matrix   2x1     1
beta.shp   matrix   2x1     1
sense.shp  matrix   2x1     1
x.lb       numeric  1x3     1
x.ub       numeric  1x3     1

I also use the above set-up in the unit test, where I use Gurobi to confirm the objective value and the optimal vector is the same for the linear programs in standard form and the non-standard form. Thanks!

a-torgovitsky commented 4 years ago

This looks great!

I will try to come up with a good real-world example for testing this. I'm going to leave the issue open until then.

conroylau commented 4 years ago

Thank you! I have also just updated the README about the part on using standard.lpmodel and lpmodel.natural.