f_make_constraint_function <- function(constraint_values, tag_outcomes){
# constraint_values <- constval$val_std
# tag_outcomes <- c('energy', 'ghge')
# this is the function we want to return
f_constr <- function (x) {
energy <- constraint_values$energy
protein <- constraint_values$protein
# a few computed constraints, where x is the new diet
# it should be the complete set of constrants,
# as we select in the last step from
energy_output_lwr <- - sum(x * energy$unit_contrib) + energy$lwr
energy_output_upr <- sum(x * energy$unit_contrib) - energy$upr
protein_output_lwr <- - sum(x * protein$unit_contrib) + protein$lwr
protein_output_upr <- sum(x * protein$unit_contrib) - protein$upr
# collect in a named vector
constr_all <- c(
energy_lwr = energy_output_lwr,
energy_upr = energy_output_upr,
protein_lwr = protein_output_lwr,
protein_upr = protein_output_upr
)
# key step:
# select the ones that we want, for example, tag1
# need to watch out for the names
tags_lwr <- paste0(tag_outcomes, '_lwr')
tags_upr <- paste0(tag_outcomes, '_upr')
constr <- constr_all[c(tags_lwr, tags_upr)]
# res <- list(constr = constr,
# tags_lwr = tags_lwr,
# tags_upr = tags_upr)
return (constr)
}
# possibly better to also return the input
return(f_constr)
}Flexible input with function factory
When we want to make systematic production of constraints for the optimization, it is important to use functions. Given the special requirement as input when the constraint function enters the algorithm, where the argument is x and output is a scalar value, we need to treat this function as an object produced by our function factory - so that we can tweak the elements outside the function itself.
The basic structure looks like this.
When calling function, can do this
# in this setting, the input data must have the columns required by the ff
f_ineq <- f_make_constraint_function(
constraint_values = constraint_val, # list of constraints
tag_outcomes = tag_outcomes)An example of a function factory
f_out <- function(x, constant){
f <- function(y){
res <- y ^ x + constant
return(res)
}
return(f)
}# it creates a function that at its core, the inner function
# create a function that raise to the power of 2
# 3^2 + 1
f_out1 <- f_out(x = 2, constant = 1)
f_out1(y=3)[1] 10
# create a function that raise to the power of 1
# 3^1 + 1
f_out2 <- f_out(x=1, constant = 1)
f_out2(y=3)[1] 4