def energyProof() :
fig = plt.figure(figsize = (9, 6))
ax = fig.add_subplot(xlim = (-1.65, 1.65),
ylim = (-1, 1.2))
#Clear axes.
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["bottom"].set_visible(False)
ax.spines["left"].set_visible(False)
ax.set_xticks([])
ax.set_yticks([])
#Legs.
ax.plot([-1.6, -1.6, 1.6, 1.6],
[-0.9, 1, 1, -0.9],
color = '#55C667FF',
lw = 5)
#Energies.
ax.plot([-1.6, -0.3, 1.6],
[-0.9, 1, -0.9],
color = '#2D708EFF',
lw = 5)
#Particles.
ax.scatter([-1.6, -0.3, 1.6],
[-0.9, 1, -0.9],
color = '#440154FF',
lw = 10,
zorder = 2)
text = [("b", (-1.61, 0.05), '#55C667FF', 'right', 'center', 90),
("b", (1.61, 0.05), '#55C667FF', 'left', 'center', 270),
("a-x", (-0.95, 1.02), '#55C667FF', 'center', 'bottom', 0),
("a+x", (0.65, 1.02), '#55C667FF', 'center', 'bottom', 0),
("√((a-x)² + b²)", (-0.85, 0.4), '#2D708EFF', 'center', 'top', 53),
("√((a+x)² + b²)", (0.53, 0.38), '#2D708EFF', 'center', 'top', 317)]
for t in text :
plt.annotate(text = t[0],
xy = t[1],
c = t[2],
size = 20,
ha = t[3],
va = t[4],
rotation = t[5])
fig.savefig("2024.12.06-0.png", bbox_inches = 'tight')
#Creates:
#bottom - list of all n points from (0, 0)...(j/n, 0)...(1, 0).
#top - list of all n points from (0, 1)...(j/n, 1)...(1, 1).
#left - list of all n points from (0, 0)...(0, k/n)...(0, 1).
#right - list of all n points from (1, 0)...(1, k/n)...(1, 1).
#points - list of all n^2 points in nxn array from (0, 0)...(j/n, k/n)...(1, 1).
def createPoints(n) :
#n+1 number from 0 to 1.
base = [i/n for i in range(n+1)]
#Points along bottom/top/left/right of square.
bottom = []
top = []
left = []
right = []
#All points in square lattice, including border points(above)
points = []
for x in base :
bottom.append((x, 0))
top.append((x, 1))
left.append((0, x))
right.append((1, x))
for y in base :
points.append((x, y))
return(bottom, top, left, right, points)
#Given two points, return the energy, the reciprocal of distance between points.
def energyCalc(a, b) :
return(1 / sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2))
#Given a list of particles, determines the next particle to add to minimize energy.
def nextParticle(particles, prev_energy, points) :
min_energy = float('inf')
for n in points :
if n in (particles) :
next
else :
energy = 0
for p in particles :
energy += energyCalc(n, p)
if energy < min_energy :
min_location = n
min_energy = energy
return(particles + [min_location],
prev_energy + min_energy)
def get(n, option) :
#Updates energy and location by calculating that of the current particles.
def totalEnergyUpdate(n, location, min_location, min_energy) :
#Make sure particles are unique.
if len(set(location)) < n:
return(min_location, min_energy)
else :
energy = 0
#All p(p-1)/2 distances
for i in range(n-1) :
for j in range(i+1, n) :
a = location[i]
b = location[j]
energy += energyCalc(a, b)
if energy < min_energy :
min_location = location
min_energy = energy
return(min_location, min_energy)
#Setup
z = 200
raw = createPoints(z)
bottom, top, left, right, points = raw[0], raw[1], raw[2], raw[3], raw[4]
min_location = [0, 0]*n
min_energy = float('inf')
p1 = (0, 0)
if option == '3A' :
p2 = (2-sqrt(3), 1)
p3 = (1, 2-sqrt(3))
location = [p1, p2, p3]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '5B' :
p1 = (0.5, 0)
for i in range(z+1) :
p2 = right[i]
p5 = left[i]
for j in range(z+1) :
p3 = top[z-j]
p4 = top[j]
location = [p1, p2, p3, p4, p5]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '5C' :
p2 = (1, 0)
p5 = (0, 1)
for i in range(6296, 6316) :
p3 = (1, i/10000)
p4 = (i/10000, 1)
location = [p1, p2, p3, p4, p5]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '6D' :
p4 = (1, 1)
for i in range(6600, 6620) :
p2 = (i/10000, 0)
p3 = (1, 1-i/10000)
p5 = (1-i/10000, 1)
p6 =(0, i/10000)
location = [p1, p2, p3, p4, p5, p6]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '6E' :
location = [(0, 0), (1, 0), (1, 0.5), (1, 1), (0, 1), (0, 0.5)]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '7F' :
p1 = (0.5, 0)
for i in range(int(z/5)) :
p2 = (1-i/z, 0)
p7 = (i/z, 0)
for j in range(5420, 5440) :
p3 = (1, j/10000)
p6 = (0, j/10000)
for k in range(int(z/2)) :
p4 = (1-k/z, 1)
p5 = (k/z, 1)
location = [p1, p2, p3, p4, p5, p6, p7]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '7G' :
for i in range(5150, 5250) :
p2 = (i/10000, 0)
p7 = (0, i/10000)
for j in range(int(z/3)) :
p3 = (1, j/z)
p6 = (j/z, 1)
for k in range(6750, 6850) :
p4 = (1, k/10000)
p5 = (k/10000, 1)
location = [p1, p2, p3, p4, p5, p6, p7]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '8H' :
location = [(0, 0), (0.5, 0), (1, 0), (1, 0.5),
(1, 1), (0.5, 1), (0, 1), (0, 0.5)]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '9I' :
p1 = (0.5, 0)
for i in range(1) :
p2 = (1-i, 0)
p9 = (i, 0)
for j in range(4520, 4540) :
p3 = (1, j/10000)
p8 = (0, j/10000)
for k in range(1,2) :
p4 = (1, k)
p7 = (0, k)
for l in range(3180, 3200) :
p5 = (1-l/10000, 1)
p6 = (l/10000, 1)
location = [p1, p2, p3, p4, p5, p6, p7, p8, p9]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
elif option == '9J' :
for i in range(465, 485) :
p2 = (i/1000, 0)
p9 = (0, i/1000)
for j in range(977, 997) :
p3 = (j/1000, 0)
p8 = (0, j/1000)
for k in range(352, 372) :
p4 = (1, k/1000)
p7 = (k/1000, 1)
for l in range(777, 797) :
p5 = (1, l/1000)
p6 = (l/1000, 1)
location = [p1, p2, p3, p4, p5, p6, p7, p8, p9]
min_location, min_energy = totalEnergyUpdate(n, location, min_location, min_energy)
return(min_location, min_energy)
def particleEnergy(particles, energy, option) :
p_num = str(len(particles))
if option == 'Min' :
title = 'Min. Energy'
else :
title = 'Alternative'
x_values = [x for x, _ in particles]
y_values = [y for _, y in particles]
fig = plt.figure(figsize = (9, 6))
ax = fig.add_subplot(xlim = (-0.1, 1.8),
ylim = (-0.1, 1.1))
#Title setup.
ax.set_title(title + ' Arrangement of ' + p_num + ' Particles', fontsize = 24)
#Clear axes.
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["bottom"].set_visible(False)
ax.spines["left"].set_visible(False)
ax.set_xticks([])
ax.set_yticks([])
#Square.
ax.add_patch(mpR(xy = (0, 0),
width = 1,
height = 1,
ec = '#55C667FF',
fill = False,
lw = 3))
#Particles.
ax.scatter(x_values,
y_values,
color = '#440154FF',
lw = 10)
#Annotate.
for p in particles :
text = str(p)
x = p[0]
y = p[1]
xy = ((x-0.5)*0.92 + 0.5, (y-0.5)*1.08 + 0.5)
ha = 'center'
va = 'center'
if y == 0 :
va = 'top'
elif y in [0.996, 1] :
va = 'bottom'
else :
xy = ((x-0.5)*0.92 + 0.5, y)
if x == 0 :
ha = 'left'
elif x == 1 :
ha = 'right'
if (x, y) == (0.5, 0.5) :
xy = (0.5, 0.58)
if x == 2 - sqrt(3) :
text = '(2-√3, ' + str(y) + ')'
elif y == 2 - sqrt(3) :
text = '(' + str(x) + ', 2-√3)'
plt.annotate(text = text,
xy = xy,
c = '#440154FF',
size = 16,
ha = ha,
va = va)
plt.annotate(text = 'Total Energy :',
xy = (1.79, 0.97),
c = '#2D708EFF',
size = 24,
ha = 'right',
va = 'center')
plt.annotate(text = str(round(energy, 4)),
xy = (1.79, 0.85),
c = '#2D708EFF',
size = 24,
ha = 'right',
va = 'center')
fig.savefig("2024.12.06-" + p_num + option + ".png", bbox_inches = 'tight')