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 _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._