Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing arguments in nonlinear optimization function `nloptr`

My initial question can be found here:Optimization in R with arbitrary constraints

It led to another question how to pass arguments into nloptr.
I need to minimize a function F(x,y,A) where x and y are vectors and A is a matrix, while having constrains that sum(x * y) >= sum(y/3) and sum(x)=1. I have tried to use nloptr:

F <- function(x,y,A){
   ...
}

Gc <- function(x,y){
  return(sum(y/3) - sum(x*y))
} 

Hc <- function(x){
  retunr(1-sum(x))
}

nloptr(x0=rep(1/3,3), eval_f=F, lb = 0.05, ub = 1, eval_g_ineq = Gc, eval_g_eq = Hc, opts = list(), y=y, A=A)

And I receive an error: 'A' passed to (...) in 'nloptr' but this is not required in the eval_g_ineq function.

If I say nloptr( ... , y, A)

I get:eval_f requires argument 'cov.mat' but this has not been passed to the 'nloptr' function.

Any advice would be great. Thanks

like image 797
mm441 Avatar asked Feb 07 '14 16:02

mm441


1 Answers

So there are several things going on here:

First, the objective function, F, the equality constraint function, Hc, and the inequality constraint function, Gc, all have to take the same arguments. So pass x, y, A to all three and just ignore them where they are not needed.

Second, you have to define y and A somewhere...

Third, you must specify which algorithm to use. Do this with opts=list(algoritm=...). It turns out that if you are (a) using constraints, and (b) not providing functions to calculate the jacobian matrices, then only some of the algorithms are appropriate. In your case opts=list(algorithm="NLOPT_GN_ISRES") seems to work.

Finally, the default maxeval = 100 which turns out to be not nearly enough. I had to set it to 100,000 to get convergence.

Putting this all together, albeit with a made-up objective function:

F <- function(x,y,A){  # made-up function
  # minimize scaled distance between points x and y
  sum((A[1]*x-A[2]*y)^2)
}
Gc <- function(x,y,A) return(sum(y/3) - sum(x*y))
Hc <- function(x,y,A) return(1-sum(x))

library(nloptr)
y= c(0,1,0)
A= c(10,1)
opt <- nloptr(x0=rep(1/3,3), eval_f=F, lb = rep(0.05,3), ub = rep(1,3), 
              eval_g_ineq = Gc, eval_g_eq = Hc, 
              opts = list(algorithm="NLOPT_GN_ISRES",maxeval=100000), y=y, A=A)
opt$solution
# [1] 0.2990463 0.4004237 0.3005300
like image 108
jlhoward Avatar answered Oct 15 '22 15:10

jlhoward