Search code examples
roptimizationminimization

minimize a multivariate function in R with constraints


I am trying to minimize a function, S.residuum , in R with some constraints

S.residuum<- function(w, stdv, corr) {
  intermed<-0
  for (i in 1:length(stdvv)) {
  intermed =intermed+residuum(w,stdvv,corr.mat,i)
  }
  return(intermed)
}  

where w is a vector with the length 6. The constraints look as follows:

0.03 <= w1 <= 0.27
0.03 <= w2 <= 0.27
0.20 <= w3 <= 0.91 
0.01 <= w4 <= 0.1
0.01 <= w5 <= 0.1
0.01 <= w6 <= 0.1

So far I was able to implement it:

nlminb(c(1,1,1,1,1,1),S.residuum,hessian = NULL,
       lower=c(0.03,0.03,0.2,0.01,0.01), upper=c(0.27,0.27,0.91,0.1,0.1)),

where c(1,1,1,1,1,1) are the initial values.

However, I have 2 other constraints. I wrote the first one as a functions:

nequal <- function(w,stdv, corr) {
  intermed<-0
  for (j in 1:length(stdvv)) {
    for (i in 1:length(stdvv)) {
      intermed =intermed+ w[[i]] * w[[j]] * stdv[[i]] * stdv[[j]] * corr[[i]][[j]]
    }
  }
  intermed=sqrt(intermed)
},

where stdv is a vector and corr is a matrix. The following constraints should be fulfilled:

 1) nequal <=0.75
 2) w1+w2+w3+w4+w5+w6=1

can someone say to me how can I do it in R? Thanks!


Solution

  • You can use the function solnp in the package Rsolnp. The code looks like this:

    library(Rsolnp)
    
    # Inequality constraint
    nequal <- function(w) {
     intermed <- 0
     for (j in 1:length(stdvv)) {
      for (i in 1:length(stdvv)) {
      intermed = intermed + w[[i]] * w[[j]] * stdvv[[i]] * stdvv[[j]] * corr.mat[[i]][[j]]
      }
     }
      sqrt(intermed)
    }
    
    # Equality constraint
    equal <- function(w) {
      w[[1]]+w[[2]]+w[[3]]+w[[4]]+w[[5]]+w[[6]]
    }
    
    # Minimization with constraints
    min <- solnp(c(0., 0., 0., 0., 0., 0.),
              S.residuum, 
              eqfun = equal,
              eqB = 1,
              ineqfun = nequal,
              ineqLB = 0,
              ineqUB = 0.075,
              LB = c(0.03, 0.03, 0.2, 0.01, 0.01, 0.01),
              UB = c(0.27, 0.27, 0.91, 0.1, 0.1, 0.1))