I have a function that makes use of the ode() function from the "deSolve" package. I am trying to find a way of getting it to put out a "progress report" every "t.int" time units (by "progress report" I just mean reporting what time it's got up to). I thought to put code something like the following in my "func" function that gets called by (is an argument to) ode():> cat("Before: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n") > if(tt - tdone >= 0.1-sqrt(.Machine$double.eps)) { > cat("Prog. Rep.: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n") > assign("tdone",tt,envir=parent.env(environment())) > } > cat("After: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n")The object "tdone" gets initialized (to 0) outside of func(), so there is not a problem with "tdone" not being found the first time that func() gets called by ode(). (I'm hardwiring "t.int=0.1" in the forgoing just for test/illustration purposes.) The "Before" and "After" cat()-s are there to demonstrate what goes wrong. What goes wrong is that I get no progress report and tdone remains equal to 0 until tt reaches 0.1. As desired. I then get a progress report and tdone gets set equal to the first value of tt which is greater than 0.1. As desired. Then I get no further progress reports and tdone gets set equal to tt at every call to func() --- even though tt - tdone = 0 which is less than 0.1 so the assignment of tdone cannot occur. And yet it does, keeping the difference equal to 0. (*Not* as desired!) So the function is recognizing that the difference is less than 0.1 in that it does not execute the cat() statement. Yet it executes the assign() statement. This is clearly impossible! :-) But it happens. The output from the cat()-ing, around time = 0.1, looks like:> Before: time = 0.09364548 tdone = 0 diff = 0.09364548 > After: time = 0.09364548 tdone = 0 diff = 0.09364548 > Before: time = 0.0975779 tdone = 0 diff = 0.0975779 > After: time = 0.0975779 tdone = 0 diff = 0.0975779 > Before: time = 0.0975779 tdone = 0 diff = 0.0975779 > After: time = 0.0975779 tdone = 0 diff = 0.0975779 > Before: time = 0.09698997 tdone = 0 diff = 0.09698997 > After: time = 0.09698997 tdone = 0 diff = 0.09698997 > Before: time = 0.1009224 tdone = 0 diff = 0.1009224 > Prog. Rep.: time = 0.1009224 tdone = 0 diff = 0.1009224 > After: time = 0.1009224 tdone = 0.1009224 diff = 0 > Before: time = 0.1009224 tdone = 0.1009224 diff = 0 > After: time = 0.1009224 tdone = 0.1009224 diff = 0 > Before: time = 0.1003344 tdone = 0.1003344 diff = 0 <--------------| > After: time = 0.1003344 tdone = 0.1003344 diff = 0 > Before: time = 0.1042669 tdone = 0.1042669 diff = 0 > After: time = 0.1042669 tdone = 0.1042669 diff = 0It's at that line indicated by "<----|", 4 lines from the bottom of the forgoing display, where things go to hell in a handcart. Why (how on earth can) tdone change from 0.1009224 to 0.1003344, given that the difference is 0 whence no assignment of tdone should take place? What am I not seeing? Can anyone help me out? I'm going mad! ***MAD*** I tell you! :-) Suggestions as to a better way of accomplishing my desired goal of producing progress reports would also be welcome. I am not at all sure that assigning "tdone" in parent.env(environment()) is the right thing to do. I need to assign it in such a way and in such a location that its value will persist from call to call of "func". Words of wisdom about this would be gratefully received. (I don't really grok environments. I just try things until *something* works!) cheers, Rolf Turner
On Tue, 25 Feb 2014, Rolf Turner <r.turner at auckland.ac.nz> writes:> I have a function that makes use of the ode() function from the > "deSolve" package. I am trying to find a way of getting it to put out > a "progress report" every "t.int" time units (by "progress report" I > just mean reporting what time it's got up to). > > I thought to put code something like the following in my "func" > function that gets called by (is an argument to) ode(): > >> cat("Before: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n") >> if(tt - tdone >= 0.1-sqrt(.Machine$double.eps)) { >> cat("Prog. Rep.: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n") >> assign("tdone",tt,envir=parent.env(environment())) >> } >> cat("After: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n") > > The object "tdone" gets initialized (to 0) outside of func(), so there > is not a problem with "tdone" not being found the first time that > func() gets called by ode(). (I'm hardwiring "t.int=0.1" in the > forgoing just for test/illustration purposes.) The "Before" and > "After" cat()-s are there to demonstrate what goes wrong. > > What goes wrong is that I get no progress report and tdone remains > equal to 0 until tt reaches 0.1. As desired. I then get a progress > report and tdone gets set equal to the first value of tt which is > greater than 0.1. As desired. > > Then I get no further progress reports and tdone gets set equal to tt > at every call to func() --- even though tt - tdone = 0 which is less > than 0.1 so the assignment of tdone cannot occur. And yet it does, > keeping the difference equal to 0. (*Not* as desired!) > > So the function is recognizing that the difference is less than 0.1 in > that it does not execute the cat() statement. Yet it executes the > assign() statement. This is clearly impossible! :-) But it happens. > > The output from the cat()-ing, around time = 0.1, looks like: > >> Before: time = 0.09364548 tdone = 0 diff = 0.09364548 >> After: time = 0.09364548 tdone = 0 diff = 0.09364548 >> Before: time = 0.0975779 tdone = 0 diff = 0.0975779 >> After: time = 0.0975779 tdone = 0 diff = 0.0975779 >> Before: time = 0.0975779 tdone = 0 diff = 0.0975779 >> After: time = 0.0975779 tdone = 0 diff = 0.0975779 >> Before: time = 0.09698997 tdone = 0 diff = 0.09698997 >> After: time = 0.09698997 tdone = 0 diff = 0.09698997 >> Before: time = 0.1009224 tdone = 0 diff = 0.1009224 >> Prog. Rep.: time = 0.1009224 tdone = 0 diff = 0.1009224 >> After: time = 0.1009224 tdone = 0.1009224 diff = 0 >> Before: time = 0.1009224 tdone = 0.1009224 diff = 0 >> After: time = 0.1009224 tdone = 0.1009224 diff = 0 >> Before: time = 0.1003344 tdone = 0.1003344 diff = 0 <--------------| >> After: time = 0.1003344 tdone = 0.1003344 diff = 0 >> Before: time = 0.1042669 tdone = 0.1042669 diff = 0 >> After: time = 0.1042669 tdone = 0.1042669 diff = 0 > > It's at that line indicated by "<----|", 4 lines from the bottom of > the forgoing display, where things go to hell in a handcart. Why (how > on earth can) tdone change from 0.1009224 to 0.1003344, given that the > difference is 0 whence no assignment of tdone should take place? > > What am I not seeing? Can anyone help me out? I'm going mad! > ***MAD*** I tell you! :-) > > Suggestions as to a better way of accomplishing my desired goal of > producing progress reports would also be welcome. > > I am not at all sure that assigning "tdone" in > parent.env(environment()) is the right thing to do. I need to assign > it in such a way and in such a location that its value will persist > from call to call of "func". Words of wisdom about this would be > gratefully received. (I don't really grok environments. I just try > things until *something* works!) > > cheers, > > Rolf Turner >I did not follow your example, neither do I use the deSolve package; but why not pass an environment as an argument? ## some iterative function that takes another fun as argument outer <- function(fun, ...) { for (i in 1:20) fun(...) } ## create an environment ... info <- new.env() info$tt <- 0 ## ... and pass it as an argument myfun <-function(e) { e$tt <- e$tt + 1 cat("Iteration ", e$tt, "\n") } outer(myfun, info) info$tt -- Enrico Schumann Lucerne, Switzerland http://enricoschumann.net
On 14-02-25 3:08 AM, Rolf Turner wrote:> > I have a function that makes use of the ode() function from the > "deSolve" package. I am trying to find a way of getting it to put out a > "progress report" every "t.int" time units (by "progress report" I just > mean reporting what time it's got up to). > > I thought to put code something like the following in my "func" function > that gets called by (is an argument to) ode(): > >> cat("Before: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n") >> if(tt - tdone >= 0.1-sqrt(.Machine$double.eps)) { >> cat("Prog. Rep.: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n") >> assign("tdone",tt,envir=parent.env(environment())) >> } >> cat("After: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n") > > The object "tdone" gets initialized (to 0) outside of func(), so there > is not a problem with "tdone" not being found the first time that func() > gets called by ode(). (I'm hardwiring "t.int=0.1" in the forgoing just > for test/illustration purposes.) The "Before" and "After" cat()-s are > there to demonstrate what goes wrong. > > What goes wrong is that I get no progress report and tdone remains equal > to 0 until tt reaches 0.1. As desired. I then get a progress report and > tdone gets set equal to the first value of tt which is greater than 0.1. > As desired. > > Then I get no further progress reports and tdone gets set equal to tt at > every call to func() --- even though tt - tdone = 0 which is less than > 0.1 so the assignment of tdone cannot occur. And yet it does, keeping > the difference equal to 0. (*Not* as desired!) > > So the function is recognizing that the difference is less than 0.1 in > that it does not execute the cat() statement. Yet it executes the > assign() statement. This is clearly impossible! :-) But it happens. > > The output from the cat()-ing, around time = 0.1, looks like: > >> Before: time = 0.09364548 tdone = 0 diff = 0.09364548 >> After: time = 0.09364548 tdone = 0 diff = 0.09364548 >> Before: time = 0.0975779 tdone = 0 diff = 0.0975779 >> After: time = 0.0975779 tdone = 0 diff = 0.0975779 >> Before: time = 0.0975779 tdone = 0 diff = 0.0975779 >> After: time = 0.0975779 tdone = 0 diff = 0.0975779 >> Before: time = 0.09698997 tdone = 0 diff = 0.09698997 >> After: time = 0.09698997 tdone = 0 diff = 0.09698997 >> Before: time = 0.1009224 tdone = 0 diff = 0.1009224 >> Prog. Rep.: time = 0.1009224 tdone = 0 diff = 0.1009224 >> After: time = 0.1009224 tdone = 0.1009224 diff = 0 >> Before: time = 0.1009224 tdone = 0.1009224 diff = 0 >> After: time = 0.1009224 tdone = 0.1009224 diff = 0 >> Before: time = 0.1003344 tdone = 0.1003344 diff = 0 <--------------| >> After: time = 0.1003344 tdone = 0.1003344 diff = 0 >> Before: time = 0.1042669 tdone = 0.1042669 diff = 0 >> After: time = 0.1042669 tdone = 0.1042669 diff = 0 > > It's at that line indicated by "<----|", 4 lines from the bottom of the > forgoing display, where things go to hell in a handcart. Why (how on > earth can) tdone change from 0.1009224 to 0.1003344, given that the > difference is 0 whence no assignment of tdone should take place? > > What am I not seeing? Can anyone help me out? I'm going mad! > ***MAD*** I tell you! :-) > > Suggestions as to a better way of accomplishing my desired goal of > producing progress reports would also be welcome. > > I am not at all sure that assigning "tdone" in parent.env(environment()) > is the right thing to do. I need to assign it in such a way and in such > a location that its value will persist > from call to call of "func". Words of wisdom about this would be > gratefully received. (I don't really grok environments. I just try > things until *something* works!)You don't show us everything (we want the full Monty!), so it's hard to say what's going wrong. My guess would be that you have both a local copy as well as a parent copy of some variable, and your test is consulting the wrong one. A better approach to what you are doing (better since yours modifies things in the global environment, and that can be dangerous; other code might modify it too) is the following. Create your func in a local block, and it will have it's own mini-environment associated with it. Put tdone there. For example, func <- local({ # local() creates an environment; that's where tdone will live tdone <- 0 # this function's environment will be the one created by # local(), so it will see tdone, but other code won't see it. function(x) { # the timing stuff tt <- Sys.time() if (tt - tdone > 0.1) { cat("Prog rep...") tdone <<- tt } # now the real stuff ... }) Duncan Murdoch