From @oko| @end|ng |rom |n@@-tou|ou@e@|r  Fri May  3 10:41:36 2019
From: @oko| @end|ng |rom |n@@-tou|ou@e@|r (Serguei Sokol)
Date: Fri, 3 May 2019 10:41:36 +0200
Subject: [Rd] 
 R optim(method="L-BFGS-B"): unexpected behavior when working
 with parent environments
In-Reply-To: <0346dccc-9d93-0d74-9c20-1825c67cd900@insa-toulouse.fr>
References: <45fd1e7c-fffa-11b1-3a62-08d086fcbd78@gmail.com>
 <0346dccc-9d93-0d74-9c20-1825c67cd900@insa-toulouse.fr>
Message-ID: <ddb7d325-67a3-ed65-11cd-014895d1a454@insa-toulouse.fr>

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.



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