I was looking at the metropolis sampler, and there's a bit in GetLazyValues() I don't quite get. Here's the snippet
- Code: Select all
// If the node has not yet been initialized, do it now
// otherwise get the last known value from the sample image
if (time == -1) {
const u_int roffs = data->rngOffset * static_cast<u_int>(stampLimit);
for (u_int i = offset; i < offset + size; ++i)
data->sampleImage[i] = rngGet2(i, roffs);
time = 0;
}
for (u_int i = offset; i < offset + size; ++i)
data->currentImage[i] = data->sampleImage[i];
currentTime = time;
}
// Mutate as needed
for (; currentTime < stampLimit; ++currentTime) {
const u_int roffs = data->rngOffset * static_cast<u_int>(stampLimit - currentTime + 1);
for (u_int i = offset; i < offset + size; ++i)
data->currentImage[i] = mutate(data->currentImage[i], rngGet2(i, roffs));
}
Now, the way I understand this is that time = -1 if the last value was from a large mutation, and then we mutate the value for the number of small mutations that we "missed" by not calling GetLazyValues for that value. What I don't get is the computation of "roffs" in the two blocks here.
Imagine the situation where time = -1 and stampLimit = 4. Then in the first block we compute roffs using stampLimit, which if of course 4. Then while "mutating up" the value we start by calculating roffs using stampLimit - currentTime + 1 = 4 - 0 + 1 = 5, then 4, etc down to 2.
This means that we use the same roffs value twice?
Also, why do we use stampLimit to initialize the value?
I don't have a solid grasp over this new QMC stuff in metropolis at all, it just raised a red flag: is it supposed to be like this?
An additional questions:
- Why do we use a non-zero offset to initialize the value in GetLazyValues if a small mutation has occurred after the large one?
- Why don't we use an offset when mutating "normal" values in GetNextSample?
edit: if these are dumb questions feel free to let me know, as I haven't had the time to study the paper you based this on.
