A student asked me about simulation he is doing. This simulation presented an interesting R programming puzzle that we did solve but I am not happy with the solution. I feel there should be a better way of doing this. Briefly, he is simulating births and deaths in a linear array of cells. Births and deaths are required to alternate. For a birth, one of the cells is selected at random to be the parent. The offspring cell is generated according to some rules based on the type of the parent then inserted into the array either to the left or to the right of the parent. The left/right choice is random. The part that took us the longest time was deciding how to insert the offspring cell into the array in a way that doesn't break down at the boundaries. I ended up using code based on an argument 'pos', which is the number of elements from the original array that will be to the left of the new element. Another way of thinking of pos is as one less than the index of the new element in the result. insert <- function(orig = 1:10, new = 0, pos = sample(0:length(orig), 1)) { ## Insert a new element at a random position in a vector. ## The default values of the arguments were for testing and do not ## reflect the process descibed above. if (pos < 1) return(c(new, orig)) left <- 1:pos c(orig[left], new, orig[-left]) } iterate <- function(current) { ## Update the array of cells with a birth followed by a death parent <- sample(seq(along = current), 1) # index of the parent pos <- parent - sample(c(0,1), 1) newcell <- ## generate the new cell based on the type of the parent newvec <- insert(current, newcell, pos) newvec[-sample(seq(along = newvec), 1)] } Can anyone come up with a cleaner way of doing the insertion or perhaps the complete birth/death step? -- Douglas Bates bates at stat.wisc.edu Statistics Department 608/262-2598 University of Wisconsin - Madison http://www.stat.wisc.edu/~bates/ -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
Douglas Bates asks:> The part that took us the longest time was deciding how to insert the > offspring cell into the array in a way that doesn't break down at the > boundaries. > > iterate <- > function(current) > { > ## Update the array of cells with a birth followed by a death > parent <- sample(seq(along = current), 1) # index of the parent > pos <- parent - sample(c(0,1), 1) > newcell <- ## generate the new cell based on the type of the parent > newvec <- insert(current, newcell, pos) > newvec[-sample(seq(along = newvec), 1)] > } > > Can anyone come up with a cleaner way of doing the insertion or > perhaps the complete birth/death step? >Here's a minor modification which avoids the separate function call to insert(). One might say it is a little more elegant, using order to insert the new element, but it does use slightly more CPU time (a few %, but this is dependent on how complex the new cell generation is): iterate <- function(current) { ## Update the array of cells with a birth followed by a death index <- seq(along = current) parent <- sample(index, 1) # index of the parent pos <- parent + sample(c(0.5, -0.5), 1) newcell <- ## generate the new cell based on the type of the parent newvec <- c(current, newcell)[order(c(index, pos))] newvec[-sample(seq(along = newvec), 1)] } Hope this helps, Ray Brownrigg <ray at mcs.vuw.ac.nz> http://www.mcs.vuw.ac.nz/~ray -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._