The concept of free will and predestination is a topic of philosophical debate. In the short term, individuals have the freedom to make choices and decisions in their daily lives. This aligns with the belief that individuals are responsible for their actions and will be judged accordingly. However, in the long term, some believe that ultimate fate and the broader events of life are predestined by a higher power or the laws of nature. This duality emphasizes the balance between free will and determinism, suggesting that while humans can make choices, their lives may unfold according to a predetermined plan.
This concept is analogous to the process in the code above. While the initial point P and the choice of vertices (A, B, or C) at each step are random (representing free will), the overall pattern that emerges after many iterations is a deterministic fractal (representing predestination). Despite the freedom in individual choices, the final result is a predictable and beautiful Sierpinski triangle, illustrating the balance between randomness and order.
This randomness game code:
`import matplotlib.pyplot as plt import numpy as np
Function to rotate a point by a certain angle def rotate_point(p, angle): rotation_matrix = np.array([[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]]) return np.dot(rotation_matrix, p)
Set the side length of the equilateral triangle side_length = 2
Define the three points of the equilateral triangle A = np.array([0, 0]) B = np.array([side_length, 0]) angle = np.pi / 3 # 60 degrees C = rotate_point(B, angle)
Initialize the starting point randomly P = np.random.rand(2) * 3 # Random starting point within a larger area
Function to move to the midpoint of a chosen vertex def move_to_midpoint(P, target): return (P + target) / 2
Set up the figure for plotting plt.figure(figsize=(6, 6)) plt.xlim(0, 3) plt.ylim(0, 3) plt.gca().set_aspect('equal', adjustable='box')
Plot the equilateral triangle triangle_x = [A[0], B[0], C[0], A[0]] triangle_y = [A[1], B[1], C[1], A[1]] plt.plot(triangle_x, triangle_y, color='black')
Perform the process of moving halfway to the selected vertex iterations = 100000 points = []
vertices = np.array([A, B, C]) # Create a 2D array of vertices
for _ in range(iterations): roll = vertices[np.random.choice(len(vertices))] # Randomly choose between A, B, and C P = move_to_midpoint(P, roll) points.append(P)
Convert points list to numpy array for easy indexing points = np.array(points)
Plot the points after discarding the first 50 plt.scatter(points[50:, 0], points[50:, 1], color='blue', s=0.1)
Show the plot plt.show()`
import matplotlib.pyplot as plt
import numpy as np
# Function to rotate a point by a certain angle
def rotate_point(p, angle):
rotation_matrix = np.array([[np.cos(angle), -np.sin(angle)],
[np.sin(angle), np.cos(angle)]])
return np.dot(rotation_matrix, p)
# Set the side length of the equilateral triangle
side_length = 2
# Define the three points of the equilateral triangle
A = np.array([0, 0])
B = np.array([side_length, 0])
angle = np.pi / 3 # 60 degrees
C = rotate_point(B, angle)
# Initialize the starting point randomly
P = np.random.rand(2) * 3 # Random starting point within a larger area
# Function to move to the midpoint of a chosen vertex
def move_to_midpoint(P, target):
return (P + target) / 2
# Set up the figure for plotting
plt.figure(figsize=(6, 6))
plt.xlim(0, 3)
plt.ylim(0, 3)
plt.gca().set_aspect('equal', adjustable='box')
# Plot the equilateral triangle
triangle_x = [A[0], B[0], C[0], A[0]]
triangle_y = [A[1], B[1], C[1], A[1]]
plt.plot(triangle_x, triangle_y, color='black')
# Perform the process of moving halfway to the selected vertex
iterations = 100000
points = []
vertices = np.array([A, B, C]) # Create a 2D array of vertices
for _ in range(iterations):
roll = vertices[np.random.choice(len(vertices))] # Randomly choose between A, B, and C
P = move_to_midpoint(P, roll)
points.append(P)
# Convert points list to numpy array for easy indexing
points = np.array(points)
# Plot the points after discarding the first 50
plt.scatter(points[50:, 0], points[50:, 1], color='blue', s=0.1)
# Show the plot
plt.show()A beautiful 3D version of it:
import plotly.graph_objects as go
import numpy as np
# Function to rotate a point around the Z-axis by a certain angle
def rotate_point_z(p, angle):
rotation_matrix = np.array([[np.cos(angle), -np.sin(angle), 0],
[np.sin(angle), np.cos(angle), 0],
[0, 0, 1]])
return np.dot(rotation_matrix, p)
# Set the side length of the equilateral triangle base
side_length = 2
# Define the three base points of the equilateral triangle
A = np.array([0, 0, 0])
B = np.array([side_length, 0, 0])
angle = np.pi / 3 # 60 degrees
C = rotate_point_z(B, angle)
# Define the apex of the pyramid
D = np.array([side_length / 2, np.sqrt(3) / 2 * side_length / 2, np.sqrt(2) * side_length])
# Initialize the starting point randomly
P = np.random.rand(3) * 3 # Random starting point within a larger area
# Function to move to the midpoint of a chosen vertex
def move_to_midpoint(P, target):
return (P + target) / 2
# Perform the process of moving halfway to the selected vertex
iterations = 149000
points = []
vertices = np.array([A, B, C, D]) # Create a 2D array of vertices
for _ in range(iterations):
roll = vertices[np.random.choice(len(vertices))] # Randomly choose between A, B, C, and D
P = move_to_midpoint(P, roll)
points.append(P)
# Convert points list to numpy array for easy indexing
points = np.array(points)
# Create the plotly figure
fig = go.Figure()
# Plot the base of the pyramid
fig.add_trace(go.Scatter3d(x=[A[0], B[0], C[0], A[0]],
y=[A[1], B[1], C[1], A[1]],
z=[A[2], B[2], C[2], A[2]],
mode='lines',
line=dict(color='black')))
# Plot the sides of the pyramid
fig.add_trace(go.Scatter3d(x=[A[0], D[0]], y=[A[1], D[1]], z=[A[2], D[2]], mode='lines', line=dict(color='black')))
fig.add_trace(go.Scatter3d(x=[B[0], D[0]], y=[B[1], D[1]], z=[B[2], D[2]], mode='lines', line=dict(color='black')))
fig.add_trace(go.Scatter3d(x=[C[0], D[0]], y=[C[1], D[1]], z=[C[2], D[2]], mode='lines', line=dict(color='black')))
# Plot the points after discarding the first 50
fig.add_trace(go.Scatter3d(x=points[50:, 0], y=points[50:, 1], z=points[50:, 2],
mode='markers',
marker=dict(color='blue', size=1)))
# Update layout for better visualization
fig.update_layout(scene=dict(aspectmode='data'),
title='3D Pyramid with Plotly',
scene_aspectmode='cube')
# Show the plot
fig.show()