Выбрать главу

Можно увеличив количество итераций и размер картинки, убедиться что шаблон повторяется.

Может возникнуть вопрос, как длина линии может быть бесконечной при конечной длине. Примерной аналогией может быть сумма ряда:

S = 0.9 + 0.09 + 0.009 + …

Как нетрудно догадаться, сам по себе ряд бесконечный, но его сумма стремится ко вполне определенному числу 0.999999… = 1.

“Снежинка Коха” интересна своей простотой, но есть и более сложные варианты фракталов. Рассмотрим множество Мандельброта, которое строится по следующему алгоритму: для каждой точки c=x + j*y на комплексной плоскости, эта точка попадает в множество при условии что ряд Zn+1 = Zn2 + c не расходится при z0 = 0.

Рассмотрим пример.

При c = (0,0) = 0 + 0j, ряд очевидно, всегда равен нулю, т.е. не расходится, значит точка (0,0) попадает в множество.

При с = (0.5, 0.5) = 0.5 + 0.5j, получаем следующие значения:

Z0 = 0

Z1 = Z0 + c = 0.5+0.5j

Z2 = Z1 + c = 0.5+1j

Z3 = Z2 + c = -0.25+1.5j

Z4 = Z3 + c = -1.6875-0.25j

Z5 = Z4 + c = 3.28515625+1.34375j

Z6 = Z5 + c = 9.48658752+9.32885j

Легко видеть, что ряд расходящийся, числа увеличиваются, значит (0.5, 0.5) не попадает в множество.

При с = (0.25, 0.25) = 0.25 + 0.25j, имеем следующий ряд:

Z0 = 0

Z1 = Z0 + c = 0.25+0.25j

      Z2 = Z1 + c = 0.25+0.375j

      Z3 = Z2 + c = 0.171875+0.4375j

      Z4 = Z3 + c = 0.088134+0.400390625j

      Z5 = Z4 + c = 0.09745508+0.32057666j

      Z6 = Z5 + c = 0.15672809+0.31248365j

Z7 = Z6 + c = 0.17691766+0.34794993j

      Z8 = Z7 + c = 0.160230+0.37311697j

      Z9 = Z8 + c = 0.1364575+0.36956959j

Как можно видеть, ряд не расходится, т.е. точка (0.25, 0.25) попадает в множество.

Разумеется, вручную делать такие проверки было бы крайне неудобно, собственно это одна из основных причин, по которой фракталы не были известны до появления компьютеров. Чтобы заметить какие-либо закономерности фрактальной природы, необходима возможность их автоматического рисования. Кстати, сам Мандельброт работал в IBM и имел доступ к весьма мощным компьютерам своего времени.

На языке Python проверку попадания точки в множество легко записать в виде функции. Для нас удобно то, что Python умеет работать с комплексными числами, что делает запись кода более короткой.

Сама функция имеет следующий вид:

def countMandelbrotIterationsForPt(pt):

z = 0

c = pt

threshold = 64

for iteration in xrange(threshold):

z = z*z + c

if abs(z) > 4:

break

return iteration

Здесь вычисляется 64 итерации, которых вполне достаточно чтобы определить, является ли ряд расходящимся или нет.

Чтобы сохранить весь фрактал, нужно перебрать все точки в диапазоне [-2, 2], программа, сохраняющая фрактал в файл, приведена ниже:

from PIL import Image

points = 1000

img = Image.new('RGB', (2*points,2*points), "black")

pixels = img.load()

# Range.X: -2..2,

# Range.Y: -2..2

for ix in xrange(-points, points, 1):

for iy in xrange(-points, points, 1):

pt = complex(2.0*ix/points, 2.0*iy/points)

i = countMandelbrotIterationsForPt(pt)

if i > 16:

colR, colG, colB = 4*i, 4*i, 0

if colR >= 255: colR = 255

if colB >= 255: colB = 255

if colB >= 255: colB = 255

img_x = points + ix

img_y = points + iy

pixels[img_x, img_y] = (colR, colG, colB)

if ix % 10 is 0:

print "Done: {}%".format(100.0*(ix + points)/(2*points))

img.save("fractal.png")

Как можно видеть, программа содержит 2 вложенных цикла ix, iy, затем значение преобразуются в комплексное число, для которого и выполняется описанная выше функция проверки.

Результат выполнения программы для 1000 точек, показан на рисунке:

Если в несколько раз увеличить количество точек, можно увидеть структуру верхней части более детально:

Немного изменив формулу, можно получить другие виды фракталов. Например, множество Жюлиа, описывается также, но Z0 = pt, и c = const. Казалось бы, небольшое отличие, приводит к совершенно другому рисунку фрактала:

Кстати, этот рисунок напоминает сорт цветной капусты “Романеско”:

Наконец, если в формуле фрактала Мандельброта Zn+1 = Zn2 + c, вычислять абсолютное значение Z*Z в виде (|a| + j|b|)*(|a| + j|b|), мы получим фрактал с названием “горящий корабль”:

Сложно сказать, насколько форма напоминает корабль, верхняя часть под увеличением скорее напоминает береговую линию, видимую с высоты: