Saturday, May 17, 2025

Euclid, Fermat, and the 65537 Reasons We Have Never Drawn Their Last Shape

 1. Straight Edge and Compass Euclidean Constructions

From the time of ancient Greece, geometers have been fascinated by what can be built using only two tools: a compass and a straightedge. These "Euclidean constructions" formed the foundation of classical geometry. You can copy a line segment, bisect an angle, draw perpendiculars Euclid's Elements are full of constructions and theorems that are built from these two tools.

But some polygons cannot be drawn this way. A regular 7-gon is impossible. Why? Because the set of constructible polygons is tied deeply to number theory, to Fermat primes.

2. Fermat Primes and Drawing Them

A Fermat prime is a prime number of the form


Only five such primes are known: 351725765537

Carl Friedrich Gauss at age 19 by proved that a regular polygon with sides is constructible if and only if is a product of a power of 2 and distinct Fermat primes. This means a regular 65537-gon is theoretically constructible.

One mathematician actually attempted to do it. Johann Gustav Hermes spent over a decade and 200 pages , detailing how to construct a 65537-gon using Euclidean methods in Ueber die Teilung des Kreises in 65537 gleiche Teile  in 1894. 

3. The 65537-gon

If you tried to actually draw a 65537-gon on a circle the size of the Earth (with of 6,371 km), each side would be approximately 611 meters long. Which means on a flat lake one side of the 65537-gon would not follow the earth's curvature by 3cm. A 65537-gon would be 3cm per 611 meter side off being a perfect circle. 

No one has ever made a by hand 65537-gon because it would just be too involved. though Hermes did spend ten years working out how it could be done in principle.


A 65537-gon (not a circle)


4. A Machine to Draw It for Us?

Could we build a machine that uses only a compass and a straightedge, like Euclid himself? Plotters could draw the 65537-gon by calculating angles and coordinates, but Euclid has famously tough lawyers and anyone making his shape not using his methods is likely to be mired in law suits




Such a Euclid Geometry machine would have to:

  • Set distances using a mechanical compass

  • Draw arcs

  • Align a straightedge through marked points

  • Draw straight lines with a pen

  • Combine these steps tens of thousands of times

It would follow the ancient Greek rules of construction.

This would be rock hard to make and not practically useful. It would involve, aligning a  ruler through two points. Resetting a compass to exactly the distance between two previous marks, which is mechanically fiddly. Detecting intersections and points on paper. All of this is simple for Ancient Greek humans but not for machines.

And yet, it would be beautiful. It would make visible not just the result of geometric thinking, but the process. A Euclid-bot wouldn’t just draw geometry it would demonstrate it.



There are cool online geometry tools but something about plotters and physical drawing things still appeals. Maybe it would be possible to make a ruler and compass wielding machine that could finally draw the 65537 sides of the last Polygon.



Saturday, May 03, 2025

Shock as Ireland goes mainly solar

 

In the Summer of 2025 there will be shock reported when solar energy supplies the majority of the power to the grid. 

When utility-scale solar reached a record output of 719MW during the early afternoon on August 31, rooftop solar is also estimated to have reached a record high output of 399MW

Demand at that time was 4300MW.




This won't happen this year. but I think it will in 2026 and when it does people will 
1. Claim this is a surprise
2. Ask about what happens at night
3. Ask about what happens in winter (which is actually a reasonable question)

38% annual growth rates of solar means that it will go from 50% at noon on the sunniest day of the year to near 100% at 4pm on a good day in May in a few years.

Drawing the US flag

 

 What happens to the US Flag they add more States

They have always added more stars sincde the original 13 up to the current 50.
There has been talk of Puerto Rico and Washington DC being added for some time. And recently Trump has been talking about adding
 Panama Canadian and Greenland.

Python Code Works

Here is some code to make a flag. 
The line to change the number of stars on each line is

layout = [10, 10, 10, 10, 10, 10, 10, 10] #60

the code is here and it is based on this original article.

51 stars is a hot mess

I cant work out how to make this nice. Maye a circle layout can do it. 


52 Stars looks better 


60 stars









Friday, May 02, 2025

Let's make Bee honeycomb more natural

Honeycombs in nature are not entirely regular. In a 2016 study, Nazzi found that cell size variation in honeycomb averaged just 2.1%, with standard deviation across samples of ±0.6%. This highlights how remarkably consistent bees are — yet not perfectly so.

