Draw with SQL Server, plot the Mandelbrot set!

Carissimi lettori,

Siamo giunti all'ultimo articolo di quest'anno.
Primi 5 mesi di vita di questo blog e circa 65 articoli che spero vi siano tutti piaciuti!
Il mio impegno per essere il più chiaro possibile ce l'ho messo tutto!

Come vi avevo anticipato questo sarà un articolo più curioso e divertente.
Vediamo come disegnare con SQL Server.


Hi guys!

We have reached the last article of this year. 
First 5 months of life of this blog and about 65 articles that I hope you enjoyed! 
I put my best effort into being as clear as possible! 

As I anticipated, this will be a more curious and fun article. 
Let's see how to draw with SQL Server.

 

Introduction


Già ma cosa disegniamo?
Disegnamo l'insieme di Mandelbrot che è l'insieme dei numeri complessi c per i quali la funzione:

 

quando iterata da Z=0 non diverge.

Questa funzione prende il nome dal matematico Benoit Mandelbrot ed è un esempio di frattale.

Ora sia Z che c sono due numeri complessi.

I numeri complessi sono un estensione dei numeri reali creati dai matematici per poter estrarre radici quadrate di numeri negati oppure per risolvere equazioni di secondo grado con discriminante negativo.

P.S. Non me ne vogliamo i matematici per questa estrema sintesi che è solo ai fini di poter  spiegare il prosieguo dell'articolo.

Quello che occorre sapere è che un numero complesso si può esprimere nella forma:

Z = X + i * y

dove i è detto unità immaginaria e vale SQRT(-1)

Bene,

Se Z = X + i * y allora avremo che:

Z^2 = X^2 + (i*y)^2 + 2 * X * i * y ) = X^2 + 2 * X * y * i + Y^2 - Y^2

Mentre C sarà:

C = X0 + i * y0

Da questo deriva che il calcolo che dovremo iterare più volte è:

X = Parte reale (  Z ^ 2 + C ) = X^2 - Y^2 +X0
Y = Parte immaginaria ( Z ^ 2 + C )  =  2*X*Y + Y0.

Il nostro algoritmo da implementare sarà:
Se iterando un certo numero di volte il calcolo sopra il risultato non diverge il punto c apparterrà all'insieme di mandelbrot altrimenti ...no!

Ora proviamo di implementare questo algoritmo in T-SQL.
Seguitemi!




But what do we draw?
We draw the Mandelbrot set which is the set of complex numbers c for which the function:



when iterated by Z = 0 it does not diverge.

This function is named after the mathematician Benoit Mandelbrot and is an example of a fractal.
Now both Z and c are two complex numbers.

Complex numbers are an extension of real numbers created by mathematicians to be able to extract square roots of negated numbers or to solve second degree equations with negative discriminant.

P.S. I do not want mathematicians for this extreme summary which is only for the purpose of being able to explain the continuation of the article

What you need to know is that a complex number can be expressed in the form:

Z = X + i * y

where i is called imaginary unit and i = SQRT(-1)


If Z = X + i * y we have:

Z^2 = X^2 + (i*y)^2 + 2 * X * i * y ) = X^2 + 2 * X * y * i + Y^2 - Y^2

While C will be:

C = X0 + i * y0

From this it follows that the calculation that we will have to iterate several times is:

X = Real Part (  Z ^ 2 + C ) = X^2 - Y^2 +X0
Y = Imaginary Part ( Z ^ 2 + C )  =  2*X*Y + Y0.

Our algorithm to implement will be:
If iterating a certain number of times the calculation above the result does not diverge the point c will belong to the set of mandelbrots otherwise ... no!
 
 
Follow me!
Now let's try to implement this algorithm in T-SQL.




Draw with SQL Server


Realizziamo il calcolo principale tramite un ciclo WHILE che sarà fatto in questo modo:

  
       
While (@Iteration < @MaxIterations) And 

      (Square(@PtX) + Square(@PtY)) < 4.0 

Begin 

  Set @PtX = Square(@PtX) - Square(@PtY) + @Xo

  Set @PtY = 2* @PtX * @PtY + @Yo   

  Set @Iteration = @Iteration + 1 

End

 
Dove

@MaxIterations = numero max di iterazioni

Adesso immaginiamo di racchiudere il blocco di codice sopra tra due cicli WHILE nidificati così da far eseguire il calcolo per che le nostre variabili X0 e Y0

While @Yo <= @Top 
Begin 
  While @Xo <= @Right 
  Begin 
    Set @PtX = @Xo 
    Set @PtY = @Yo

    <<< BLOCCO PRECEDENTE >>>

    If @Iteration < @MaxIterations
    then 1
    else 0



    Set @Xo = @Xo + @res 
    Set @Iteration = 0
  End
  Set @Xo = @Left
  Set @Yo = @Yo + @Res
