The Diet Problem with lpSolve

This relates to Coursera's “Linear and Integer Programming” course, September 2013.

The solution shown here was kindly provided by Hao Lu on the course discussion forum.

Data Preparation

The tables we need were supplied by the course tutors in .xlsx format, readable by varius spreadsheet programs (including Excel if you have it, LibreOffice Calc if you prefer free software).

In “dataFiles_DietProblemData.xlsx”, please delete the second row “Index” of the first spreadsheet. Then export the first two spreadsheets into two csv files: the data and constraints, respectively.

Calculation

# Filenames for data and constraints
dataFileName <- "dataFiles_DietProblemData_nut.csv"
constraintsFileName <- "dataFiles_DietProblemData_bound.csv"

# data layout information
dataColumns <- 11  # number of decision variables
costColumn <- 12

# Set up data - nutrition table in the Diet Problem example
data <- read.csv(dataFileName)
rownames(data) <- data$Food
data$Food <- NULL
data$Index <- NULL
A <- as.matrix(data[, -costColumn])

# the right-most column is cost per unit, e.g.'Price/serving ($)'
Cost <- as.matrix(data[, costColumn, drop = FALSE])

# Set up constraints - e.g. max/min for each nutrient type
boundaries <- read.csv(constraintsFileName)
b <- c(boundaries$Min, boundaries$Max)

# The R-CRAN package lpSolve must be installed on your system
require("lpSolve")
## Loading required package: lpSolve

# Run the solver
res <- lp(objective.in = Cost, const.mat = rbind(t(A), t(A)), const.dir = c(rep(">=", 
    nrow(boundaries)), rep("<=", nrow(boundaries))), const.rhs = b)

Results

# Get the results into a more human-readable format
amount <- res$solution
names(amount) <- rownames(data)
amount[amount != 0]
##        Carrots,Raw    Potatoes, Baked          Skim Milk 
##             0.2358             3.5449             2.1678 
##      Peanut Butter Popcorn,Air-Popped 
##             3.6008             4.8232

# print Optimal objective value (lowest total cost in $ for the diet
# example)
res$objval
## [1] 0.956