import numpy as np import matplotlib.pyplot as plt

phi = (1 + np.sqrt(5)) / 2 tau = 1 / phi**2

alpha = 2 * phi beta = 1

x = np.linspace(0, 0.5, 1000)

y = x**alpha * (0.5 - x)**beta

y /= y.max()

plt.figure(figsize=(8,4)) plt.plot(x, y, lw=2) plt.axvline(tau, color='red', ls='--', label=r'$\tau=1/\varphi^2$') plt.xlabel("Error") plt.ylabel("Score") plt.title("Golden-ratio Beta-style bump") plt.grid(True) plt.legend() plt.show()


import numpy as np import matplotlib.pyplot as plt

N = 10000 # Search EDOs from 1 to N num_primes = 25 # Number of prime harmonics phi = (1 + np.sqrt(5)) / 2 tau = 1 / phi**2

alpha = 2 * phi beta = 1

def beta_bump(x):

   y = x**alpha * (0.5 - x)**beta
   peak = tau**alpha * (0.5 - tau)**beta
   return y / peak

def first_primes(n):

   primes = []
   k = 2
   while len(primes) < n:
       is_prime = True
       for p in primes:
           if p * p > k:
               break
           if k % p == 0:
               is_prime = False
               break
       if is_prime:
           primes.append(k)
       k += 1
   return np.array(primes)

primes = first_primes(num_primes + 1)[1:]

weights = 2.0 ** (-np.arange(1, num_primes + 1)) weights /= weights.sum()

scores = []

for edo in range(1, N + 1):

   logs = edo * np.log2(primes)
   # distance to nearest integer, in EDO steps
   errors = np.abs(logs - np.round(logs))
   # normalize to [0,0.5]
   errors = np.minimum(errors, 1 - errors)
   score = np.sum(weights * beta_bump(errors))
   scores.append(score)

scores = np.array(scores)

ranking = np.argsort(scores)[::-1]

print("Worst EDOs according to golden-error score:\n")

for rank, idx in enumerate(ranking[:30], start=1):

   edo = idx + 1
   score = scores[idx]
   print(f"{rank:2d}. {edo:4d}-EDO   score = {score:.8f}   distance from ideal = {1-score:.8f}")

plt.figure(figsize=(10,5)) plt.plot(np.arange(1, N+1), scores) plt.xlabel("EDO") plt.ylabel("Golden badness score") plt.grid(True) plt.show()

Recordholders

Record-holder progression:

  1-EDO   score = 0.79348366   distance from ideal = 0.20651634
  8-EDO   score = 0.83520073   distance from ideal = 0.16479927
 54-EDO   score = 0.89628624   distance from ideal = 0.10371376
175-EDO   score = 0.93106554   distance from ideal = 0.06893446
225-EDO   score = 0.94135007   distance from ideal = 0.05864993

1514-EDO score = 0.95731194 distance from ideal = 0.04268806 9709-EDO score = 0.95906127 distance from ideal = 0.04093873


Interestingly, this:

# ---------- 1/p^2 weighting ----------

  1. Assumes beta_bump(), first_primes(), N and num_primes already exist.
  1. Odd primes only

primes = first_primes(num_primes + 1)[1:]

  1. Normalize weights

weights = 1.0 / primes**2 weights /= weights.sum()

scores_p2 = []

for edo in range(1, N + 1):

   logs = edo * np.log2(primes)
   # Distance to nearest integer
   errors = np.abs(logs - np.round(logs))
   errors = np.minimum(errors, 1 - errors)
   score = np.sum(weights * beta_bump(errors))
   scores_p2.append(score)

scores_p2 = np.array(scores_p2)

  1. ---------- Record holders ----------

best_score = -1

print("Record-holder progression (1/p² weighting):\n")

for edo, score in enumerate(scores_p2, start=1):

   if score > best_score:
       best_score = score
       print(f"{edo:5d}-EDO   score = {score:.8f}   distance = {1-score:.8f}")

Produces the same sequence:

Record-holder progression (1/p² weighting):

   1-EDO   score = 0.79730468   distance = 0.20269532
   8-EDO   score = 0.81988848   distance = 0.18011152
  54-EDO   score = 0.89675569   distance = 0.10324431
 175-EDO   score = 0.92591451   distance = 0.07408549
 225-EDO   score = 0.92620065   distance = 0.07379935
1514-EDO   score = 0.94713238   distance = 0.05286762

This indicates that:

1, 8, 54, 175, 225, 1514, hence are the worst edos.