Search code examples
rconstraintsboundsnonlinear-optimization

Nonlinear bounded optimization in R


I am trying to run a nonlinear optimization with bounded constraints in R. I have got to know NlcOptim & roptim can be used to optimize a nonlinear objective function, and I have gone through examples [https://cran.r-project.org/web/packages/NlcOptim/NlcOptim.pdf] like one (ex1) as I have mentioned below;

require(NlcOptim)
require(MASS)
objfun=function(x){
  return(exp(x[1]*x[2]*x[3]*x[4]*x[5]))
}
#constraint function
confun=function(x){
  f=NULL
  f=rbind(f,x[1]^2+x[2]^2+x[3]^2+x[4]^2+x[5]^2-10)
  f=rbind(f,x[2]*x[3]-5*x[4]*x[5])
  f=rbind(f,x[1]^3+x[2]^3+1)
  #return(list(ceq=f,c=NULL))
  return(list(ceq=f,c=NULL))
}
x0=c(-2,2,2,-1,-1)
solnl(x0,objfun=objfun,confun=confun)

Understanding: x used in both objfun & confun, is a vector containing x(i), i=1(1)5 x0 is the starting values (In this case, I am bit confused as we are not defining here the bounds of x1,..,x5, rather only the initial values)

I have tried to replicate this example for my actual problem, the objective function I framed is as below;

Maximize P= (x*y*z)-(cost1 + cost2 + cost3 + cost4 + cost5 + cost6) 
where
cost1 = 5000
cost2 = (0.23*cost1) + (0.67*x*y) 
cost3 = 0.2* cost1+ (0.138*x*y)
cost4 = 0.62*cost1
cost5 = 0.12* cost1
cost6 = 0.354*x
Boundaries for the variables are as follow;
200<=x=>350
17<=y=>60
964<=z=>3000

Having this problem in hand, I tried to formulate this as code;

x <- runif(2037,200,350)
y <- runif(2037,17,60)
z <- seq(964,3000,1)  # z is having highest length of 2037. But not sure if this the way to define bounds!!
data_comb <- cbind(x,y,z)
mat <- as.matrix(data_comb)

cost1 <- 5000
cost2 <- (0.23*cost1) + (0.67* mat[,1])* (mat[,2]) 
cost3 <- 0.2* cost1+ (0.138* mat[,1])* (mat[,2])
cost4 <- rep(0.62*cost1, dim(mat)[1])
cost5 <- rep(0.12* cost1, dim(mat)[1])
cost6 <- 0.354* mat[,1]
#Objective function
objfun <- function(mat){
  return((mat[,1]*mat[,2]*mat[,3]) - (cost1 + cost2 + cost3 + cost4 + cost5 + cost6))
}
#Constraints
confun=function(mat){
  f=NULL
  f=rbind(f,(0.23*cos1) + (0.67*mat[,1])* (mat[,2]))
  f=rbind(f,(0.2*cost1) + (0.138*mat[,1])*(mat[,2]))
  f=rbind(f,0.354*mat[,1])
  return(list(ceq=f,c=NULL))
}
x0 <- c(200,17,964)
solnl(x0,objfun=objfun,confun=confun)

This is giving me an error

Error in mat[, 2] : subscript out of bounds

I am having a feel somehow I am not replicating the example properly for my problem, but at the same time not able to understand what I am missing. I don’t know if I have defined the bounds properly or how to include multivariate bounds in the function. Please help me in solving this optimization problem.

TIA


Solution

  • There are no nonlinear constraints, only box constraints, therefore no reason to apply a specialized package or function.

    obj <- function(v) {
        x <- v[1]; y <- v[2]; z <- v[3]
        cost1 <- 5000
        cost2 <- (0.23*cost1) + (0.67*x*y) 
        cost3 <- 0.2* cost1+ (0.138*x*y)
        cost4 <- 0.62*cost1
        cost5 <- 0.12* cost1
        cost6 <- 0.354*x
        w <- (x*y*z) - (cost1 + cost2 + cost3 + cost4 + cost5 + cost6)
        return(-w)
    }
    
    o <- optim(c(200,17,964), obj, method = "L-BFGS-B",
               lower = c(200,17,964), upper = c(350,60,3000))
    
    o$par; -o$value
    ## [1]  350   60 3000
    ## [1] 62972058
    

    For using NlcOptim:solnl() you can define the box constraints with the lb and ub option arguments, just the same as above.

    NlcOptim::solnl(c(200,17,964), obj,
                    lb = c(200,17,964), ub = c(350,60,3000))
    

    with the same result, showing that your function does not have a real, inner maximum. Or you can integrate the bounds into the constraint function