Minimize a function with two variables

I would like to keep a function with two variables to a minimum.

I first created a function (rba)

that is needed inside a function (kvasum)

that I need to keep to a minimum. The minimized values ​​are part of rba

.

# Data
vpk = data.frame(V1 =c(3650000000, 19233, 2211.2, 479.47, 168.46, 83.447, 52.349, 38.738,
                     32.34, 29.588), V2 = 1:10)
n = nrow(vpk)

# functions to minimize 

# This function returns a vector with 10 values

rba = function(par){
  v <- matrix(ncol = 1, nrow = 10)
  for (p in 1:10){
    k<- ifelse (par[1] < 1-1/p && par[1]>0 && p > par[2] && 
par[2]>0 && par[2]<2, par[2]*p,
                    ifelse(par[1] < 1-1/par[2] && par[1] > 0 && 
p < par[2] && par[2]>0 && par[2]<2, -1+(par[1]+1/par[2]),
                           ifelse(par[1] > (1 - 1 / max(p,par[2])) && 
par[2]>0 && par[2]<2, -1+p, "error")))
    v[p] <- k 
  }
  return(v)
}

# This function uses the function rba, and returns a value

kvasum = function(par){
  sum( (log(vpk$V1)/log(1/n) - rba(par) )^2)
}

# what I would I to do is to find par[1] and par[2] such that kvasum is minimized

m1 = optim(par=c(0.1,0.4),kvasum, lower=0)

      

I tried to use the optim function, but I cannot get it to work. I am getting a non-numeric argument and trying everything I can think of. Any help is appreciated.

+3


source to share


1 answer


There are several issues with your overall process that are causing problems.

First of all, as @ user227710 mentions in the comments, you should replace &&

with &

. They have different meanings.

Now for the optimizer

It sounds like you want to set limits on your parameters (i.e. what is known as in-box constraints). To do this, and thus use an argument lower

, you need to use the method L-BFGS-B

. When you use this, you need to provide an argument as well upper

.

Received error, you get it because your operator ifelse

only works when values ​​are between 0 and 1 roughly. Otherwise the variable k gets a value error

(this value is returned if all conditions in the statements are ifelse

FALSE), so you get

Error in log(vpk$V1)/log(1/n) - rba(par) : 
  non-numeric argument to binary operator

      



mistake.

So if you set your window limits appropriately (or maybe take a look at your ifelse statement, because you may have coded it wrong), this seems to work fine:

# Data
vpk = data.frame(V1 =c(3650000000, 19233, 2211.2, 479.47, 168.46, 83.447, 52.349, 38.738,
                       32.34, 29.588), V2 = 1:10)
n = nrow(vpk)

# functions to minimize 

# This function returns a vector with 10 values

rba = function(par){
  v <- matrix(ncol = 1, nrow = 10)
  for (p in 1:10){
    k<- ifelse (par[1] < 1-1/p & par[1]>0 & p > par[2] & 
                  par[2]>0 & par[2]<2, par[2]*p,
                ifelse(par[1] < 1-1/par[2] & par[1] > 0 & 
                         p < par[2] & par[2]>0 & par[2]<2, -1+(par[1]+1/par[2]),
                       ifelse(par[1] > (1 - 1 / max(p,par[2])) & 
                                par[2]>0 & par[2]<2, -1+p, "error")))
    #I am adding a line here so that you know why the optim failed
    if(k=='error') stop('your ifelse function returned an error')
    v[p] <- k 
  }
  return(v)
}

# This function uses the function rba, and returns a value

kvasum = function(par){
  sum( (log(vpk$V1)/log(1/n) - rba(par) )^2)
}

# what I would I to do is to find par[1] and par[2] such that kvasum is minimized

m1 = optim(par=c(0.1,0.4),kvasum, method='L-BFGS-B', lower= c(0.1,0.1), upper=c(0.9,0.9))

      

Output:

> m1
$par
[1] 0.1 0.1

$value
[1] 171.5774

$counts
function gradient 
       2        2 

$convergence
[1] 0

$message
[1] "CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL"

      

+5


source







All Articles