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.

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)
}

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