A little irregularity might actually help bees, by making the environment less predictable for their enemies

  • Mites might find entirely regular honeycombs easier to deal with
  • Entirely regular honeycombs might produce bees with less variety in sizes
    • This might make it easier for predators and parasites to specialise given less variance in the bees
    • It might slightly reduce the variety of foods bees eat


When we manage hives, we often insert wax foundation sheets embossed with perfect hexagons to guide the bees' construction. But maybe we shouldn’t.
Maybe our foundation should closely match the natural variation bees already produce. It might be a small change — but one that works with evolution, not against it.

Here’s the code I used to simulate a naturally varied honeycomb layout.




import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi
from shapely.geometry import Polygon, Point

def generate_jittered_hex_points(rows, cols, spacing=1.0, jitter=0.05):
"""Generate a grid of points in a hexagonal layout with jitter applied."""
points = []
h = np.sqrt(3) * spacing / 2 # vertical distance between rows
for row in range(rows):
for col in range(cols):
x = col * 1.5 * spacing
y = row * h * 2 + (h if col % 2 else 0)
# Add jitter
x += np.random.uniform(-jitter, jitter) * spacing
y += np.random.uniform(-jitter, jitter) * spacing
points.append((x, y))
return np.array(points)

def filtered_voronoi_polygons(vor, points, margin):
"""Return only Voronoi regions that are within the central margin area."""
regions = []
valid_polygon_centers = []
center_x = (np.max(points[:, 0]) + np.min(points[:, 0])) / 2
center_y = (np.max(points[:, 1]) + np.min(points[:, 1])) / 2
width = np.max(points[:, 0]) - np.min(points[:, 0])
height = np.max(points[:, 1]) - np.min(points[:, 1])

allowed_box = Polygon([
(center_x - width/2 + margin, center_y - height/2 + margin),
(center_x - width/2 + margin, center_y + height/2 - margin),
(center_x + width/2 - margin, center_y + height/2 - margin),
(center_x + width/2 - margin, center_y - height/2 + margin),
])

for point_idx, region_index in enumerate(vor.point_region):
region = vor.regions[region_index]
if not region or -1 in region:
continue
polygon = Polygon([vor.vertices[i] for i in region])
if allowed_box.contains(Point(points[point_idx])):
regions.append(polygon)
valid_polygon_centers.append(points[point_idx])
return regions

# Parameters
rows, cols = 20, 20
spacing = 1.0
jitter = 0.042 # to get an average of 2.1% jitter
points = generate_jittered_hex_points(rows, cols, spacing, jitter)

# Voronoi diagram
vor = Voronoi(points)

# Margin (in same units as spacing)
margin = spacing * 1.0 # Leave one cell of wax space around

# Get filtered polygons
filtered_polygons = filtered_voronoi_polygons(vor, points, margin)

# Plotting
fig, ax = plt.subplots(figsize=(10, 10))
ax.set_aspect('equal')
ax.axis('off')

for poly in filtered_polygons:
x, y = poly.exterior.xy
ax.plot(x, y, color='black', linewidth=0.5)

plt.savefig("jittered_voronoi_clean_edges.png", dpi=300, bbox_inches='tight', pad_inches=0)
plt.close()


As well as encouraging natural variation in cell size, I would also like to see foundation sheets reflect the natural tilt of honeycomb cells.
Bees build each cell with a slight upward slope, typically between 9 and 13 degrees, averaging around 9°

While bees in managed hives do seem to recreate this slope reliably on their own, adding a subtly varied tilt to the foundation embossing rather than a perfectly uniform angle. Mind you, since bees usually reproduce this slope, sloped embossing is likely less useful than capturing variation in cell size.

There's also a theory that a small number of undersized cells in the comb may help control Varroa mites. The idea is that bees raised in smaller cells hatch slightly earlier, disrupting the mites' reproductive cycle. While results from studies are mixed to negative, it's another reason to consider embracing natural variation, rather than enforcing a rigid cell size across the hive.


Thursday, May 01, 2025

Percy Ludgate: Early Computer Pioneer and his Irish Logarithms

 

Irish Logarithms are a multiplication method invented by Irishman Percy Ludgate in 1909. 

1. Why use Logarithms

a logarithm transforms multiplication into addition:
logb(xy)=logb(x)+logb(y)

By storing precomputed “log” values and then adding them, we reduce the hard part of multiplication to a single addition followed by a lookup (the inverse logarithm).

