Reputation: 977
I am trying to build a double optimization in R. By double optimization, I mean that there is going to be an inner call, in which I optimize a function called inner_function()
, and then an outer call, in which I optimize an outer_function()
whose output is computed using the optimization of inner_function()
.
I can make this work when inner_function()
is optimized through optim()
and outer_function()
takes only one argument and is optimized through optimize()
:
constructor_function <- function(data, fixed = c(FALSE, FALSE)) {
params <- fixed
function(p) {
params[!fixed] <- p
a <- data[1]
b <- data[2]
c <- data[3]
d <- data[4]
e <- params[1]
f <- params[2]
## Calculate something
tot <- abs(a + b + c + d + e + f)
return(tot)
}
}
inner_function <- constructor_function(c(1, 2, 3, 4))
inner_function(c(5, 6))
#> [1] 21
optim(c(0, 0), inner_function)$par
#> [1] -3.454274 -6.545726
sum(optim(c(0, 0), inner_function)$par)
#> [1] -10
outer_function <- function(first_factor) {
inner_function <- constructor_function(c(first_factor, 2, 3, 4))
values <- optim(c(0, 0), inner_function)$par
tot <- sum(values)
return(tot)
}
# check
outer_function(1)
#> [1] -10
optimize(outer_function, lower = 0, upper = 4)
#> $minimum
#> [1] 3.99994
#>
#> $objective
#> [1] -12.99994
# check
outer_function(3.99994)
#> [1] -12.99994
But I can't make the double optimization work when the outer function (now called outer_function_args
) takes more than one argument, so that it can be optimized only with optim()
:
outer_function_args <- function(first_factor, second_factor) {
inner_function <- constructor_function(c(first_factor, second_factor, 3, 4))
values <- optim(c(0, 0), inner_function)$par
tot <- sum(values)
return(tot)
}
outer_function_args(1,2)
#> [1] -10
optim(par=c(0,2), outer_function_args)
#> Error in fn(par, ...): argument "second_factor" is missing, with no default
The error mentions that argument "second_factor" is missing
, but outer_function_args
is running correctly.
Created on 2021-04-15 by the reprex package (v0.3.0)
Upvotes: 0
Views: 510
Reputation: 10253
You need to modify your function to take in the parameters as a vector, like so:
outer_function_args <- function(par) {
inner_function <- constructor_function(c(par[1], par[2], 3, 4))
values <- optim(c(0, 0), inner_function)$par
tot <- sum(values)
return(tot)
}
outer_function_args(par = c(1, 2))
#> [1] -10
optim(par=c(0,2), outer_function_args)
#$par
#[1] 3355434 3355445
#
#$value
#[1] -6710886
#
#$counts
#function gradient
# 253 NA
#
#$convergence
#[1] 0
#
#$message
#NULL
From the documentation of optim(par, fn)
in help("optim")
:
fn
A function to be minimized (or maximized), with first argument the vector of parameters over which minimization is to take place. It should return a scalar result.
Upvotes: 1