37

In my thesis that I'm writing on, I'm using a Mandelbrot generator to test an application I've written. To explain a certain problem discussed in the report an actual generated image need to be included.

Since every figure in the report so far has been generated using TikZ, I'm wondering whether I could also generate the Mandelbrot image using TikZ. But would it possible?

2
  • 1
    There's a TikZ library for fractal decorations (30.7 Fractal Decorations) and a Lindenmayer systems library (37 Lindenmayer System Drawing Library) Commented Aug 25, 2012 at 15:44
  • Heiko Oberdiek posted a Mandelbrot generator in LaTeX at the Programming Puzzels & Code Golf stackexchange: codegolf.stackexchange.com/questions/23423/… Commented Mar 25, 2014 at 5:50

6 Answers 6

28

There's a Mandelbrot set shading in the shadings library:

\documentclass{article} \usepackage{tikz} \usetikzlibrary{shadings} \begin{document} \tikz\shade[shading=Mandelbrot set] (0,0) rectangle (4,4); \end{document} 

Mandelbrot set

Displayed with the Acrobat Reader, as the TeXworks PDF previewer did not show high resolution.

The Mandelbrot set is computed and generated by the PDF renderer. The algorithm is written using PostScript commands, PDF supports a subset of Postscript operators, that's why it should be much faster than computing using higher level pgf or TikZ operators.

4
  • Ha! Well, that was unexpected. ^^ Unfortunately, the image doesn't exactly look like a Mandelbrot set, but cool nonetheless. Commented Dec 28, 2011 at 17:05
  • 3
    @gablin This could be caused by a low number of iterations, I would expect that a higher number of iterations would be nearer to the exact Mandelbrot set, which would require an infinite number of iterations. Commented Dec 28, 2011 at 17:10
  • @StefanKottwitz Is there any way to increase the iteration count? That looks like 10 or so iterations . . . you get a much better picture even with just 20. Commented Nov 15, 2013 at 18:53
  • @mrc Yes, it can be seen in the code of that TikZ library, the number of iteration is fixed but can be extended by changing or redefining the code. Commented Nov 15, 2013 at 22:15
23

Here is a rather crude solution using luatex. Note that the calculations are done without any optimization, no use of symmetry or any other properties of the Mandelbrot set. Warning: the code takes a while to process even on a fairly fast computer.

\documentclass{standalone} \usepackage{tikz} \usepackage{luacode} \def\escapetime#1#2{\directlua{tex.print(escape_time(#1,#2))}} \def\mandcolor#1#2{\directlua{mand_color(#1,#2)}} \begin{document} \begin{luacode} local NUMITER=100 point_iter = function (a,b) local n = 1 local x = a local y = b return function () if n > NUMITER then return nil end n = n+1 x,y = x*x - y*y + a, 2*x*y + b return n, x*x + y*y end end escape_time = function (a,b) local esc_time for n, d in point_iter(a,b) do esc_time = n if d > 4 then break end end return esc_time end mand_color = function (a,b) local etime = escape_time(a,b) if etime == NUMITER+1 then tex.print("black") else tex.print("red!"..etime) end end \end{luacode} \begin{tikzpicture}[scale=2] \foreach \x in {-2,-1.99,...,.5}{ \foreach \y in {-1.3,-1.29,...,1.3}{ \draw[\mandcolor{\x}{\y},fill] (\x,\y) +(-.005,-.005) rectangle +(.005,.005);}} \end{tikzpicture} \end{document} 

This is the resulting image:

mandelbrot set generated with lualatex

The next step would be to use mplib directly from lua to render the picture.

22

For those who are interested in another approach, i.e., using PSTricks:

\documentclass[border=12pt]{standalone} \usepackage{pst-fractal} \begin{document} \psfractal[type=Mandel,baseColor=red,maxRadius=30,dIter=30,cx=-1.3,xWidth=4cm,yWidth=4cm](-3,-2)(2,2) \end{document} 

enter image description here

Compile the code snippet above with xelatex or latex-dvips-ps2pdf sequence.

3
  • 1
    Very cool! How does the pstricks compare to MATLAB or Python in the terms of speed when it comes to things like plotting strange attractors, KAM islands or fractals? How difficult is to generate movie? In MATLAB is for example trivial to generate movie which shows creation of the Lorenz attractor. It is fairly easy to call such movie from the Powerdot slides (written in PSTricks) but I wonder if I could create animation natively which will not require to launch a video player. Commented Dec 29, 2011 at 2:05
  • 2
    I believe that pstricks does not actually generate the image, it inserts postscript code that does the actual calculation. Which means the speed would depend on your postscript interpreter. When printing such document on a postscript printer, the calculations would be done on the printer. When viewing the resulting dvi or postscript file, the calculations would be done by your dvi or ps viewer at the time of viewing. Perhaps you could first convert from postscript to another format, the calculation would happen then, and view the result later. Commented Dec 29, 2011 at 2:52
  • Of course. I meant PostScript and Ghostscript interpreter vs MATLAB or Python. See my post here for getting row PostScript into TeX with command special tex.stackexchange.com/questions/23987/… Commented Dec 29, 2011 at 4:39
11

