📜 ⬆️ ⬇️

Falling in love with F #: Dose 2: Building a fractal image, or a set of Mandelbrot do it yourself

In the last lesson we reviewed the basic concepts of functional programming, now let's try to put them into practice. Since functional programming, as you probably understood, is ideally suited for solving mathematical problems, we will consider just such a task - building an image of the Mandelbrot set, the most famous fractal set.



image


Mathematically, the Mandelbrot set is defined as follows. Consider the sequence of complex numbers z (n + 1) = z (n) ^ 2 + c, z (0) = 0. For different c, this sequence either converges or diverges. For example, for c = 0, z (i) = 0, and for c = 2, we have a divergent sequence. So, the Mandelbrot set is the set of those c for which the sequence converges.


We proceed to the implementation of the algorithm on F #. To begin with, we define the original function



let mandelf (c:Complex) (z:Complex) = z*z+c;;


Here we had to explicitly specify the type of Complex (this should be done for at least one of the variables, but we did for two for symmetry), since the default for the + operation is to have an integer type. In order for the Complex type to become available, you must first specify the preamble:


')
open Microsoft.FSharp.Math;;
open System;


To test convergence, we will make a small assumption. We assume that the sequence converges if | z (20) | <1. To calculate z (20), we use the following function of a multiple composition that recursively applies the specified function a specified number of times:



 let rec rpt nf = if n=0 then (fun x->x) else f >> (rpt (n-1) f);; 

Here, the sign >> denotes the composition of functions, and the entry fun x-> x - the identity function. Generally speaking, the construction fun x -> ... allows us to set a functional constant, i.e. expression of the function type from a single argument. For example, the following two constructions are equivalent:



 let double x = x*2 let double = fun x -> x*2 

In our case, the function rpt takes one argument of integer type n (number of repetitions), and some function f, i.e. has type rpt: int -> ('a ->' a) -> ('a ->' a). For n = 0, the identity function is returned, and for n> 0, the composition f and (n-1) -fold application of f are returned. The entry 'a means polymorphic type, i.e. instead, it can be any valid data type.


Returning to our task, recall that for a fixed c, the partial application of a curried function (mandelf c) will be a function of one argument (x), and the function of multiple composition applies to this function. As a result, | z (20) | will be calculated as rpt 20 (mandelf c) (Complex.zero) . Indeed, rpt 20 (mandelf c) will denote
A 20-fold application of the mandelf function mandelf , which we then apply to 0. Then the membership function of a complex number to the Mandelbrot set is written as


 let ismandel c = Complex.Abs(rpt 20 (mandelf c) (Complex.zero))<1.0;; 

The rest is a matter of technique. We define the scale scaling function (it will take as pairs of numbers as arguments - ranges of change of variables of type float*float and
int*int ), and in a double loop we print the set on the console:



 let scale (x:float,y:float) (u,v) n = float(nu)/float(vu)*(yx)+x;; for i = 1 to 60 do for j = 1 to 60 do let lscale = scale (-1.2,1.2) (1,60) in let t = complex (lscale j) (lscale i) in System.Console.Write(if ismandel t then "*" else " "); System.Console.WriteLine("") ;; 

But that is not all! Recall that the full power of the Microsoft .NET platform is available to the F # programmer! Therefore, we can build a graphic image in the window using
Windows Forms and the System.Drawing library! Corresponding code:



 #light open System.Drawing open System.Windows.Forms let form = let image = new Bitmap(400, 400) let lscale = scale (-1.2,1.2) (0,image.Height-1) for i = 0 to (image.Height-1) do for j = 0 to (image.Width-1) do let t = complex (lscale i) (lscale j) in image.SetPixel(i,j,if ismandel t then Color.Black else Color.White) let temp = new Form() temp.Paint.Add(fun e -> e.Graphics.DrawImage(image, 0, 0)) temp [<STAThread>] do Application.Run(form);; 

What came out of it - see the picture below:


image


Of course, to get a full-fledged color image of the Mandelbrot set on F #, you need to work a little more! Let my readers do it as
exercises. If possible - write in the comments!

Source: https://habr.com/ru/post/53626/


All Articles