End


Adesso manca solamente la parte che scrive a video che potete vedere evidenziata in giallo:
       
Create PROCEDURE dbo.mandelbrot
@left float,
@right float,
@Top float,
@Bottom float,
@Res float,
@MaxIterations Integer = 500

As
Set NoCount On

Declare @StrOut varchar(200)
Declare @Xo float, @Yo float, @Abs float
Declare @PtX Float, @PtY Float
Declare @Iteration Integer Set @Iteration = 0

SET @Xo = @Left
SET @Yo = @Bottom

While @Yo <= @Top Begin
  While @Xo <= @Right Begin
    SET @PtX = @Xo
    SET @PtY = @Yo

    While @Iteration < @MaxIterations And 
          (Square(@PtX) + Square(@PtY)) < 4.0
    Begin
      SET @PtX = Square(@PtX) - Square(@PtY) + @Xo
      SET @PtY = 2* @PtX * @PtY + @Yo
      SET @Iteration = @Iteration + 1
    End



    SET @StrOut = @StrOut + ( Case
                              When @Iteration < @MaxIterations
                              Then 'X'
                              Else ' '
                              End )


    SET @Xo = @Xo + @res
    SET @Iteration = 0
  End
  
  Print @Strout
  SET @StrOut = ''
  SET @Xo = @Left
  SET @Yo = @Yo + @Res
End



OK siete pronti per provare?

Provate a scrivere:
       
EXEC mandelbrot -2, 2, 2, -2, 0.02
      

Prendente l'output e copiatelo nel notepad ed ecco la prima immagine dell'insieme di Mandelbrot!


mandelbrot set in ascii

 
Per oggi è tutto anzi, per quest'anno è tutto!
Grazie per avermi seguito, spronato e corretto.

Vi auguro un sereno e felice 2020!






We carry out the main calculation through a WHILE cycle which will be done in this way.
       
While (@Iteration < @MaxIterations) And 

      (Square(@PtX) + Square(@PtY)) < 4.0 

Begin 

  Set @PtX = Square(@PtX) - Square(@PtY) + @Xo

  Set @PtY = 2* @PtX * @PtY + @Yo   

  Set @Iteration = @Iteration + 1 

End

 
Where

@MaxIterations = max number of iterations


Now let's imagine enclosing the block of code above between two nested WHILE loops so as to make the calculation for our variables X0 and Y0
       
While @Yo <= @Top 
Begin 
  While @Xo <= @Right 
  Begin 
    Set @PtX = @Xo 
    Set @PtY = @Yo

    <<< BLOCCO PRECEDENTE >>>

    If @Iteration < @MaxIterations
    then 1
    else 0



    Set @Xo = @Xo + @res 
    Set @Iteration = 0
  End
  Set @Xo = @Left
  Set @Yo = @Yo + @Res
End       
 

Now only the part that writes on video that you can see highlighted in yellow is missing:
       

Create PROCEDURE dbo.mandelbrot
@left float,
@right float,
@Top float,
@Bottom float,
@Res float,
@MaxIterations Integer = 500

As
Set NoCount On

Declare @StrOut varchar(200)
Declare @Xo float, @Yo float, @Abs float
Declare @PtX Float, @PtY Float
Declare @Iteration Integer Set @Iteration = 0

SET @Xo = @Left
SET @Yo = @Bottom

While @Yo <= @Top Begin
  While @Xo <= @Right Begin
    SET @PtX = @Xo
    SET @PtY = @Yo

    While @Iteration < @MaxIterations And 
          (Square(@PtX) + Square(@PtY)) < 4.0
    Begin
      SET @PtX = Square(@PtX) - Square(@PtY) + @Xo
      SET @PtY = 2* @PtX * @PtY + @Yo
      SET @Iteration = @Iteration + 1
    End



    SET @StrOut = @StrOut + ( Case
                              When @Iteration < @MaxIterations
                              Then 'X'
                              Else ' '
                              End )


    SET @Xo = @Xo + @res
    SET @Iteration = 0
  End
  
  Print @Strout
  SET @StrOut = ''
  SET @Xo = @Left
  SET @Yo = @Yo + @Res
End

       
 

OK are you ready to try? 
 
 
Just type:

EXEC mandelbrot -2, 2, 2, -2, 0.02 
       

Taking the output and copy it to the notepad and here is the first image of the Mandelbrot collection!

Mandelbrot set in ascii



That's all for today, that's all for this year! 
Thank you for following me.
I wish you a peaceful and happy 2020!




Luca Biondi @ SQLServerPerformance blog!












Comments

I Post più popolari

SQL Server, execution plan and the lazy spool (clearly explained)

SQL Server, datetime vs. datetime2

La clausola NOLOCK. Approfondiamo e facciamo chiarezza!