Case Study

A manufacturing manager is in charge of minimizing the total costs (raw materials, labor and storage costs) of the following four months. In Table 3.1 can be found the cost of raw materials of one unit of final product, the demand of final product and the working hours available for each month. Labor costs are of 12 € per hour, and only worked hours are payed. Each unit of final product needs 30 minutes of labor. Storage costs are equal to 2 € for each unit stored at the end of the month. Any unit produced at a given month can be used to cover the demand of the same month, or be stored to cover the demand of months to come. At the beginning of month 1 there is no stock, and there are no minimum stock requirements for any month.
##                     Month One Two Three Four
## 1               Unit cost   6   8    10   12
## 2          Demand (units) 100 200   150  400
## 3 Working hours available 200 200   150  150

Problem definition

First, we define the following variables :

  • \(q_i\) is the quantity produced in month \(i\).
  • \(s_i\) is the stock at the end of month \(i\).

We would like to minimize the total cost so we must set our objective function as follows

\[cost(s_i, q_i) = 2 s_i + 12 q_i = MIN(cost)\]

Now, we will solving the problem using lpSolve and lpSolveAPI

Solution with lpSolve

lpsolve: is callable from R via an extension or module. As such, it looks like lpsolve is fully integrated with R. Matrices can directly be transferred between R and lpsolve in both directions.

## Warning: package 'lpSolve' was built under R version 3.6.2
## Success: the objective function is 0.1333333
## [1] 0.06666667 0.00000000
## [1] 0 4
## [1] 6e+00 1e+30
## [1] 0.00000000 0.00000000 0.01333333 0.00000000 0.00000000 8.00000000

So, the minimum value of z is 0.13, where \(q_i\) is 0.067, \(s_i\) is 0.00 and the sensitivity coefficient changes from 0 and 4 to 6e+00 and 1e+30.

Solution with lpSolveAPI

The lpSolveAPI R package is a second implementation of an interface of lpsolve to R. It provides an R API mirroring the lp_solve C API and hence provides a great deal more functionality but has a steeper learning curve.

