206 points by mg on Oct 16, 2012 | hide | past | favorite | 47 comments

 It's not a fractal, but it is something familiar.Multiply two complex numbers z and c is equivalent to taking z and applying a rotation and dilation to it, the rotation through arg(c) and the dilation through |c|. Division is the inverse of both, so z/c is z rotated by -arg(c) and dilated by 1/|c|.What you're looking at, then, is taking the operation defined by c (rotate by -arg(c) and dilate by 1/|c|) and asking, if you take the Gaussian integers as the vertexes of a directed graph, what fraction of the vertexes are the source of an edge.Consider the 1 dimensional analogy using real numbers. Given some real number c, take all the integers as the vertexes of a graph, and if z/c (for some integer z) is also an integer, I put a directed edge from z to z/c. When are these connected? Well, if c is irrational, never. If c is rational, then there will be an infinite number of connections, but how infinite? When c is 2, there will be twice as many edges on average in any subset of the source vertexes as when c is 4. If we can write c as p/q, then the smaller p is, the more edges we'll get, and the brighter the pixel in your image.The 1 dimensional analogy will have a spike at 1/2, smaller spikes at 1/3 and 2/3, yet smaller spikes at 1/4 and 3/4, smaller ones yet at 1/5, 2/5, 3/5, and 4/5, etc. The spikes will all be distinct (because between any two rationals there is an irrational), but will be infinitely close (because the rationals are dense in the reals). As you keep zooming in, you will get more and more edges like this.What you're seeing is a variation on the classical structure of the rationals dense within the reals.Now, a fractal is a set with a fractional Hausdorff dimension. We have to extract a set from your function of c in order to talk about fractal dimension. We could take the support of the function (everywhere it's not zero). In the one dimensional case, that's the rationals. We could take level sets farther up (the set of c such that f(c) = k, for a constant k). Those are subsets of the rationals. However, the rationals, while dense in the reals, are of measure zero in the reals, and have Hausdorff dimension zero, and so do all the level sets. So it's not a fractal.Doesn't make it any less pretty though.
 I don't think this has anything to do with directed graphs. The operation looks like this. For nonzero c in C, compute the distance d(a(i+1)/c, Z+iZ) to the nearest Gaussian integer, where a is an integer.The max distance is A = 1/sqrt(2) so color the point a(1+i)/c proportionally by (A - d(a(i+1)/c, Z+iZ))/A  I'm taking a liberty with the description, since computing "the percentage of a(i+1)/c's that are Gaussian integers" is open to interpretation, and if taken literally could mean something else entirely, such as computation of the ratio #(A(c,n)\cap Z+iZ) / n  where A(c, n) = { a(i+1)/ c : 1 <= a <= n }  which is asking for a proportion products that become Gaussian integers--this is a divisibility test. However, this doesn't show how to vary the brightness of the images.
 "What you're looking at, then, is taking the operation defined by c (rotate by -arg(c) and dilate by 1/|c|) and asking, if you take the Gaussian integers as the vertexes of a directed graph, what fraction of the vertexes are the source of an edge."This doesn't sound like a mathematical operation. Can you give a more mathematical definition of the full graph? For Gaussian integers a+ib, c+id, (a+ib, c+id) is a directed edge from a+ib to c+id if and only if what?Whatever this directed graph (V, E) is, where V = Z + iZ and E \subseteq V \times V, it is not clear how the complex number c relates to the proportion of z in V such that there exists w in V with (z, w) in E. We have to know what E is before we can answer this.
 OK, for a less abstract description, the site gives:"For each complex number c calculate the following: For all gaussian integers g like 1+1i, 2+2i, 3+3i... when calculating g/c which percentage results in a gaussian integer again? The higher the percentage, the lighter the pixel."So, Imagine you have: c = a+bi g = x+xi  Division by complex numbers is simplified with a trick of multiplying both numerator and divisor by the complex conjugate of the divisor, so we compute:- 1 / c = c' / ( c * c' )  And we know that c * c' will always be real rather than complex. 1 / c = (a-bi) / (a^2 + b^2)  Now it's just a case of iterating through the possibilities of g and seeing if g time this value of 1/c produces a gaussian integer again. x+xi * a-bi = ( x*a - x*b*i^2 ) + i*(x*a - x*b) = x ( a+b + i(a-b) )  So, g/c = x [ a+b + i(a-b) ) / (a^2 + b^2) ] where g = x+xi  So for any g = x+xi this will only be a gaussian integer if both:- (a^2 + b^2) | x*(a+b) (a^2 + b^2) | x*(a-b)  And the original algorithm is testing all gaussian integers where 0 <= x <= 100(Probably riddled with mistakes, should really be revising for my final Maths exam tomorrow morning...)
 jc-denton replied, but appears to be hellbanned. His reply looks like this: ---Humm tried to implement it simply using std::complex but it does not give me meaningful results. What did I do wrong?template void CalcRealPercentage( const complex from, const complex to, const int intervalSize, std::vector& intensityMap ){ auto height = to.imag() - from.imag(); auto width = to.real() - from.real(); assert(intervalSize > 0 && height > 0 && width > 0 && from > 0); intensityMap.resize(width * height, 0); for (complex c = from; c.imag() < to.imag(); c.imag(c.imag() + 1)) { for (; c.real() < to.real(); c.real(c.real() + 1)) { for (auto i = 0; i < intervalSize; i++) { complex g(i, i); complex result = g / c; auto imagPart = result.imag(); if (imagPart == 0) { intensityMap.at(c.imag() * width + c.real())++; } } } }
 Seems to be after this comment: https://news.ycombinator.com/item?id=3468011Not sure why he was hellbanned and not Zed after that little exchange.
 Because readers of hacker news, as objective and spock-like as they like to think they are, really can't help but reverse-ad hominen when they vote. People are right because of who they are, not what they said. At the very least the bias appears as a benefit of the doubt.PG should have, instead of removing vote totals, removed usernames. But of course that would get in the way of the ego stroking..(I am of course no exception)
 > Now, a fractal is a set with a fractional Hausdorff dimension.Is there an authoritative definition of a fractal? The one you use rules out structures like Hilbert curves, which are generally considered fractals.
 > Is there an authoritative definition of a fractal?Sort of. I believe Mandelbrot's original definition required only that the Hausdorff dimension exceeds the topological dimension. And that kinda-sorta includes Hilbert curves, if you count them as topologically 1-dimensional.But I've seen other definitions, including a rather hazy one that was not a definition in the formal sense, but just talked about properties that certain interesting sets tend to have: self-similarity, etc.In any case, I have yet to find a situation in which the formal definition of "fractal" actually mattered significantly. (If someone knows of one, I'd be interested.)
 sp332 on Oct 16, 2012 No, it's pretty vague. http://en.wikipedia.org/wiki/Fractal#Characteristics Also, the Hausdorff dimension of a Hilbert curve is 2.
 Thanks Madhadron, this makes a lot of sense. The Gaussian Numbers define a grid in the Complex plane. This calculation highlights complex numbers which represent best the ratios among Gaussian Numbers. It shouldn't be surprising to find such an ordered distribution.
 madhadron: thank you for that explanation. In particular, I found your 1-dimensional analogy very helpful. Now that I understand the graph, I think it's even prettier. The beauty of these 'structural relationships' between numbers never ceases to amaze me.
 I don't really get what you are describing. But perhaps you could provide a matlab script to show?
 Evbn on Oct 16, 2012 It is as fractal as this is: http://en.m.wikipedia.org/wiki/Hilbert_curve
 It would be a lot more useful if he also described how he generated the picture, which would enable mathematicians to give him some useful pointers for exploring it further.
 Wow, HN front page! Ok, will describe the algorithm. One moment...
 mg on Oct 16, 2012 Ok, I have put a description of the algorithm above the comment section.
 How do you calculate that percentage, do you brute force it or do you have a formula that estimates or exactly gives the percentage?Also, do you allow the result of the division to be near a gaussian integer, or do you do an exact floating point equals?
 mg on Oct 16, 2012 I brute force it up to n sample points. For the first image n was 100.Yes, I allow the result to be near a gaussian integer. For the first image I counted everything as a gaussian integer where (real%1<0.1 && imaginary%1<0.1)
 Nursie on Oct 16, 2012 Cool, how high up the gaussian integers do you go to get that sort of detail?
 mg on Oct 16, 2012 For the first image up to 100+100i. Please be aware, that I only use gaussian integers of the form x+xi where the real and imaginary part are the same. Im not sure if that is clear from my description. If there is demand, I can put up the source. Its Javascript.
 yes please, put the javascript source.
 dfc on Oct 16, 2012 You have the 4000x4000 file with a jpg suffix but it is actually a png? I ran the image through pngcrush and it decreased the file size by 50%. You might want to do the same and save on bandwidth / page loading... \$ du -sh fractal* 14M fractal-optim.png 27M fractal.png
 mg on Oct 16, 2012 You are right! I had a png and a jpg version and uploaded the wrong one. Now the jpg is up. Thank you!
 Very cool. I stumbled upon something in the late 90s that is fractal in nature but doesnt use complex numbers - it just plots points directly on a grid with no need for iteration. http://www.youtube.com/watch?v=uwjhRYZ_eSI&feature=plcp
 I'm reminded of Escher's "Square Limit" works. Not sure if this is actually the same class of grid as those he used to generate them, but it's visually similar at least:http://www.wikipaintings.org/en/m-c-escher/square-limit-colo...
 This looks like the complex differentiation of 1/z with a grid like domain.
 It looks a lot like a cubic grid with perspective projection; http://degreesgame.com/display/ShowImage?imageUrl=/storage/I...
 From my sketchy understanding of your description of the algorithm, it seems like a 2d version of the patterns in gaps you see when you look at cornrows.
 The lines look like those on an inverted plane: http://xahlee.info/SpecialPlaneCurves_dir/Inversion_dir/inve...
 It's possible that what we're looking at is based on the map f(z) = 1/z applied to the cartesian coordinate grid.This is old-school, but a long time ago I wrote a java applet to help explore this function on the complex plane:http://www.math.nyu.edu/~neylon/applet1/If you move around the red square, you see a lot of the circular shapes that look similar to those in the fractal.I don't completely understand the algorithm being used, so I'm not sure how to gain more confidence on this guess.
 nyud.net doesn't really archive anything. https://en.wikipedia.org/wiki/Coral_cache
 I have nothing mathematical to add here. Just want to say when I voted for this item this morning I waited and waited for others to vote, then I had to leave the PC for several hours. Before that, I kept looking at that image and hoping others would vote for it and I'd see some Comments. Thanks for voting for it and all these Comments!
 My attempt using matlab(octave) to generate a 100x100 version of the image (using his function description):https://gist.github.com/3903785Hadn't figured out if there is a way of vectorising it further. Would appreciate any tips if anyone has any.
 I've managed to hack it into a semi-vectorised implementation which works up to 700x700 before it runs out of memory.http://i.imgur.com/xzgXW.png
 mg on Oct 17, 2012 Interesting! You dont have the squares. This is a hint that the squares in my version are due to floating point limitations.
 It's probably a combination of floating point errors adding up.
 To me, it looks VERY similar to the Laue pattern of the enzyme Rubisco. http://www.amazon.com/Photographic-diffraction-Science-Photo...
 Probably you still can define a fractal by changing slightly the construction.Anyways, here's my take for a generalization : http://imgur.com/qD0aZ
 reminds me of points on a 3d grid..http://www.youtube.com/watch?v=60CnwbngWWw&t=15m10s
 The self-similar structure originating from simple division looks reminiscent of various representations of the natural prime numbers.
 That's what I thought of to.http://en.wikipedia.org/wiki/Ulam_spiral
 Are you using a large fixed point system or floating point? I hope the fractal-ness isn't just floating point rounding writ large.
 Its Javascript numbers. As far as I know they are always 64bit floating points. Yes, its possible that floating point artefacts play a role in this.
 I would look into Lobachevsky geometry or inversions on the plane to describe this.