Skip to Content
Course content

196: Linear Programming with lpSolve

Click on the "Edit" button in the top corner of the screen to edit your slide content.

A few years ago, I was consulting for a boutique furniture maker who was struggling with their production schedule. They made two things: high-end dining tables and ergonomic office chairs. Each required a different amount of mahogany and labor hours. The owner was essentially guessing how many of each to build every month to maximize profit, often ending up with leftover wood but no staff hours left, or vice versa. He thought he needed a complex AI system to solve this. In reality, he just needed a simple linear programming model. Once I plugged his constraints into R, we found a production mix that increased his monthly margin by nearly 15% without hiring a single new employee.

Linear programming is essentially the art of finding the "best" outcome (like maximum profit or lowest cost) in a mathematical model whose requirements are represented by linear relationships. In R, the lpSolve package is the go-to tool for this. It doesn't require you to be a mathematician; you just need to be able to express your problem as a set of linear equations.

Mapping the Objective and Constraints

To use lpSolve, you have to translate your real-world problem into four specific components: the objective function, the constraint matrix, the direction of the inequalities, and the right-hand side values. Let's use that furniture example. Suppose a table yields $100 profit and a chair yields $40. We want to maximize 100x + 40y.

library(lpSolve)

# The objective function coefficients (Profit per unit)
# Table: 100, Chair: 40
f.obj <- c(100, 40)

# The constraint matrix
# Row 1: Mahogany used (Table: 10 units, Chair: 3 units)
# Row 2: Labor hours used (Table: 5 hours, Chair: 4 hours)
f.con <- matrix(c(10, 3,
                   5, 4), nrow = 2, byrow = TRUE)

# The direction of the constraints (Less than or equal to)
f.dir <- c("<=", "<=")

# The right-hand side (Available resources)
# 100 units of mahogany, 80 labor hours
f.rhs <- c(100, 80)

# Run the solver to maximize the objective
result <- lp("max", f.obj, f.con, f.dir, f.rhs)

I've found that the most common mistake people make is misaligning the f.con matrix. If your objective function is c(100, 40), the first column of your matrix must represent the constraints for the tables, and the second column must represent the chairs. If you swap them, your results will be nonsense.

Decoding the Solver's Output

The lp() function returns a list, but the two things you actually care about are the optimal value of the objective function and the values of the variables that got you there. In our furniture case, we want to know exactly how many tables and chairs to build.

# The total maximum profit
result$objval 

# The optimal number of tables and chairs
result$solution

If result$solution returns c(7, 7.5), you've hit a snag: you can't build half a chair. Linear programming assumes variables are continuous. If you need whole numbers, you're moving into Integer Programming. Fortunately, lpSolve handles this easily with the all.int = TRUE argument inside the lp() call. I always recommend adding this if you're dealing with physical goods; otherwise, you'll be trying to explain to a shop foreman why he needs to manufacture 0.3 of a table.




📋 Practical Task

Optimizing a Digital Marketing Budget

You are managing a marketing budget for a new app. You have a total budget of $5,000 to spend on two platforms: Social Ads and Search Ads. Your goal is to maximize the total number of new user sign-ups.

  • Social Ads: Cost $2 per sign-up.
  • Search Ads: Cost $5 per sign-up.

However, you have the following constraints:

  • The total spend cannot exceed $5,000.
  • To maintain brand presence, you must spend at least $1,000 on Social Ads.
  • Due to platform limits, you cannot spend more than $3,000 on Search Ads.

Write an R script using lpSolve to determine the optimal amount to spend on each platform to maximize sign-ups. Note: Since you are optimizing the number of sign-ups, your objective function should reflect the "yield" per dollar spent (e.g., if a sign-up costs $2, the yield is 0.5 sign-ups per dollar). Use all.int = FALSE as budget spend is continuous.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.