## Warning: package 'lpSolveAPI' was built under R version 3.6.3
## $anti.degen
## [1] "fixedvars" "stalling" 
## 
## $basis.crash
## [1] "none"
## 
## $bb.depthlimit
## [1] -50
## 
## $bb.floorfirst
## [1] "automatic"
## 
## $bb.rule
## [1] "pseudononint" "greedy"       "dynamic"      "rcostfixing" 
## 
## $break.at.first
## [1] FALSE
## 
## $break.at.value
## [1] -1e+30
## 
## $epsilon
##       epsb       epsd      epsel     epsint epsperturb   epspivot 
##      1e-10      1e-09      1e-12      1e-07      1e-05      2e-07 
## 
## $improve
## [1] "dualfeas" "thetagap"
## 
## $infinite
## [1] 1e+30
## 
## $maxpivot
## [1] 250
## 
## $mip.gap
## absolute relative 
##    1e-11    1e-11 
## 
## $negrange
## [1] -1e+06
## 
## $obj.in.basis
## [1] TRUE
## 
## $pivoting
## [1] "devex"    "adaptive"
## 
## $presolve
## [1] "none"
## 
## $scalelimit
## [1] 5
## 
## $scaling
## [1] "geometric"   "equilibrate" "integers"   
## 
## $sense
## [1] "minimize"
## 
## $simplextype
## [1] "dual"   "primal"
## 
## $timeout
## [1] 0
## 
## $verbose
## [1] "neutral"
## [1] 0
## Model name: 
##             C1    C2          
## Minimize     2    12          
## R1           0     0  free   0
## R2           0     0  free   0
## R3           0     0  free   0
## R4           0     0  free   0
## R5         100   400    >=   6
## R6         200   400    >=   8
## R7         150   300    >=  10
## R8         400   300    >=  12
## Kind       Std   Std          
## Type      Real  Real          
## Upper      Inf   Inf          
## Lower        0     0
## [1] 0.06666667 0.00000000
## [1] 0.1333333
## $lower
## [1] 0 0
## 
## $upper
## [1] Inf Inf
LS0tDQp0aXRsZTogIkxpbmVhciBQcm9ncmFtbWluZyBNb2RlbGluZyINCmF1dGhvcjogIk5pY2hvbGFzIEFuZHJpYW4iDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KDQotLS0NCg0KYGBge3IgTG9nbywgZWNobz1GQUxTRSxmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICc0MCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkU6L2Rvd25sb2FkIGFuL2ZvdG8ucG5nIikNCmBgYA0KDQoNCiMgQ2FzZSBTdHVkeSANCg0KYGBgDQpBIG1hbnVmYWN0dXJpbmcgbWFuYWdlciBpcyBpbiBjaGFyZ2Ugb2YgbWluaW1pemluZyB0aGUgdG90YWwgY29zdHMgKHJhdyBtYXRlcmlhbHMsIGxhYm9yIGFuZCBzdG9yYWdlIGNvc3RzKSBvZiB0aGUgZm9sbG93aW5nIGZvdXIgbW9udGhzLiBJbiBUYWJsZSAzLjEgY2FuIGJlIGZvdW5kIHRoZSBjb3N0IG9mIHJhdyBtYXRlcmlhbHMgb2Ygb25lIHVuaXQgb2YgZmluYWwgcHJvZHVjdCwgdGhlIGRlbWFuZCBvZiBmaW5hbCBwcm9kdWN0IGFuZCB0aGUgd29ya2luZyBob3VycyBhdmFpbGFibGUgZm9yIGVhY2ggbW9udGguIExhYm9yIGNvc3RzIGFyZSBvZiAxMiDigqwgcGVyIGhvdXIsIGFuZCBvbmx5IHdvcmtlZCBob3VycyBhcmUgcGF5ZWQuIEVhY2ggdW5pdCBvZiBmaW5hbCBwcm9kdWN0IG5lZWRzIDMwIG1pbnV0ZXMgb2YgbGFib3IuIFN0b3JhZ2UgY29zdHMgYXJlIGVxdWFsIHRvIDIg4oKsIGZvciBlYWNoIHVuaXQgc3RvcmVkIGF0IHRoZSBlbmQgb2YgdGhlIG1vbnRoLiBBbnkgdW5pdCBwcm9kdWNlZCBhdCBhIGdpdmVuIG1vbnRoIGNhbiBiZSB1c2VkIHRvIGNvdmVyIHRoZSBkZW1hbmQgb2YgdGhlIHNhbWUgbW9udGgsIG9yIGJlIHN0b3JlZCB0byBjb3ZlciB0aGUgZGVtYW5kIG9mIG1vbnRocyB0byBjb21lLiBBdCB0aGUgYmVnaW5uaW5nIG9mIG1vbnRoIDEgdGhlcmUgaXMgbm8gc3RvY2ssIGFuZCB0aGVyZSBhcmUgbm8gbWluaW11bSBzdG9jayByZXF1aXJlbWVudHMgZm9yIGFueSBtb250aC4NCmBgYA0KDQpgYGB7cn0NCiNUYWJsZSAzLjENCk1vbnRoIDwtIGMoIlVuaXQgY29zdCIsICJEZW1hbmQgKHVuaXRzKSIsICJXb3JraW5nIGhvdXJzIGF2YWlsYWJsZSIpDQpPbmUgICA8LSBjKCA2LDEwMCwyMDApDQpUd28gICA8LSBjKCA4LDIwMCwyMDApDQpUaHJlZSA8LSBjKDEwLDE1MCwxNTApDQpGb3VyICA8LSBjKDEyLDQwMCwxNTApDQpUYWJsZSA8LSBkYXRhLmZyYW1lKE1vbnRoLCBPbmUsIFR3bywgVGhyZWUsIEZvdXIpDQpUYWJsZQ0KYGBgDQoNCiMjIFByb2JsZW0gZGVmaW5pdGlvbg0KRmlyc3QsIHdlIGRlZmluZSB0aGUgZm9sbG93aW5nIHZhcmlhYmxlcyA6DQoNCiogJHFfaSQgaXMgdGhlIHF1YW50aXR5IHByb2R1Y2VkIGluIG1vbnRoICRpJC4NCiogJHNfaSQgaXMgdGhlIHN0b2NrIGF0IHRoZSBlbmQgb2YgbW9udGggJGkkLg0KDQoNCldlIHdvdWxkIGxpa2UgdG8gbWluaW1pemUgdGhlIHRvdGFsIGNvc3Qgc28gd2UgbXVzdCBzZXQgb3VyIG9iamVjdGl2ZSBmdW5jdGlvbiBhcyBmb2xsb3dzDQoNCiQkY29zdChzX2ksIHFfaSkgPSAyIHNfaSArIDEyIHFfaSA9IE1JTihjb3N0KSQkDQoNCk5vdywgd2Ugd2lsbCBzb2x2aW5nIHRoZSBwcm9ibGVtIHVzaW5nIGBscFNvbHZlYCBhbmQgYGxwU29sdmVBUElgDQoNCiMjIFNvbHV0aW9uIHdpdGggYGxwU29sdmVgDQoNCmBscHNvbHZlOmAgaXMgY2FsbGFibGUgZnJvbSBSIHZpYSBhbiBleHRlbnNpb24gb3IgbW9kdWxlLiBBcyBzdWNoLCBpdCBsb29rcyBsaWtlIGxwc29sdmUgaXMgZnVsbHkgaW50ZWdyYXRlZCB3aXRoIFIuIE1hdHJpY2VzIGNhbiBkaXJlY3RseSBiZSB0cmFuc2ZlcnJlZCBiZXR3ZWVuIFIgYW5kIGxwc29sdmUgaW4gYm90aCBkaXJlY3Rpb25zLg0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygibHBTb2x2ZSIpDQpsaWJyYXJ5KGxwU29sdmUpDQoNCiMgc2V0IHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIG9iamVjdGl2ZSBmdW5jdGlvbg0Kby5mdW5jIDwtIGMoMiwgMTIpDQoNCiMgc2V0IG1hdHJpeCBjb3JyZXNwb25kaW5nIHRvIGNvZWZmaWNpZW50cyBvZiBjb25zdHJhaW50IGJ5IHJvd3MNCiMgRG9uJ3QgY29uc2lkZXIgdGhlIG5vbi1uZWdhdGl2ZSBjb25zdHJhaW50LCBpdCBpcyBhdXRvbWF0aWNhbGx5IGFzc3VtZWQNCmNvbnMgICA8LSBtYXRyaXgoYygxMDAsIDQwMCwNCiAgICAgICAgICAgICAgICAgICAyMDAsIDQwMCwNCiAgICAgICAgICAgICAgICAgICAxNTAsIDMwMCwNCiAgICAgICAgICAgICAgICAgICA0MDAsIDMwMCksIA0KICAgICAgICAgICAgICAgICBucm93ID0gNCwgYnlyb3cgPSBUKQ0KDQojIHNldCByaWdodCBoYW5kIHNpZGUgZm9yIHRoZSBjb25zdHJhaW50cw0KcmhzIDwtIGMoNiwgOCwgMTAsIDEyKQ0KDQojIHNldCBkaXJlY3Rpb24gb2YgdGhlIGNvbnN0cmFpbnRzDQpjLmRpcmVjdCA8LSBjKCI+PSIsICI+PSIsICI+PSIsICI+PSIpDQoNCiMgVGhlIEZpbmFsIHZhbHVlICh6KSA6IDAgPSBzdWNjZXNzLCAyID0gbm8gZmVhc2libGUgc29sdXRpb24NCmxwKCJtaW4iLCBvLmZ1bmMsIGNvbnMsIGMuZGlyZWN0LCByaHMpDQoNCiMgVmFyaWFibGVzIGZpbmFsIHZhbHVlcw0KbHAoIm1pbiIsIG8uZnVuYywgY29ucywgYy5kaXJlY3QsIHJocykkc29sdXRpb24NCg0KIyBzZW5zaXRpdml0aWVzDQpscCgibWluIiwgby5mdW5jLCBjb25zLCBjLmRpcmVjdCwgcmhzLCBjb21wdXRlLnNlbnM9VCkkc2Vucy5jb2VmLmZyb20NCmxwKCJtaW4iLCBvLmZ1bmMsIGNvbnMsIGMuZGlyZWN0LCByaHMsIGNvbXB1dGUuc2Vucz1UKSRzZW5zLmNvZWYudG8NCg0KIyBEdWFsIFZhbHVlcyAoZmlyc3QgZHVhbCBvZiB0aGUgY29uc3RyYWludHMgYW5kIHRoZW4gZHVhbCBvZiB0aGUgdmFyaWFibGVzKQ0KIyBEdWFscyBvZiB0aGUgY29uc3RyYWludHMgYW5kIHZhcmlhYmxlcyBhcmUgbWl4ZWQNCmxwKCJtaW4iLCBvLmZ1bmMsIGNvbnMsIGMuZGlyZWN0LCByaHMsIGNvbXB1dGUuc2Vucz1UKSRkdWFscw0KDQpgYGANCg0KU28sIHRoZSBtaW5pbXVtIHZhbHVlIG9mIHogaXMgMC4xMywgd2hlcmUgJHFfaSQgaXMgMC4wNjcsICRzX2kkIGlzIDAuMDAgYW5kIHRoZSBzZW5zaXRpdml0eSBjb2VmZmljaWVudCBjaGFuZ2VzIGZyb20gMCBhbmQgNCB0byA2ZSswMCBhbmQgMWUrMzAuDQoNCiMjIFNvbHV0aW9uIHdpdGggYGxwU29sdmVBUElgDQoNClRoZSBgbHBTb2x2ZUFQSWAgUiBwYWNrYWdlIGlzIGEgc2Vjb25kIGltcGxlbWVudGF0aW9uIG9mIGFuIGludGVyZmFjZSBvZiBgbHBzb2x2ZWAgdG8gUi4gSXQgcHJvdmlkZXMgYW4gUiBBUEkgbWlycm9yaW5nIHRoZSBgbHBfc29sdmVgIEMgQVBJIGFuZCBoZW5jZSBwcm92aWRlcyBhIGdyZWF0IGRlYWwgbW9yZSBmdW5jdGlvbmFsaXR5IGJ1dCBoYXMgYSBzdGVlcGVyIGxlYXJuaW5nIGN1cnZlLg0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygibHBTb2x2ZUFQSSIpDQpsaWJyYXJ5KGxwU29sdmVBUEkpDQoNCiMgU2V0IDQgY29uc3RyYWludHMgYW5kIDIgZGVjaXNpb24gdmFyaWFibGVzDQpscHJlYyAgIDwtIG1ha2UubHAobnJvdyA9IDQsIG5jb2wgPSAyKQ0KDQojIFNldCB0aGUgdHlwZSBvZiBwcm9ibGVtIHdlIGFyZSB0cnlpbmcgdG8gc29sdmUNCmxwLmNvbnRyb2wobHByZWMsIHNlbnNlPSJtaW4iKQ0KDQojIFNldCBvYmplY3RpdmUgZnVuY3Rpb24gY29lZmZpY2llbnRzIHZlY3Rvcg0Kc2V0Lm9iamZuKGxwcmVjLCBvLmZ1bmMpDQoNCiMgQWRkIGNvbnN0cmFpbnRzDQphZGQuY29uc3RyYWludChscHJlYywgY29uc1sxLCBdLCAiPj0iLCByaHNbMV0pDQphZGQuY29uc3RyYWludChscHJlYywgY29uc1syLCBdLCAiPj0iLCByaHNbMl0pDQphZGQuY29uc3RyYWludChscHJlYywgY29uc1szLCBdLCAiPj0iLCByaHNbM10pDQphZGQuY29uc3RyYWludChscHJlYywgY29uc1s0LCBdLCAiPj0iLCByaHNbNF0pDQoNCmBgYA0KYGBge3J9DQojIFNvbHZlIHByb2JsZW0NCnNvbHZlKGxwcmVjKQ0KYGBgDQpgYGB7cn0NCiMgRGlzcGxheSB0aGUgbHBzb2x2ZSBtYXRyaXgNCmxwcmVjDQpgYGANCg0KYGBge3J9DQojIEdldCB0aGUgZGVjaXNpb24gdmFyaWFibGVzIHZhbHVlcw0KZ2V0LnZhcmlhYmxlcyhscHJlYykNCmBgYA0KDQpgYGB7cn0NCiMgR2V0IHRoZSB2YWx1ZSBvZiB0aGUgb2JqZWN0aXZlIGZ1bmN0aW9uDQpnZXQub2JqZWN0aXZlKGxwcmVjKQ0KYGBgDQoNCmBgYHtyfQ0KIyBOb3RlIHRoYXQgdGhlIGRlZmF1bHQgYm91bmRhcmllcyBvbiB0aGUgZGVjaXNpb24gdmFyaWFibGUgYXJlIGMoMCwgMCkgYW5kIGMoSW5mLCBJbmYpDQpnZXQuYm91bmRzKGxwcmVjKQ0KYGBgDQoNCmBgYHtyfQ0KIyBCb3VuZGFyaWVzIGNhbiBiZSBzZXQgd2l0aCBmb2xsb3dpbmcgZnVuY3Rpb24NCmxwU29sdmVBUEk6OnNldC5ib3VuZHMobHByZWMpDQpgYGANCg0K