[Rd] R optim(method="L-BFGS-B"): unexpected behavior when working with parent environments

peter dalgaard pd@|gd @end|ng |rom gm@||@com
Fri May 3 13:13:39 CEST 2019


Yes, I think you are right. I was at first confused by the fact that after the optim() call,

> environment(fn)$xx
[1] 10
> environment(fn)$ret
[1] 100.02

so not 9.999, but this could come from x being assigned the final value without calling fn.

-pd


> On 3 May 2019, at 11:58 , Duncan Murdoch <murdoch.duncan using gmail.com> wrote:
> 
> Your results below make it look like a bug in optim():  it is not duplicating a value when it should, so changes to x affect xx as well.
> 
> Duncan Murdoch
> 
> On 03/05/2019 4:41 a.m., Serguei Sokol wrote:
>> On 03/05/2019 10:31, Serguei Sokol wrote:
>>> On 02/05/2019 21:35, Florian Gerber wrote:
>>>> Dear all,
>>>> 
>>>> when using optim() for a function that uses the parent environment, I
>>>> see the following unexpected behavior:
>>>> 
>>>> makeFn <- function(){
>>>>      xx <- ret <- NA
>>>>      fn <- function(x){
>>>>         if(!is.na(xx) && x==xx){
>>>>             cat("x=", xx, ", ret=", ret, " (memory)", fill=TRUE, sep="")
>>>>             return(ret)
>>>>         }
>>>>         xx <<- x; ret <<- sum(x^2)
>>>>         cat("x=", xx, ", ret=", ret, " (calculate)", fill=TRUE, sep="")
>>>>         ret
>>>>      }
>>>>      fn
>>>> }
>>>> fn <- makeFn()
>>>> optim(par=10, fn=fn, method="L-BFGS-B")
>>>> # x=10, ret=100 (calculate)
>>>> # x=10.001, ret=100.02 (calculate)
>>>> # x=9.999, ret=100.02 (memory)
>>>> # $par
>>>> # [1] 10
>>>> #
>>>> # $value
>>>> # [1] 100
>>>> # (...)
>>>> 
>>>> I would expect that optim() does more than 3 function evaluations and
>>>> that the optimization converges to 0.
>>>> 
>>>> Same problem with optim(par=10, fn=fn, method="BFGS").
>>>> 
>>>> Any ideas?
>>> I don't have an answer but may be an insight. For some mysterious
>>> reason xx is getting changed when in should not. Consider:
>>>> fn=local({n=0; xx=ret=NA; function(x) {n <<- n+1; cat(n, "in
>>> x,xx,ret=", x, xx, ret, "\n"); if (!is.na(xx) && x==xx) ret else {xx
>>> <<- x; ret <<- x**2; cat("out x,xx,ret=", x, xx, ret, "\n"); ret}}})
>>>> optim(par=10, fn=fn, method="L-BFGS-B")
>>> 1 in x,xx,ret= 10 NA NA
>>> out x,xx,ret= 10 10 100
>>> 2 in x,xx,ret= 10.001 10 100
>>> out x,xx,ret= 10.001 10.001 100.02
>>> 3 in x,xx,ret= 9.999 9.999 100.02
>>> $par
>>> [1] 10
>>> 
>>> $value
>>> [1] 100
>>> 
>>> $counts
>>> function gradient
>>>        1        1
>>> 
>>> $convergence
>>> [1] 0
>>> 
>>> $message
>>> [1] "CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL"
>>> 
>>> At the third call, xx has value 9.999 while it should have kept the
>>> value 10.001.
>>> 
>> A little follow-up: if you untie the link between xx and x by replacing
>> the expression "xx <<- x" by "xx <<- x+0" it works as expected:
>>  > fn=local({n=0; xx=ret=NA; function(x) {n <<- n+1; cat(n, "in
>> x,xx,ret=", x, xx, ret, "\n"); if (!is.na(xx) && x==xx) ret else {xx <<-
>> x+0; ret <<- x**2; cat("out x,xx,ret=", x, xx, ret, "\n"); ret}}})
>>  > optim(par=10, fn=fn, method="L-BFGS-B")
>> 1 in x,xx,ret= 10 NA NA
>> out x,xx,ret= 10 10 100
>> 2 in x,xx,ret= 10.001 10 100
>> out x,xx,ret= 10.001 10.001 100.02
>> 3 in x,xx,ret= 9.999 10.001 100.02
>> out x,xx,ret= 9.999 9.999 99.98
>> 4 in x,xx,ret= 9 9.999 99.98
>> out x,xx,ret= 9 9 81
>> 5 in x,xx,ret= 9.001 9 81
>> out x,xx,ret= 9.001 9.001 81.018
>> 6 in x,xx,ret= 8.999 9.001 81.018
>> out x,xx,ret= 8.999 8.999 80.982
>> 7 in x,xx,ret= 1.776357e-11 8.999 80.982
>> out x,xx,ret= 1.776357e-11 1.776357e-11 3.155444e-22
>> 8 in x,xx,ret= 0.001 1.776357e-11 3.155444e-22
>> out x,xx,ret= 0.001 0.001 1e-06
>> 9 in x,xx,ret= -0.001 0.001 1e-06
>> out x,xx,ret= -0.001 -0.001 1e-06
>> 10 in x,xx,ret= -1.334475e-23 -0.001 1e-06
>> out x,xx,ret= -1.334475e-23 -1.334475e-23 1.780823e-46
>> 11 in x,xx,ret= 0.001 -1.334475e-23 1.780823e-46
>> out x,xx,ret= 0.001 0.001 1e-06
>> 12 in x,xx,ret= -0.001 0.001 1e-06
>> out x,xx,ret= -0.001 -0.001 1e-06
>> $par
>> [1] -1.334475e-23
>> $value
>> [1] 1.780823e-46
>> $counts
>> function gradient
>>         4        4
>> $convergence
>> [1] 0
>> $message
>> [1] "CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL"
>> Serguei.
>> ______________________________________________
>> R-devel using r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>> 
> 
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

-- 
Peter Dalgaard, Professor,
Center for Statistics, Copenhagen Business School
Solbjerg Plads 3, 2000 Frederiksberg, Denmark
Phone: (+45)38153501
Office: A 4.23
Email: pd.mes using cbs.dk  Priv: PDalgd using gmail.com



More information about the R-devel mailing list