Classical log-based multiplication steps:

  1. Log lookup: retrieve and from a table.

  2. Add: compute .

  3. Anti-log lookup: retrieve from another table.


2. What Irish Logarithms involve 

To multiply two one digit numbers

table1 = [50, 0, 1, 7, 2, 23, 8, 33, 3, 14]

table2 = [ 1,  2,  4,  8, 16, 32, 64,  3,  6, 12, 
          24, 48,  0,  0,  9, 18, 36, 72,  0,  0, 
           0, 27, 54,  5, 10, 20, 40,  0, 81,  0, 
          15, 30,  0,  7, 14, 28, 56, 45,  0,  0, 
          21, 42,  0,  0,  0,  0, 25, 63,  0,  0, 
           0,  0,  0,  0,  0,  0, 35,  0,  0,  0, 
           0,  0,  0,  0,  0,  0, 49,  0,  0,  0, 
           0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
           0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
           0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
           0]

Lets say 4*5. Look up the 4th position in table 1. That is 2 (table starts at 0). and the 5th is 23. Add these together to get 25.
Now look up the 25th position in table 2 (the anti-log table) is 20. the right answer.

To do multi digit multiplication you do the multiplication of individual digits and then add them like in school. 

Ludgate worked out this logarithm and anti-logarithm mapping himself which in a pre computer time was a huge amount of effort.  As he wrote 'the result of about six years' work, undertaken . . . with the object of designing machinery capable of performing calculations, however, intricate or laborious, without the immediate guidance of the human intellect'

3. Who was Percy Ludgate

He was an Irish accountant and computer pioneer who invented the second ever design for a Turing complete computer. and one that was much more practical than Babbage's. But he never got the money needed to construct it.

Brian Coghlan has done a huge amount of research on Ludgate's computer. There is a popular press  article on Ludgate here

Ludgate's original article describing his computer is here. The Irish logarithms were only one of his inventions needed to make a practical computer. I think his story should be better known. 


4. Hex Irish Logarithms


Here is the python code to work out what the base 16 hex Irish logarithm would be. For no reason other then no one else seems to have worked it out before. 

#!/usr/bin/env python3
# Requires: pip install z3-solver

from z3 import *

# 1. Variables Z0…Z15, plus M
Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9, Z10, Z11, Z12, Z13, Z14, Z15 = \
Ints('Z0 Z1 Z2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 Z15')
Z = [Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9, Z10, Z11, Z12, Z13, Z14, Z15]
M = Int('M')

opt = Optimize()

# 2. Symmetry-breaking: log(1)=0, log(2)=1
opt.add(Z1 == 0, Z2 == 1)

# 3. Bounds on Z1…Z15 in [0..M], and send Z0 out-of-range
for i in range(1, 16):
opt.add(Z[i] >= 0, Z[i] <= M)
opt.add(Z0 == M + 1)

# 4. Force worst-case = sum of two largest primes 13+13
opt.add(M == Z13 + Z13)

# 5. Prime-ordering to break permutations
opt.add(Z2 < Z3, Z3 < Z5, Z5 < Z7, Z7 < Z11, Z11 < Z13)

# 6. Collision-avoidance for all non-zero digit-pairs
pairs = [(a, b) for a in range(1, 16) for b in range(a, 16)]
S = {(a, b): Z[a] + Z[b] for (a, b) in pairs}

for i, (a, b) in enumerate(pairs):
for (c, d) in pairs[i+1:]:
if a*b == c*d:
opt.add(S[(a, b)] == S[(c, d)])
else:
opt.add(S[(a, b)] != S[(c, d)])

# 7. Ensure every valid sum ≤ M
for (a, b) in pairs:
opt.add(S[(a, b)] <= M)

# 8. Minimize M
opt.minimize(M)

# 9. Solve & report
if opt.check().r == 1: # sat
model = opt.model()

# Convert each Z[i] (an IntNumRef) into a plain Python int
table1 = [model[Z[i]].as_long() for i in range(16)]

M_val = model[M].as_long()
print("Minimum max-sum M =", M_val)
print("Table1 (Z0…Z15) =", table1)

max_sum = max(table1) + max(table1)
print("Verified max_sum =", max_sum)
else:
print("No solution found")


Minimum max-sum M = 178 Table1 (Z0…Z15) = [179, 0, 1, 21, 2, 51, 22, 77, 3, 42, 52, 85, 23, 89, 78, 72] Verified max_sum = 358