| # Circle Packing Strategies for n=26 in a Unit Square |
|
|
| ## Key Insight |
| Naive geometric placement (rings, grids) gives sum_radii ~ 1.0. |
| Using numerical optimization (scipy.optimize) with proper constraint formulation |
| can push sum_radii above 2.5. |
|
|
| ## Why Optimization Works Better Than Manual Placement |
|
|
| Manual placement fixes circle positions, then computes maximum radii. |
| This leaves gaps because positions aren't optimized for the radii they produce. |
|
|
| **Joint optimization** treats both positions (x,y for each circle) AND radii |
| as decision variables, optimizing them simultaneously. This is the key insight. |
|
|
| Decision vector: [x0, y0, x1, y1, ..., x25, y25, r0, r1, ..., r25] |
| Total variables: 26*2 + 26 = 78 |
| |
| ## Constraint Formulation |
| |
| 1. **Non-overlap**: For every pair (i,j): distance(center_i, center_j) >= r_i + r_j |
| 2. **Boundary**: For every circle i: x_i - r_i >= 0, x_i + r_i <= 1, y_i - r_i >= 0, y_i + r_i <= 1 |
| 3. **Positive radii**: r_i > 0 for all i (use bounds, not constraints) |
| |
| ## Recommended Solver |
| |
| scipy.optimize.minimize with method="SLSQP": |
| - Handles inequality constraints natively |
| - Works with bounds on variables |
| - Good for smooth, continuous problems like circle packing |
| - Sensitive to initial guess — use multiple starts or a good heuristic |
| |
| ## Initial Guess Strategy |
| |
| A hexagonal grid initial guess works well: |
| - Place circles on offset rows (hex pattern) |
| - Start with equal small radii (e.g., 0.05) |
| - Let the optimizer adjust both positions and radii |
| |
| ## Performance Tips |
| |
| - Set maxiter=1000 or higher for 26 circles |
| - Use ftol=1e-8 or smaller for precise solutions |
| - Radii bounds: (0.01, 0.2) is a reasonable range for n=26 |
| - The objective is -sum(radii) (minimize negative to maximize) |
| |