I have example machine data:
set.seed(0)
n <- 10
machine_data <- data.frame(c(1:n), sample.int(2, n, replace=TRUE), runif(n, min=50, max=100), runif(n, min=20000, max=100000))
colnames(machine_data) <- c("ID", "Location", "Condition", "ReplaceCost")
I also have a list of potential actions to perform maintenance on the equipment of a particular location:
actions <- c("do_nothing", "repair", "replace")
periods <- 3
perms <- gtools::permutations(n=length(actions), r=periods, v=actions, repeats.allowed = T)
n <- length(unique((machine_data$Location)))
decisions <- do.call(rbind, replicate(n, perms, simplify=FALSE))
df <- data.frame(rep(c(1:n), each=nrow(perms)), decisions)
action_labels <- paste("Period", c(1:periods))
colnames(df) <- c("Location", action_labels)
df$Improvement <- 0
df$Cost <- 0
I also have a model that predicts machine condition:
# for simplicity assume it degrades 10% each period
degrade_machine <- function(currentCondition)
{
newCondition <- currentCondition * 0.90
return(newCondition)
}
The idea is to calculate the $Improvement
and $Cost
of each action set. An action set is defined as the permutation of potential actions across all periods. E.g., "do_nothing," "repair," and "do_nothing" is one action set across the three periods.
I have a function to perform a single period action and give the resulting condition:
perform_action <- function(action, machine_data, location_id, repair_threshold, replace_threshold)
{
print(action)
location_data <- machine_data[machine_data$Location == location_id, ]
# repair decisions and resulting cis
location_data <- location_data %>%
# repair results in condition of 95; replace results in 100
mutate(Condition = ifelse(action == "repair" & Condition <= repair_threshold, 95,
ifelse(action == "replace" & Condition <= replace_threshold, 100, Condition))
)
machine_data[machine_data$Location == location_id,]$Condition <- location_data$Condition
# degrade machine for next iteration
# print the condition after maintenance decision
print(machine_data$Condition)
machine_data$Condition <- degrade_machine(machine_data$Condition)
# print the condition after components degrade
print(machine_data$Condition)
return(machine_data)
}
A previous question helped me set this up using the purrr
library (Avoiding Loops in R for Accumulating Function Values):
for(i in 1:nrow(df))
{
action_set <- df[i, 2:4]
machine_data <- purrr::reduce(action_set %>% as_vector(),
function(x,y) {
x <- perform_action(y, machine_data, 1,
repair_threshold, replace_threshold)
return(x)
}, .init = 0)
}
However, this creates a problem: each recursive call in the above loop starts with the original machine_data
values.
For example, suppose I have the action set c('repair', 'do_nothing', 'repair)
. Machine 2 starts with a $Condition
of ~ 60.299. We can see that the second component gets repaired to 95 and then degrades to 85.5 after the first decision to repair. The intent is that the second action (do_nothing
) would be passed the updated condition of 85.5, but we see it starts with the original condition value of 60.299 and then degrades to 54.27. I would expect it to instead have a resulting $Condition = 0.9 * 85.5 = 76.95
Starting data:
Data after a repair
and do_nothing
decision:
I would like this data to be passed as a reference within the reduce()
function. Is that possible?