Live data from Hacker News

Vitter's reservoir sampling algorithm D: randomly selecting unique items

getkerf.wordpress.com

71–80 of 83 posts

Re: Vitter's reservoir sampling algorithm D: randomly selecting unique items

#71
post #65

Earlier quoted context omitted.

This is very practical, but the result is not uniform; in fact it only returns a tiny fraction of the possible combinations. There are "N choose k" combinations, which in the worst case (k = N/2) grows as ~ 2^N. The number of combinations quickly outstrips the number of possible states of the LCG, and most combinations will never be found. For example, we have a list of length 16 and wish to choose 8. We have a choic…

Good point. You would get different sequences by choosing different constants for the generator though, but you couldn't cover all of them by a longshot.

And this inability to cover all possible sequences has real-world implications.

https://www.cigital.com/papers/download/developer_gambling.p...

http://superuser.com/questions/712551/how-are-pseudorandom-a...

Re: Vitter's reservoir sampling algorithm D: randomly selecting unique items

#74
post #19

Huh, is it really true that Reservoir Sampling is not well-known? It was part of the standard curriculum in my top-30-but-not-top-10 CS school, the University of Utah. I think that even a significant subset of my cohort could explain the correspondence between this and the Fisher-Yates shuffling algorithm.

I don't even have a CS degree and I know about it. I wrote some PowerShell (don't ask) to sample a large collection of documents from file shares looking for embedded links to other documents. We needed to break up the existing file share into smaller pieces and wanted to estimate how many documents would have to be touched due to broken links. (The surprising answer was "very few", since most links were relative to the containing directory).

Re: Vitter's reservoir sampling algorithm D: randomly selecting unique items

#75

Why cannot you just create random numbers and discard duplicates? For practical purposes when list.length << total.lenght shouldn't that be good enough?

I had the same thought. However thinking about it more, the requirement is that this algorithm is O(k). As k gets closer and closer to the size of the list, you will spend more and more time looking for unique items. You also need to pay the costs of checking for uniqueness which also grows with k.

You store the selected items in a hashtable or similar data structure with O(1) behavior of "x in y".

Re: Vitter's reservoir sampling algorithm D: randomly selecting unique items

#76

Again, I am confused. Why doesn't this snippet solve the problem? void increasingRandomSequence(arrayptr, base, k, n) { if (k == 0) return; int i = randInt(n - k); *(arrayptr) = base + i; increasingRandomSequence(arrayptr + 1, base + i + 1, k - 1, n - (i + 1)); } increasingRandomSequence(hand, 0, k, n) fills the array hand with a sequence which is picked with uniform distribution over all increasing sequences of leng…

You guys are right, it's uniform in the first digit of the sequence which is actually not uniform at all... Thanks for pointing it out!

Re: Vitter's reservoir sampling algorithm D: randomly selecting unique items

#77
post #6

IMO the Wikipedia article on this is better than this article: https://en.wikipedia.org/wiki/Reservoir_sampling

I only see an O(n) algorithm there, there is no O(k). Am I missing something?

Wiki shows Algorithm R, this article talks about Algorithm D, both by the same author.

The former is well known, while the latter is more obscure. This is probably because the extra complexity of Algorithm D is rarely necessary. If k and n are on the same order of magnitude, there is not much difference, and if k << n then simple random sampling would work nearly as well.

Re: Vitter's reservoir sampling algorithm D: randomly selecting unique items

#78

This may be a stupid question, but what exactly is wrong with (using the dealing random cards analogy): for i = 1 to k pickedCardIndex = randomInt(n - i) hand[i - 1] = deck[pickedCardIndex] swap(deck[pickedCardIndex], deck[n - i]) As far as I can see this satisfies all conditions stated by the author (assuming that randomInt(x) produces a uniformly random integer in the range [0, x], there are n cards in the deck arr…

How do you implement swap if deck is too large to hold in memory?

mmap the deck

Re: Vitter's reservoir sampling algorithm D: randomly selecting unique items

#79

The C code in this article is a mirror of the code from Appendix 2 in Vitter's paper, which I guess explains/excuses the abbreviated variable names. The paper says things like, "use an exponentially distributed random variate Y," and uses variable names like n, N, U, S, X, y1, and y2 in the appendix. Nonetheless, I find this coding style unreadable. "Y" is not a very good name for an exponentially distributed random…

var naming aside, the whitespacing is perplexing: U = random_double(); negSreal=-S; y1=exp(log(U*Nreal/qu1real)*nmin1inv); Vprime = y1 * (-X/Nreal+1.0)*(qu1real/(negSreal+qu1real)); if(Vprime S){bottom=-nreal+Nreal;limit=-S+N;} else{bottom=-1.0+negSreal+Nreal; limit=qu1;} Sometimes two statements per line, sometimes one. Sometimes spaces before and after equals, sometimes none. Sometimes multiple ifs, breaks and stat…

I feel like 2 seconds in an ide would have saved readability quite a bit. A simple automated cleanup would have helped worlds.

Re: Vitter's reservoir sampling algorithm D: randomly selecting unique items

#80
post #30
post #26

Earlier quoted context omitted.

Your solution requires space to hold all items from the pool

I believe it would be easy to modify it to have only k chosen indexes in memory, and for k significantly smaller than n and n an order of 2 to 64 it would still be much faster than iterating through all n (which is the first algorithm presented here: https://en.wikipedia.org/wiki/Reservoir_sampling )

[deleted]
Post reply on HN