Um número imaginário é dado pela existência de uma raiz quadrada de um número negativo, uma vez que, em termos reais, as raízes de números negativos seriam impossíveis de serem resolvidas. Desta forma, o número imaginário i é representado por √(-1).
Diante disso, os números complexos são obtidos pela adição de um número real e um número imaginário (a + bi) onde a e b são denominados números reais e i um número imaginário. O par acima é composto ainda por duas partes: uma real (a) e outra imaginária (bi), que permitem operações de adição e multiplicação a partir das seguintes regras:
(a+ib)+(c+id)=(a+c)+i(b+d)
(a+ib) X (c + id) = (ac - bd ) + i(ad+bc)
A regra de multiplicação nos permite verificar que a parte real bd é formada pela multiplicação de dois números imaginários i x i, uma vez que a raiz quadrada de um número imaginário (√(-1)^2 )) é igual a -1.
Além disso, se a parte imaginária é tida como zero, então tanto a multiplicação quanto a adição terão o padrão de números reais.
Verifica-se, portanto, que a aritmética dos números complexos contempla as premissas que a aritmética que os números reais consideram, sendo possível representar os números reais e complexos em um plano cartesiano complexo, tendo o eixo x representando os valores reais e o eixo y representando os números imaginários.

Uma vez que se identifica o plano de números reais juntamente com números imaginários, é possível verificar a exata localização de um número complexo.
Por exemplo, o número complexo (2+√(-4) ) pode ser representado por: 2+√((4) x (-1)), ou ainda, 2+√4 x √(-1), que por sua vez, se transforma em 2 + 2√(-1), ou 2+2i.
No plano complexo, esse número estaria localizado na seguinte posição

Dito isto, para encontrar o conjunto de mandelbrot, utiliza-se a função iterativa Zn=Z(n-1)^2+C (onde C representa um número complexo qualquer) para identificar quais números, dentro do plano complexo, não diverge para o infinito, ou seja, não cresce exponencialmente.
Especificando a equação, vale ressaltar que o número complexo C é dado como fixo, e se repete a cada iteração, conforme o exemplo abaixo, simbolizado por vermelho.
Por exemplo, se selecionarmos o ponto acima indicado, 2+2i, então teríamos os seguintes resultados:
Zn=Z(n-1)^2+C
Para Z0 = 0
Para Z1= 0^2+ (2+2i) = 2+ 2i
Para Z2 = 〖(2+2i)〗^2 +(2+ 2i) = 2 + 10 i
Para Z3 = 〖( 2 + 10i ) 〗^2 + (2+2i) = (-94 + 42i )
Para Z_4= 〖(-94 + 42i)〗^2 + (2+2i) = (7.074 + 6.944i)
Verifica-se, portanto, que o número complexo (2+ 2i) não estaria dentro do conjunto de mandelbrot, pois seu comportamento na função Zn=Z(n-1)^2+C é dado por um aumento exponencial, não convergindo para dentro de uma fronteira.
Diante disso, na medida em que as iterações são feitas, verifica-se que os numeros que não se dispersam para o infinito vão sendo concetrados em em regiões específicas, conforme os números subsequentes de iterações abaixo:

Benoit Mandelbrot foi o matemático francês de origem polonesa que primeiramente estudou a fundo a função Zn=Z(n-1)^2+C , utilizando mecanismos computacionais (FLAKE, 1998).
Números entre -2 e 1 não irão dispersar de forma exponencial. Números positivos menores do que 1 aumentarão, mas em tamanhos cada vez menores,tendendo à convergência.
Já em relação aos números negativos entre -2 e 0 as regras de multiplicação e elevação ao quadrado resultarem números positivos e de adição de um número negativo resultar em uma subtração, trabalham uma contra a outra, tornando os ganhos de adição cada vez menores a cada iteração.
Para representar essa estrutura na forma de programação orientada a objeto é preciso atribuir à classe os atributos específicos que envolverão o cálculo do mandelbrot set.
A primeira coisa a fazer é importação do pacote numpy, pacote básico da linguagem Python que nos permite trabalhar com matrizes de N dimensões.
A função @autojit do pacote Numba é utilizado para dar agilidade no cálculo, uma vez que inúmeras simulações são realizadas com infinitas soluções. Além disso, a biblioteca matplotlib.pyplot possibilita a plotagem do resultado.
import numpy
from numba import autojit
import matplotlib.pyplot as plt
Em seguida é necessário definir os argumentos da função “m-set”, neste caso foram são definidos três atributos, a saber: Re, Im e iter_max. Este último faz referência ao limite máximo de iterações (repetições).
Após a criação da função m-set, denominamos c e z, as variáveis que irão compor a função na sequência.
@autojit
def m-set (Re, Im, inter_max):
c = complex (Re, Im)
z = 0
O método é definido a partir da função base do conjunto m-set, definindo um processo recursivo.
for i in range (max_inter):
z = z*z + c
if (z.real*z.real + z.imag*z.imag) >= 4:
return i
return max_inter
Em seguida, após a definição de um array que armazena o resultado do teste em cada ponto do plano complexo(2.000 pontos para cada eixo).
Columns = 2000
Rows = 2000
Result = numpy.zeros([rows, columns])
O código dispõe de um looping que percorre o espaço real ( do intervalo -2 a 1)
E um outro looping, que percorre os 2.000 pontos da parte imaginária do ponto -1.0 a 1.0
for row_index, Re in enumerate(numpy.linspace(-2, 1, num=rows)):
for column_index, Im in enumerate (numpy.linspace(-1, 1, num=columns)):
A função m-set calcula, então, se o ponto definido dentro de cada looping pertence ou não ao conjunto de mandelbrot.
O resultado dessa função é estocado na array abaixo:
result[row_index, column_index] = mset(Re, Im, 100)
Onde 200 neste caso determina o número de iterações necessárias para que o ponto esteja dentro do conjunto. Sendo assim, na medida em que o número de iterações aumenta, a figura vai tomando forma gradativamente, conforme demonstrado anteriormente na figura 1.
result[row_index, column_index] = mset(Re, Im, 200)
Os resultados são plotados pelos comandos subsequentes, o 100 representa a dimensão da figura impressa na tela, o cmap representa o estilo da coloração da figura, interpolation o tipo de interpolação, e o plano onde a figura estará localizada.
plt.figure(dpi=100) ,
plt.imshow(result.T, cmap='hot', interpolation='bessel', extent=[-2, 1, -1, 1]),
Assim, definindo abaixo os rótulos dos eixos, solicita-se a plotagem:
plt.xlabel('Real')
plt.ylabel('Imaginário')
plt.show()
O código completo é o que segue:
import numpy
from numba import autojit
import matplotlib.pyplot as plt
@autojit
def mset (Re, Im, max_inter):
c = complex (Re, Im)
z = 0
for i in range (max_inter):
z = z*z + c
if (z.real*z.real + z.imag*z.imag) >= 4:
return i
return max_inter
#resolução da imagem
columns = 200
rows = 200
result = numpy.zeros([rows, columns])
for row_index, Re in enumerate(numpy.linspace(-2, 1, num=rows)):
for column_index, Im in enumerate (numpy.linspace(-1, 1, num=columns)):
result[row_index, column_index] = mset(Re, Im, 100)
plt.figure(dpi=100)
plt.imshow(result.T, cmap='hot', interpolation='bessel', extent=[-2, 1, -1, 1])
plt.xlabel('Real')
plt.ylabel('Imaginário')
plt.show()
Referência:
Flake, G. W. (1998). The Computational Beauty of Nature: Computer Explorations of Fractals, Chaos. Complex Systems, and Adaptation. MIT Press.