Sattolo's Algorithm (2017)
danluu.com
danluu.com
That Wikipedia prose is like the lazy author's approach, it's a brain dump and not a real attempt to inform or educate. It is nice that there is Python code in the relevant section on the algorithm, that's informative (and why I like Python, it's executable pseudocode). But it would also be nice to have properly structured proofs to go along with the awful prose section (and either remove it or clean it up).
Also, here's the discussion from when this was first posted: https://news.ycombinator.com/item?id=14967697
Textbooks often format proofs as a sequence paragraphs, but this really obscures the logical structure of the argument. As a student, I found it very helpful to write down proofs as nested lists [1,2] instead.
Admittedly, now that I have more experience, I do like my proofs to be more terse when I'm communicating them just to myself.
[1]: https://benrbray.com/static/notes/separating-hyperplane-thm_... [2]: https://benrbray.com/static/notes/minimax-approx_nov16.pdf
During my studies, I had to assist to a conference by a mathematician explaining some image processing algorithm. It took me half an hour to realize that all that was a good old "make each pixel the weighted average of its surroundings" blur, also known as a convolution filter. And I spent the other half hour completely lost trying to understand what was special about his blur. I think no one actually understood anything, in fact, I probably did better than most because I was familiar with convolution filters from personal experience.
Had he explained it in terms of pixels and loops instead of what was probably (for us) a Greek letter soup, I am sure we would have understood.
> Had he explained it in terms of pixels and loops instead of what was probably (for us) a Greek letter soup, I am sure we would have understood.
Unfortunately concretizing the math to realizations leaves you with a cookbook for implementing the least interesting bits of signal processing. Looking at some matrix multiplication as for loops doesn't teach you how a filter works.
Like just to give an example, I don't think it's possible to come up with an explanation of the Remez Exchange Algorithm in any physically meaningful context since it's fundamentally about recognizing the mathematical properties of a higher order abstraction of the system designed with it. But we can be a bit smarter about how we write, since "an iterative algorithm used to find simple approximations to functions, specifically, approximations by functions in a Chebyshev space that are the best in the uniform norm L∞ sense" is Wikipedia word soup that belies the concepts and connections that make it useful. It's just hard to do it in a sentence and not a semester.
The nlab and wiki2.org are nice for the subjects they cover.
def sattolo(a, key):
n = len(a)
keylength = len(key)
j = 0
for i in range(n - 1):
j = (j + a[i] + key[i % keylength]) % n
a[i], a[j] = a[j], a[i]
(key needs to be a byte string because it's easier that way)--edit--
Doesn't work for producing a singlar path:
>>> x = [0,1,2,3,4,5,6,7,8,9]
>>> sattolo(x, b'zanzibar')
>>> x
[0, 2, 1, 5, 4, 3, 8, 6, 9, 7]There are a lot of variations, but I particularly like the 128 bit version from the original paper [1].
Here is the entire code
unsigned long xor128() {
static unsigned long x=123456789,y=362436069,z=521288629,w=88675123;
unsigned long t;
t=(xˆ(x<<11));x=y;y=z;z=w;
return( w=(wˆ(w>>19))ˆ(tˆ(t>>8)) );
}
Note: Do not use for security applications! It is not cryptographically secure. But if you need that, or if you are running Monte Carlo simulations and want nothing but the best, you probably should use specialized libraries anyways.[1] https://www.jstatsoft.org/index.php/jss/article/view/v008i14...
Edit: And since we are in the subject of picking random numbers for Sattolo's algorithm. Using a simple modulo operator for get a range from a single random number going from 0 to 2^n-1 (like most RNGs produce) can introduce a bias. If the list is short and the numbers are large, it doesn't make that big a difference, but it is something to consider.
1. Find the smallest Z s.t. 2^Z-1 <= N, generate a random number, bitwise-and with 2^Z-1, accept the result if the result <= N, otherwise repeat. The expected number of times through the loop depends on Y and N, but is strictly less than 2.
2. Let W = floor((2^Z-1) / N), generate a random number, if the number < N*W, return the number mod N, otherwise repeat. The expected number of times through the loop depends on N and Y, but is no more than the first algorithm. The downside is that division and modular division are much slower than bitwise-and on most processors.
If division or modular division (on many processors, the same instruction) is much slower than bitwise-and, and your PRNG is pretty fast (such as xorshift / xorishiro), you're better off with the first algorithm.Note that finding the mask from the first algorithm on a 64-bit machine is as simple as:
mask = N; for( i = 1; i < 64; i *= 2) { mask |= mask >> i; } // Check if your compiler unrolls this loopI'm having trouble parsing the motivation and terminology. When a list has one cycle, does that mean it repeats once? Or is this basically 'i want a random but stable order of events'?
If you choose an element belonging to a given cycle, then generate new elements by repeatedly applying the permutation, all the elements you generate will belong only to that cycle.
So, if your permutation can be written as the product of more than one cycle, and you choose a random starting element and generate new elements by successive application of the permutation, you will only generate a strict subset of all the possible elements.
On the other hand, if your permutation only has a single cycle, then that procedure will generate all the elements.
[1] https://en.wikipedia.org/wiki/Permutation#Cycle_notation
Looks like the first sentence of wikipedia confirms it's an overloaded word:
>In mathematics, a permutation of a set is, loosely speaking, an arrangement of its members into a sequence or linear order, or if the set is already ordered, a rearrangement of its elements. The word "permutation" also refers to the act or process of changing the linear order of an ordered set.
https://github.com/travisdowns/MemoryLanes/blob/b6cd7d2ceaa0...
I have used it a half dozen times in more or less that specific context.