I posted a pgfplots solution on TeXwelt.de drawing the Mandelbrot set: Fraktale mit pgfplots. Christian Feuersänger improved it, instead of creating a table (as inspired by Herbert) doing the sampling via \addplot3 and the coloring by surf and shader=interp. Run it with LuaLaTeX.

Mandelbrot set

The complete code:

\documentclass{standalone} \usepackage{pgfplots} \pgfplotsset{width=7cm,compat=1.8} \usepackage{luacode} \begin{luacode} function mandelbrot(cx,cy, max_iter, max) local x,y,xtemp,ytemp,squaresum,iter squaresum = 0 x = 0 y = 0 iter = 0 while (squaresum <= max) and (iter < max_iter) do xtemp = x * x - y * y + cx ytemp = 2 * x * y + cy x = xtemp y = ytemp iter = iter + 1 squaresum = x * x + y * y end local result = 0 if (iter < max_iter) then result = iter end -- result = squaresum -- io.write("" .. cx .. ", " .. cy .. " = " .. result .. " (iter " .. iter .. " squaresum " .. squaresum .. ") \string\n") tex.print(result); end \end{luacode} \begin{document} \begin{tikzpicture} \begin{axis}[ colorbar, axis equal, point meta max=30, tick label style={font=\tiny}, view={0}{90}] \addplot3 [surf,domain=-1.72:0.72,shader=interp,domain y=-1:1,samples=300] { \directlua{mandelbrot(\pgfmathfloatvalueof\x, \pgfmathfloatvalueof\y,10000,4)} }; \end{axis} \end{tikzpicture} \end{document} 
5

I couldn't resist to proposing a MetaPost version. After all, MetaPost is embedded in LuaTeX and thanks to the package luamplib we have direct access to it, so it would be a pity not to take advantage of this fact :-)) All credits must go to Stephan Kottwitz though (and to Herbert previously), since the following code is almost entirely an adaptation of his Lua Code to MetaPost. Without it, drawing this would probably not have been possible to me, since I know too little about fractals.

Notice the call to MetaPost's newly implemented floating point number system by the instruction \mplibnumbersystem{double}. I figure it is necessary, due to the heaviness of the computations.

Caution: it may take several minutes for the following code to compile! (10 min for my 5-year old laptop.)

\documentclass[12pt]{article} \usepackage{luamplib} \mplibnumbersystem{double} \mplibtextextlabel{enable} \begin{document} \begin{center} \leavevmode \begin{mplibcode} u := 4cm; vardef mandelbrot(expr xa, xb, ya, yb, steps, max_iter, maxs) = save dx, dy, cx, cy, xtemp, ytemp, squaresum, iter; clearxy; dx := (xb-xa)/steps; dy := (yb-ya)/steps; cx := xa; forever: exitunless cx <= xb; cy := ya; forever: exitunless cy <= yb; squaresum := 0; x:= 0; y:= 0; iter := 0; forever: exitunless (squaresum <= maxs) and (iter < max_iter); xtemp := x**2 - y**2 + cx; ytemp := 2*x*y + cy; x := xtemp; y := ytemp; iter := iter + 1; squaresum := x**2 + y**2; endfor; if iter >= max_iter: draw u*(cx, cy); fi; cy := cy + dy; endfor; cx := cx + dx; endfor; enddef; beginfig(0); % Coordinates and marks xmin = -2; xmax = 0.75; ymin = -1.25; ymax = 1.25; len := 6bp; draw u*(xmin, ymin) -- u*(xmax, ymin) -- u*(xmax, ymax) -- u*(xmin, ymax) -- cycle; for i = -1.5 step .5 until .5: label.bot("$" & decimal i & "$", u*(i, ymin)); draw u*(i, ymin) -- (i*u, ymin*u+len); draw u*(i, ymax) -- (i*u, ymax*u-len); endfor; for j = -1 step 1 until 1: label.lft("$"&decimal j&"$", u*(xmin, j)); draw u*(xmin, j) -- (xmin*u+len, j*u); draw u*(xmax, j) -- (xmax*u-len, j*u); endfor; % Mandelbrot fractal pickup pencircle scaled 1bp; mandelbrot(-2, 1, -2, 2, 500, 1000, 4); endfig; \end{mplibcode} \end{center} \end{document} 

enter image description here

1

With knitr one can use R to draw the Mandelbrot set (R code from here):

\documentclass[12pt]{scrartcl} \begin{document} <<echo=F>>= cols <- colorRampPalette(c("blue","yellow","red","black"))(11) xmin = -2 xmax = 1 nx = 500 ymin = -1.5 ymax = 1.5 ny = 500 n=200 # variables x <- seq(xmin, xmax, length.out=nx) y <- seq(ymin, ymax, length.out=ny) c <- outer(x,y*1i,FUN="+") z <- matrix(0.0, nrow=length(x), ncol=length(y)) k <- matrix(0.0, nrow=length(x), ncol=length(y)) for (rep in 1:n) { index <- which(Mod(z) < 2) z[index] <- z[index]^2 + c[index] k[index] <- k[index] + 1 } image(x,y,k, col=cols) @ \end{document} 

mandelbrot set

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.