Skip to content

vectorization & modifying globals in functions

5 messages · Sam Steingold, Neal H. Walfield, Suzen, Mehmet +2 more

#
I have the following code:

--8<---------------cut here---------------start------------->8---
d <- rep(10,10)
for (i in 1:100) {
  a <- sample.int(length(d), size = 2)
  if (d[a[1]] >= 1) {
    d[a[1]] <- d[a[1]] - 1
    d[a[2]] <- d[a[2]] + 1
  }
}
--8<---------------cut here---------------end--------------->8---

it does what I want, i.e., modified vector d 100 times.

Now, if I want to repeat this 1e6 times instead of 1e2 times, I want to
vectorize it for speed, so I do this:

--8<---------------cut here---------------start------------->8---
update <- function (i) {
  a <- sample.int(n.agents, size = 2)
  if (d[a[1]] >= delta) {
    d[a[1]] <- d[a[1]] - 1
    d[a[2]] <- d[a[2]] + 1
  }
  entropy(d, unit="log2")
}
system.time(entropy.history <- sapply(1:1e6,update))
--8<---------------cut here---------------end--------------->8---

however, the global d is not modified, apparently update modifies the
local copy.

so,
1. is there a way for a function to modify a global variable?
2. how would you vectorize this loop?

thanks!
#
At Thu, 27 Dec 2012 15:38:08 -0500,
Sam Steingold wrote:
Use <<- instead of <-.
This is hard.  Your function has a feedback loop: an iteration depends
on the previous iteration's result.  A for loop is about as good as
you can do in this case.  sapply might help a bit, but it is really
just a for loop in disguise.

Since sample.int is used to generate indexes, you might try to
generate a bunch of indexes, take as many as don't overlap (i.e.,
collect all orthogonal updates) and do all of those updates at once.
If you really need the entropy after every iteration, however, then
this won't work for you either.

Neal
#
You can use environments. Have a look at this this discussion.

http://stackoverflow.com/questions/7439110/what-is-the-difference-between-parent-frame-and-parent-env-in-r-how-do-they
On 27 December 2012 21:38, Sam Steingold <sds at gnu.org> wrote:
#
On Dec 27, 2012, at 12:38 PM, Sam Steingold wrote:

            
You could get some modest improvement by "vectorizing" the two  
lookups, additions, and assignments into one:

      d[a] <- d[a]-c(1,-1)

In a test with 100000 iterations, it yields about a  1.693/1.394 -1  =  
21 percent improvement.
The `unit` seems likely to throw an error since there is no argument  
for it to match.
You could have returned 'd' and the entropy result as a list. But what  
would be the point of saving 1e6 copies????
So if you replaced it in the global environment, you would only be  
seeing the result of the last iteration of the loop. What's the use of  
that????