mandelbrotset
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
The Mandelbrot Set
A [NetLogo] model by Rik Blok.
http://www.zoology.ubc.ca/~rikblok/wiki/doku.php?id=science:popmod:mandelbrot_set:start
Explore the Mandelbrot Set and these related fractals:
Mappings
Each fractal is defined by a function in the complex plane. Starting with an initial value z=0, each point c in the plane is repeatedly iterated through the map, z → f(z,c). The mapping function is characterized by an exponent, d (d-multibrot-exp slider in the simulation), as follows:
- Mandelbrot: f(z,c) = z2 + c (same as Multibrot with d=2)
- Multibrot: f(z,c) = zd + c
- Mandelbar: f(z,c) = Conj(z)d + c
- Burning ship: f(z,c) = (|Re(z)| + i |Im(z)|)d + c
A point c is excluded from the set if the value z diverges after repeated iteration. In the simulation, excluded points are painted a color indicating how many iterations were required to decide they have diverged. Black points indicate undecided candidates that may belong to the set.
Other implementations and examples
This implementation of the Mandelbrot set is neither fast nor beautiful -- it's just a proof of concept and a demonstration of how to code in [NetLogo]. If you're interested in the Mandelbrot set or similar fractals, check out these excellent pages:
- Google's Julia Map
- Last Lights On - video of Mandelbrot zoom to 10228
Comments and Questions
globals [ xmin ymin xmax ymax was-mouse-down? was-mouse-xcor was-mouse-ycor was-record-mov was-record-png png-file-prefix png-file-index was-multibrot-exp was-generalization was-going tick-last-change max-detectable-period was-zoom-power ] patches-own [ x y real imag was-real was-imag] to startup clear-all ; defaults set record-mov false set was-record-mov false set record-png false set was-record-png false set was-mouse-down? false set was-going false set jump-size 25 set mouse-zooms-in true set max-detectable-period 3 set was-zoom-power 0 reset ; hint output-print "Explore the Mandelbrot set\nand related fractals.\nPress go to get started." end to reset ; range set xmin -2 set xmax 2 set ymin -2 set ymax 2 zoom end to zoom if (movie-status != "No movie.") [ movie-grab-view ] if (record-png) [ export-view ( word png-file-prefix " " was-zoom-power " " png-file-index ".png" ) set png-file-index png-file-index + 1 set was-zoom-power zoom-power ] reset-ticks set tick-last-change 20 * ticks-per-zoom ; don't auto-zoom for at least 20 ticks-per-zoom if all black set was-multibrot-exp d-multibrot-exp ; set was-conjugate conjugate set was-generalization generalization let xslope width / ( max-pxcor - min-pxcor ) let yslope height / ( max-pycor - min-pycor ) ask patches [ set pcolor black set x (pxcor - min-pxcor) * xslope + xmin set y (pycor - min-pycor) * yslope + ymin set real 0 set imag 0 set was-real [] set was-imag [] ] ask patch max-pxcor 4 [ set plabel zoom-power ] end to go ; check for changed parameters if (not was-going) [ output-print "\nDrag the mouse to move or\npress the W/A/S/D keys." output-print "Click to zoom or\npress the +/- keys." set was-going true ] if (d-multibrot-exp != was-multibrot-exp ) [ zoom output-print "\nChange the multibrot\nexponent d, z->z^d+c." ] if (generalization != was-generalization) [ zoom output-print "\nChoose a generalization\nof the Mandelbrot set." ] ; check for changed record switches if (record-png and not was-record-png) [ ; start recording to png ifelse (netlogo-applet?) [ output-print "\nSorry, can't record from applet." output-print "Download the .nlogo file to allow recording." set png-file-prefix false ][ set png-file-prefix user-new-file ] ifelse (png-file-prefix != false) [ ; strip file extension set png-file-prefix remove ".PNG" png-file-prefix set png-file-prefix remove ".png" png-file-prefix set was-record-png true set was-zoom-power zoom-power output-print "\nStarted recording to png files." ][ ; cancelled set record-png false ] ] if (record-mov and not was-record-mov) [ let mov-file false ifelse (netlogo-applet?) [ output-print "\nSorry, can't record from applet." output-print "Download the .nlogo file to allow recording." ][ set mov-file user-new-file ] ifelse (mov-file != false) [ ; strip file extension set mov-file remove ".MOV" mov-file set mov-file remove ".mov" mov-file ; add extension set mov-file word mov-file ".mov" ; start recording to mov movie-start mov-file set was-record-mov true output-print "\nStarted recording to mov file." ][ ; cancelled set record-mov false ] ] if (was-record-mov and not record-mov) [ ; stop recording mov if (movie-status != "No movie.") [ movie-close ] output-print "\nStopped recording to mov file." ] ; check for mouse activity if (mouse-down? and not was-mouse-down?) [ ; mouse press set was-mouse-down? true set was-mouse-xcor mouse-xcor set was-mouse-ycor mouse-ycor ] ; check for auto-zoom if (was-mouse-down? and not mouse-down?) [ ; mouse release let xslope width / ( max-pxcor - min-pxcor ) let yslope height / ( max-pycor - min-pycor ) if-else (mouse-xcor = was-mouse-xcor and mouse-ycor = was-mouse-ycor) [ ; click, zoom centered on mouse output-type "\nMouse click: zoom " let xc (mouse-xcor - min-pxcor) * xslope + xmin let yc (mouse-ycor - min-pycor) * yslope + ymin let xrad 0 let yrad 0 ifelse mouse-zooms-in [ set xrad width * (1 - jump-size / 100) / 2 set yrad height * (1 - jump-size / 100) / 2 output-type "in " ][ set xrad width / (1 - jump-size / 100) / 2 set yrad height / (1 - jump-size / 100) / 2 output-type "out " ] output-type jump-size output-print "%" set xmin xc - xrad set xmax xc + xrad set ymin yc - yrad set ymax yc + yrad ][ ; drag output-print "\nMouse drag: move" let xshift (was-mouse-xcor - mouse-xcor) * xslope let yshift (was-mouse-ycor - mouse-ycor) * yslope set xmin xmin + xshift set xmax xmax + xshift set ymin ymin + yshift set ymax ymax + yshift ] set was-mouse-down? false zoom ] ; let hue ticks mod 256 ; let sat 255 - 20 * int ( ticks / 256 ) let slow-ticks 1.25 * ticks ^ 0.8 ; increases slower than ticks for large ticks let hue slow-ticks mod 256 let sat 255 - int ( slow-ticks / 12.8 ) let conjugate ( generalization = "Mandelbar, complex conjugate" ) let absolute-value ( generalization = "Burning ship, absolute value" ) let changes 0 ask patches with [pcolor = black] [ ; iterate z_{n+1} = z_n^2 + (x + i y) if (conjugate) [ set imag ( - imag ) ] if (absolute-value) [ set real abs real set imag abs imag ] let oldreal real set real x + re-pow real imag d-multibrot-exp ; Re(z_{n+1}) = x + Re(z_n^multibrot-exp) set imag y + im-pow oldreal imag d-multibrot-exp ; Im(z_{n+1}) = x + Im(z_n^multibrot-exp) ifelse (real * real + imag * imag) > 4 [ ; diverges set pcolor hsb hue sat 255 set changes changes + 1 ][ ; hasn't diverged. Check if periodic let period position real was-real ifelse (period != false and period = position imag was-imag) [ set period period + 1 ; so not zero set pcolor rgb period period period ; don't track changes here...makes run too long ; set changes changes + 1 ][ ; not periodic. Add new (real, imag) to history set was-real fput real was-real set was-imag fput imag was-imag while [length was-real > max-detectable-period] [ ; trim set was-real but-last was-real set was-imag but-last was-imag ] ] ] ] if (changes > 0) [ ; if (ticks > tick-last-change + 1) [ print ticks ] set tick-last-change ticks ] tick end to zoom-in ; zoom in by factor 1 - jump-size let newwidth width * (1 - jump-size / 100) let newheight height * (1 - jump-size / 100) let xcrop ( width - newwidth ) / 2 let ycrop ( height - newheight ) / 2 set xmin xmin + xcrop set xmax xmax - xcrop set ymin ymin + ycrop set ymax ymax - ycrop output-type "\nZoom in " output-type jump-size output-print "%" zoom end to zoom-out ; zoom in by factor 1 - jump-size let newwidth width / (1 - jump-size / 100) let newheight height / (1 - jump-size / 100) let xcrop ( newwidth - width ) / 2 let ycrop ( newheight - height ) / 2 set xmin xmin - xcrop set xmax xmax + xcrop set ymin ymin - ycrop set ymax ymax + ycrop output-type "\nZoom out " output-type jump-size output-print "%" zoom end to move-up ; shift by jump-size let move jump-size / 100 * height set ymin ymin + move set ymax ymax + move output-type "\nMove up " output-type jump-size output-print "%" zoom end to move-left ; shift by jump-size let move jump-size / 100 * width set xmin xmin - move set xmax xmax - move output-type "\nMove left " output-type jump-size output-print "%" zoom end to move-down ; shift by jump-size let move jump-size / 100 * height set ymin ymin - move set ymax ymax - move output-type "\nMove down " output-type jump-size output-print "%" zoom end to move-right ; shift by jump-size let move jump-size / 100 * width set xmin xmin + move set xmax xmax + move output-type "\nMove right " output-type jump-size output-print "%" zoom end to-report width report xmax - xmin end to-report height report ymax - ymin end to toggle-mouse-zoom set mouse-zooms-in not mouse-zooms-in output-type "\nMouse clicks now zoom " output-print ifelse-value (mouse-zooms-in) [ "in." ][ "out." ] end to-report re-pow [ zr zi d ] ; returns Re(z^d) = Re((zr + i zi)^d) via recursion. Assumes d>=2 is an integer. ifelse (d = 2) [ ; Re(z^2) = zr^2 - zi^2 report zr * zr - zi * zi ][ ; Re(z^d) = Re(z z^(d-1)) = zr Re(z^(d-1)) - zi Im(z^(d-1)) report zr * ( re-pow zr zi (d - 1)) - zi * ( im-pow zr zi (d - 1)) ] end to-report im-pow [ zr zi d ] ; returns Im(z^d) = Im((zr + i zi)^d) via recursion. Assumes d>=2 is an integer ifelse (d = 2) [ ; Im(z^2) = 2 zr zi report 2.0 * zr * zi ][ ; Im(z^d) = Im(z z^(d-1)) = zi Re(z^(d-1)) + zr Im(d^(n-1)) report zi * ( re-pow zr zi (d - 1)) + zr * ( im-pow zr zi (d - 1)) ] end to coords ; report coordinates output-print "center:" output-type "x = " output-print ( xmin + xmax ) / 2 output-type "y = " output-print ( ymin + ymax ) / 2 let scale xmax - xmin output-type "scale = " output-print ifelse-value (scale <= 0) [ 0 ][ rel-precision scale 2 ] end to-report rel-precision [ number places ] ; like precision but only for mantissa let pow floor log number 10 ; report ( 10 ^ pow ) * precision ( number / 10 ^ pow ) places report ( word precision ( number / 10 ^ pow ) places "E" pow ) end to zoom-every if (ticks > ( tick-last-change + ticks-per-zoom ) ) [ ifelse mouse-zooms-in [ zoom-in output-print "\nAutomatically zoomed in" ][ zoom-out output-print "\nAutomatically zoomed out" ] output-type "after " output-type ticks-per-zoom output-print " unchanged ticks." ] end to-report zoom-power report precision ( 0 - log width 10 ) 2 end
There is only one version of this model, created about 11 years ago by Rik Blok.
This model does not have any ancestors.
This model does not have any descendants.