Chaos theory is a branch of mathematics focusing on the behavior of dynamical systems that are highly sensitive to initial conditions. "Chaos" is an interdisciplinary theory stating that within the apparent randomness of chaotic complex systems, there are underlying patterns, constant feedback loops, repetition, self-similarity, fractals, self-organization, and reliance on programming at the initial point known as sensitive dependence on initial conditions. [1]
# Load the Python libraries
import numpy as np
from collections import Counter
from numpy import complex, array
# Load plotting libraries
import matplotlib.pyplot as plt
from PIL import Image
import colorsys
# This function gets a random number from a uniform distribution between the two input values [min_value, max_value] inclusively
def get_random_number(min_value, max_value):
range = max_value - min_value
num = np.random.uniform(0, 1)
return min_value + range * num
# Function that creates a series of numbers using chaos theory
def get_chaos_list(seed, n):
numList = []
k = 3.9976543219876543210
x = seed
for i in range(n):
x = x * k * (1 - x)
numList += [x]
# Return x and y
return np.arange(len(numList)), numList
# Function that plot a (x, y) series of points
def plot_line_chart(x, y, x_label, y_label, title):
plt.figure(figsize = (16, 4))
plt.plot(x, y, label = y_label)
plt.xlabel(x_label, fontsize = 11)
plt.ylabel(y_label, fontsize = 11)
plt.title(title, size=14)
plt.legend(loc = 'upper right')
plt.show()
# Create and plot 100 random-chaos numbers
seed = get_random_number(0, 1)
x, y = get_chaos_list(seed, 100)
plot_line_chart(x, y, '$x$', '$chaos(x)$', 'Numbers created with the Chaos Function')
# Create 3 different seeds
gap = 1.00000001
seeds = []
seeds.append(get_random_number(0, 1))
seeds.append(seeds[len(seeds) - 1] * gap)
seeds.append(seeds[len(seeds) - 1] * gap)
seeds
[0.02194082139898834, 0.021940821618396555, 0.02194082183780477]
# Get 3 different chaos results
max_iter = 100
x1, y1 = get_chaos_list(seeds[0], max_iter)
x2, y2 = get_chaos_list(seeds[1], max_iter)
x3, y3 = get_chaos_list(seeds[2], max_iter)
# Plot multi-lines chart
x_label = '$x$'
y_label = '$chaos(x)$'
title = 'Numbers created with the Chaos Function'
plt.figure(figsize = (16, 8))
plt.plot(x1, y1, label = 'chaos(x1)')
plt.plot(x2, y2, label = 'chaos(x2)')
plt.plot(x3, y3, label = 'chaos(x3)')
plt.xlabel(x_label, fontsize = 11)
plt.ylabel(y_label, fontsize = 11)
plt.title(title, size=14)
plt.legend(loc = 'upper right')
plt.show()
It can be seen how a small variation in its initial conditions produces completely different results.
In the example above approximately from iteration number 25.
In the mathematical field of dynamical systems, an attractor is a set of numerical values toward which a system tends to evolve, for a wide variety of starting conditions of the system. System values that get close enough to the attractor values remain close even if slightly disturbed. [2]
# Finds and returns a list of attractors
def find_attractors(data, tolerance=10.0):
attractors = []
n = len(data)
if n > 0:
value, freq = data[0]
init_freq = freq
# Find best attractors
for i in range(0, n):
value, freq = data[i]
if freq > 0 and abs(init_freq - freq) / freq < tolerance:
attractors.append(value)
else:
break
return attractors
# Generate chaotic system data for r
solution = {}
k = 0.1
max_r = 4.0
n = 1000
precision = 2
while k <= max_r:
x = 0.5
data = []
for i in range(n):
x = x * k * (1 - x)
data.append(round(x, precision))
key = round(k, 2)
solution[key] = Counter(data).most_common()
k += 0.001
# Plot chaotic system result
plt.figure(figsize = (16, 9))
for k, v in solution.items():
y = find_attractors(v, 7)
x = [k] * len(y)
plt.plot(x, y, '.k')
plt.title("Chaotic Systems with Attractors", size=14)
plt.xlabel("k", fontsize=11)
plt.ylabel("x", fontsize=11)
plt.xlim(2, 4.0)
plt.show()
In mathematics, a fractal is a subset of a Euclidean space for which the Hausdorff dimension strictly exceeds the topological dimension. Fractals tend to appear nearly the same at different levels, as is illustrated here in the successively small magnifications of the Mandelbrot set; because of this, fractals are encountered ubiquitously in nature
Fractals exhibit similar patterns at increasingly small scales called self similarity, also known as expanding symmetry or unfolding symmetry; if this replication is exactly the same at every scale, as in the Menger sponge, it is called affine self-similar. Fractal geometry lies within the mathematical branch of topology. [3]
Properties:
The Sierpinski triangle, also called the Sierpinski gasket or Sierpinski sieve, is a fractal and attractive fixed set with the overall shape of an equilateral triangle, subdivided recursively into smaller equilateral triangles. Originally constructed as a curve, this is one of the basic examples of self-similar sets–that is, it is a mathematically generated pattern that is reproducible at any magnification or reduction. [4]
# Setting the width and height of the image to be created
WIDTH, HEIGHT = 1028, 512
# Rule: bin(90) = 01011010
rule = {'000': 0, '001': 1, '010': 0, '011': 1, '100': 1, '101': 0, '110': 1, '111': 0}
rule
{'000': 0, '001': 1, '010': 0, '011': 1, '100': 1, '101': 0, '110': 1, '111': 0}
# Creating Koch snowflake image
def sierpinski_triangle():
# Color list
c_gold = (212,175,55)
c_black = (0, 0, 0)
# Creating the new image in RGB mode
fractal = Image.new('RGB', (WIDTH, HEIGHT), "white")
pixels = fractal.load()
pixels[WIDTH // 2, 0] = c_gold
# The logic of cellular automata is used (see chapter 8)
for y in range(1, HEIGHT):
for x in range(0, WIDTH):
ix_start = x - 1
ix_end = x + 1
gen = ''
for i in range(ix_start, ix_end + 1):
ix = i % WIDTH
gen += str('1' if pixels[ix, y - 1] == c_gold else '0')
cell = rule[gen]
pixels[x, y] = c_gold if cell == 1 else c_black
return fractal
# Drawing Koch snowflake
sierpinski_triangle()
# Setting the width, height and zoom of the image to be created
WIDTH, HEIGHT, ZOOM = 1920, 1080, 1
# Creating Julia fractal image
def create_julia_fractal():
# Creating the new image in RGB mode
fractal = Image.new("RGB", (WIDTH, HEIGHT), "white")
pixels = fractal.load()
# Setting up the variables according to the equation to create the fractal
cX, cY = -0.7, 0.27015
move_x, move_y = 0.0, 0.0
max_iter = 255
for x in range(WIDTH):
for y in range(HEIGHT):
zx = 1.5 * (x - WIDTH / 2) / (0.5 * ZOOM * WIDTH) + move_x
zy = 1.0 * (y - HEIGHT / 2) / (0.5 * ZOOM * HEIGHT) + move_y
i = max_iter
while zx * zx + zy * zy < 4 and i > 1:
tmp = zx * zx - zy * zy + cX
zy, zx = 2.0 * zx * zy + cY, tmp
i -= 1
# Convert byte to RGB (3 bytes), kinda magic to get nice colors
pixels[x, y] = (i << 11) + (i << 18) + i * 8
return fractal
# Drawing Julia fractal
create_julia_fractal()
The Mandelbrot set is the set of complex numbers $c$ for which the function $ f_{c}(z)=z^{2}+c $ does not diverge when iterated from $ z=0 $, i.e., for which the sequence $ f_{c}(0), f_{c}(f_{c}(0)) $, etc., remains bounded in absolute value. [5]
# Setting the width and height of the image to be created
WIDTH, HEIGHT = 1024, 512
# Function that return a tuple of colors as integer value of rgb
def rgb_conv(i):
color = 255 * array(colorsys.hsv_to_rgb(i / 55.0, 1.0, 0.5))
return tuple(color.astype(int))
# Function defining a mandelbrot
def mandelbrot(x, y):
c0 = complex(x, y)
c = 0
for i in range(1, 1000):
if abs(c) > 2:
return rgb_conv(i)
c = c * c + c0
return (0, 0, 0)
# Creating mandelbrot fractal image
def create_mandelbrot_fractal():
# Creating the new image in RGB mode
fractal = Image.new('RGB', (WIDTH, HEIGHT), "white")
pixels = fractal.load()
for x in range(WIDTH):
for y in range(HEIGHT):
pixels[x, y] = mandelbrot((x - (0.75 * WIDTH)) / (WIDTH / 4), (y - (WIDTH / 4)) / (WIDTH / 4))
return fractal
# Drawing Mandelbrot fractal
create_mandelbrot_fractal()