| |
| """Constructor-based circle packing for n=26 circles""" |
| import numpy as np |
|
|
|
|
| def construct_packing(): |
| """ |
| Construct a specific arrangement of 26 circles in a unit square |
| that attempts to maximize the sum of their radii. |
| |
| Returns: |
| Tuple of (centers, radii, sum_of_radii) |
| centers: np.array of shape (26, 2) with (x, y) coordinates |
| radii: np.array of shape (26) with radius of each circle |
| sum_of_radii: Sum of all radii |
| """ |
| |
| n = 26 |
| centers = np.zeros((n, 2)) |
|
|
| |
| |
|
|
| |
| centers[0] = [0.5, 0.5] |
|
|
| |
| for i in range(8): |
| angle = 2 * np.pi * i / 8 |
| centers[i + 1] = [0.5 + 0.3 * np.cos(angle), 0.5 + 0.3 * np.sin(angle)] |
|
|
| |
| for i in range(16): |
| angle = 2 * np.pi * i / 16 |
| centers[i + 9] = [0.5 + 0.7 * np.cos(angle), 0.5 + 0.7 * np.sin(angle)] |
|
|
| |
| |
| |
| centers = np.clip(centers, 0.01, 0.99) |
|
|
| |
| radii = compute_max_radii(centers) |
|
|
| |
| sum_radii = np.sum(radii) |
|
|
| return centers, radii, sum_radii |
|
|
|
|
| def compute_max_radii(centers): |
| """ |
| Compute the maximum possible radii for each circle position |
| such that they don't overlap and stay within the unit square. |
| |
| Args: |
| centers: np.array of shape (n, 2) with (x, y) coordinates |
| |
| Returns: |
| np.array of shape (n) with radius of each circle |
| """ |
| n = centers.shape[0] |
| radii = np.ones(n) |
|
|
| |
| for i in range(n): |
| x, y = centers[i] |
| |
| radii[i] = min(x, y, 1 - x, 1 - y) |
|
|
| |
| |
| |
| for i in range(n): |
| for j in range(i + 1, n): |
| dist = np.sqrt(np.sum((centers[i] - centers[j]) ** 2)) |
|
|
| |
| if radii[i] + radii[j] > dist: |
| |
| scale = dist / (radii[i] + radii[j]) |
| radii[i] *= scale |
| radii[j] *= scale |
|
|
| return radii |
|
|
|
|
| |
|
|
|
|
| |
| def run_packing(): |
| """Run the circle packing constructor for n=26""" |
| centers, radii, sum_radii = construct_packing() |
| return centers, radii, sum_radii |
|
|
|
|
| def visualize(centers, radii): |
| """ |
| Visualize the circle packing |
| |
| Args: |
| centers: np.array of shape (n, 2) with (x, y) coordinates |
| radii: np.array of shape (n) with radius of each circle |
| """ |
| import matplotlib.pyplot as plt |
| from matplotlib.patches import Circle |
|
|
| fig, ax = plt.subplots(figsize=(8, 8)) |
|
|
| |
| ax.set_xlim(0, 1) |
| ax.set_ylim(0, 1) |
| ax.set_aspect("equal") |
| ax.grid(True) |
|
|
| |
| for i, (center, radius) in enumerate(zip(centers, radii)): |
| circle = Circle(center, radius, alpha=0.5) |
| ax.add_patch(circle) |
| ax.text(center[0], center[1], str(i), ha="center", va="center") |
|
|
| plt.title(f"Circle Packing (n={len(centers)}, sum={sum(radii):.6f})") |
| plt.show() |
|
|
|
|
| if __name__ == "__main__": |
| centers, radii, sum_radii = run_packing() |
| print(f"Sum of radii: {sum_radii}") |
| |
|
|
| |
| visualize(centers, radii) |
|
|