I have a simple non-linear example listed below that properly calculates 1 data set perfectly using the ROI package. In the code, I am filtering on CompanyA only. The goal is to minimize total cost by hiring the optimal number of full-time associates for each company separately.
Each company has the ability to use an outside vendor, which entails a higher wage rate. The benefit of the outside vendor is that you are able to adjust hours easier, since full-time associates require 40 hours each week.
The functions below work like a charm for 1 data set, but I am unable to figure out how to loop through 3 different data sets which produces 3 different Minimized Total Costs and 3 different Optimal full-time associates for each Company. The minimal total cost for Company A, B, & C are $9,000, $8,100, and $13,200, respectively. The Optimal number of associates for Company A, B, and C are 2.92, 2.50, and 3.74.
The last part of the code shows listed the desired output. The name of the tibble is called desired_final_tbl.
# 1.0 LIBRARIES ----
# Solver Backend
library(ROI)
library(ROI.plugin.alabama)
# Core
library(tidyverse)
#1.1 Create tibble data set ----
# Company column - 3 separate companies trying to optimize number of Full Time Associates they should hire
# Week - number of weeks we are analyzing
# Full_Time_Associate_Wage_Rate - wage rate for a full time associate that is guarateed 40 hours
# Outside Vendor Wage Rate - wage rate if we decided to hire help from a third party.
# Cleaning Hours - number of cleaning hours needed for each of the days
data_tbl <- tibble(Company = rep(c("CompanyA", "CompanyB", "CompanyC"), times = c(5,5,5)),
Week = rep(1:5, length.out=15),
Full_Time_Associate_Wage_Rate = rep(c(12, 11, 12), times = c(5,5,5)),
Outside_Vendor_Wage_Rate = rep(c(15, 13, 15), times = c(5,5,5)),
Cleaning_Hours = c(100, 120, 140, 160, 180, 100, 120, 140, 160, 180, 140, 160, 200, 240, 280))
data_tbl
# 2.0 FUNCTIONS EO ----
calc_FT_Associates <- function(Optimal_Full_Time_Associates) {
data_tbl %>%
filter(Company == "CompanyA") %>%
select(Company, Week, Full_Time_Associate_Wage_Rate, Outside_Vendor_Wage_Rate, Cleaning_Hours) %>%
# Calculate FT Associate Hours
mutate(FT_Associate_Hours = Optimal_Full_Time_Associates * 40) %>%
# Calculate Number of Hours the Outside Vendor has to fill
mutate(Outside_Vendor_Hours = case_when(Cleaning_Hours <= FT_Associate_Hours ~ 0,
TRUE ~ Cleaning_Hours - FT_Associate_Hours)) %>%
# Calculate Cost of FT Associates
mutate(FT_Associate_Cost = FT_Associate_Hours*Full_Time_Associate_Wage_Rate) %>%
# Calculate Cost of Outside Vendor
mutate(Outside_Vendor_Cost = Outside_Vendor_Hours*Outside_Vendor_Wage_Rate) %>%
# Calculate Total Cost
mutate(Total_Cost = FT_Associate_Cost + Outside_Vendor_Cost) %>%
# Summarise Total Cost
summarise(Total_Cost_sum = sum(Total_Cost)) %>%
# Pull summarization into a vector so that it will be able to get passed in below
pull(Total_Cost_sum)
}
# Test function for Company A only
calc_FT_Associates(2.92)
# 3.0 OBJECTIVE EO ----
n <- 1
single_data_set_optimization <- function(data = data) {
hrs_model_nlp <- OP(
objective = F_objective(F = calc_FT_Associates, n = n, names = "Opt_Associates"),
constraints = rbind(
F_constraint(F = calc_FT_Associates, dir = ">=", rhs = 0)
),
maximum = FALSE
)
sol <- ROI_solve(hrs_model_nlp, solver = "alabama", start = rep(1/n, n))
return(
bind_cols(
tibble(Total_Cost = calc_FT_Associates(sol$solution)),
enframe(sol$solution) %>% spread(key = name, value = value))
)
}
single_data_set_optimization(Company_A)
# I need the code above to loop through each data set, find the optimal associates for each company and calculate the minimal Total Cost.
# The tibble below is the desired final result
desired_final_tbl <- tibble(Company = c("CompanyA", "CompanyB", "CompanyC"),
Total_Cost = c(9000, 8100, 13200),
Opt_Associates = c(2.92, 2.5, 3.74))
desired_final_tbl
Desired Output Image: desired output