JustinTX commited on
Commit
3827e9c
·
verified ·
1 Parent(s): 50c51ed

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/__pycache__/main.cpython-313.pyc +0 -0
  2. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/edit.diff +212 -0
  3. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/main.py +203 -0
  4. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/original.py +203 -0
  5. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/results/correct.json +4 -0
  6. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/results/metrics.json +25 -0
  7. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/search_replace.txt +91 -0
  8. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/__pycache__/main.cpython-313.pyc +0 -0
  9. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/correct.json +4 -0
  10. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/job_log.err +9 -0
  11. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/job_log.out +16 -0
  12. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/metrics.json +15 -0
  13. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_1/__pycache__/main.cpython-313.pyc +0 -0
  14. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_1/results/correct.json +4 -0
  15. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_1/results/metrics.json +25 -0
  16. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/__pycache__/main.cpython-313.pyc +0 -0
  17. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/edit.diff +137 -0
  18. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/main.py +129 -0
  19. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/original.py +122 -0
  20. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/results/correct.json +4 -0
  21. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/results/metrics.json +25 -0
  22. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/search_replace.txt +50 -0
  23. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_100/__pycache__/main.cpython-313.pyc +0 -0
  24. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_100/results/correct.json +4 -0
  25. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_100/results/metrics.json +25 -0
  26. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_101/__pycache__/main.cpython-313.pyc +0 -0
  27. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_101/results/correct.json +4 -0
  28. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_101/results/metrics.json +25 -0
  29. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/__pycache__/main.cpython-313.pyc +0 -0
  30. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/edit.diff +216 -0
  31. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/main.py +202 -0
  32. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/original.py +164 -0
  33. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/results/correct.json +4 -0
  34. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/results/metrics.json +25 -0
  35. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/search_replace.txt +326 -0
  36. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_103/__pycache__/main.cpython-313.pyc +0 -0
  37. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_103/results/correct.json +4 -0
  38. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_103/results/metrics.json +19 -0
  39. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/__pycache__/main.cpython-313.pyc +0 -0
  40. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/edit.diff +206 -0
  41. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/main.py +196 -0
  42. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/original.py +185 -0
  43. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/results/correct.json +4 -0
  44. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/results/metrics.json +25 -0
  45. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/rewrite.txt +187 -0
  46. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_105/__pycache__/main.cpython-313.pyc +0 -0
  47. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_105/results/correct.json +4 -0
  48. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_105/results/metrics.json +19 -0
  49. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_106/__pycache__/main.cpython-313.pyc +0 -0
  50. examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_106/results/correct.json +4 -0
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/__pycache__/main.cpython-313.pyc ADDED
Binary file (9.06 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/edit.diff ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ --- a/original.py
2
+ +++ b/original.py
3
+ @@ -1,203 +1,203 @@
4
+ # EVOLVE-BLOCK-START
5
+ """
6
+ Implements a long-run, highly adaptive Langevin-dynamics-inspired Simulated
7
+ Annealing (SA) algorithm for the circle packing problem. This hybrid version
8
+ combines the long search of one parent with the proven parameter set of a
9
+ higher-performing parent to achieve a superior result.
10
+ """
11
+
12
+ import numpy as np
13
+
14
+ def _compute_forces(centers, radii, sensitivity, max_force):
15
+ """Calculates repulsion forces based on gaps between circles and walls."""
16
+ n = centers.shape[0]
17
+ force_vectors = np.zeros_like(centers)
18
+
19
+ # Inter-circle forces
20
+ pdiff = centers[:, np.newaxis, :] - centers[np.newaxis, :, :]
21
+ pdist = np.sqrt(np.sum(pdiff**2, axis=-1))
22
+ np.fill_diagonal(pdist, np.inf)
23
+
24
+ radii_sum = radii[:, np.newaxis] + radii[np.newaxis, :]
25
+ gaps = pdist - radii_sum
26
+ force_magnitudes = np.exp(-sensitivity * gaps)
27
+
28
+ # Add a small epsilon to avoid division by zero
29
+ direction_vectors = pdiff / (pdist[..., np.newaxis] + 1e-12)
30
+ force_vectors += np.sum(force_magnitudes[..., np.newaxis] * direction_vectors, axis=1)
31
+
32
+ # Wall forces
33
+ gaps_walls = np.array([centers[:, 0] - radii, (1 - centers[:, 0]) - radii, centers[:, 1] - radii, (1 - centers[:, 1]) - radii]).T
34
+ force_magnitudes_walls = np.exp(-sensitivity * gaps_walls)
35
+ force_vectors[:, 0] += force_magnitudes_walls[:, 0]
36
+ force_vectors[:, 0] -= force_magnitudes_walls[:, 1]
37
+ force_vectors[:, 1] += force_magnitudes_walls[:, 2]
38
+ force_vectors[:, 1] -= force_magnitudes_walls[:, 3]
39
+
40
+ # Cap forces for stability
41
+ norms = np.linalg.norm(force_vectors, axis=1)
42
+ large_force_mask = norms > max_force
43
+ if np.any(large_force_mask):
44
+ force_vectors[large_force_mask] *= (max_force / (norms[large_force_mask, np.newaxis] + 1e-12))
45
+
46
+ return force_vectors
47
+
48
+ def construct_packing():
49
+ """
50
+ Constructs an optimized arrangement of 26 circles using a hybrid
51
+ Langevin-dynamics-inspired Simulated Annealing (SA) algorithm.
52
+ """
53
+ n = 26
54
+
55
+ # 1. Initial State: Proven 5x5 grid with two-stage perturbation.
56
+ centers = np.zeros((n, 2))
57
+ d = 0.09525
58
+ grid_coords = np.linspace(d, 1 - d, 5)
59
+ idx = 0
60
+ for x in grid_coords:
61
+ for y in grid_coords:
62
+ centers[idx] = [x, y]
63
+ idx += 1
64
+ centers[25] = [0.39, 0.41] # Key asymmetric perturbation
65
+
66
+ # Add a small random perturbation to break any remaining symmetries
67
+ perturbation_scale = 0.005
68
+ centers += np.random.uniform(-perturbation_scale, perturbation_scale, centers.shape)
69
+ centers = np.clip(centers, 0.01, 0.99)
70
+
71
+ # 2. Algorithm Parameters: Hybrid of long-run and proven parameters
72
+ max_steps = 150000
73
+ T_initial = 0.005
74
+ T_final = 1e-10 # Lower final temperature for the long run
75
+ alpha = (T_final / T_initial)**(1.0 / max_steps)
76
+
77
+ # Langevin Dynamics Parameters (from high-performing parent)
78
+ step_size_initial = 1.8e-3
79
+ noise_initial = 4.5e-3
80
+
81
+ # Force Calculation Parameter Schedules (from high-performing parent)
82
+ sensitivity_start = 180.0
83
+ - sensitivity_end = 250.0
84
+ + sensitivity_end = 350.0 # Increased for sharper forces at end, closer to 2.61 ancestor (380.0)
85
+ max_force_start = 75.0
86
+ - max_force_end = 40.0
87
+ + max_force_end = 30.0 # Reduced for finer control at end, closer to 2.61 ancestor (25.0)
88
+
89
+ # Radius Solver Parameter Schedules (long-run base with proven tweaks)
90
+ - q_iter_start, q_iter_end = 120, 500
91
+ + q_iter_start, q_iter_end = 120, 400 # Aligned with 2.61 ancestor
92
+ q_init_uf_start, q_init_uf_end = 0.85, 0.6
93
+ q_final_uf_start, q_final_uf_end = 0.65, 0.4
94
+ q_switch_start, q_switch_end = 0.25, 0.5 # From high-performing parent
95
+
96
+ # 3. Initialization of State Variables and Schedules
97
+ current_centers = np.copy(centers)
98
+ best_centers = np.copy(centers)
99
+
100
+ # Pre-generate schedules for efficiency inside the loop
101
+ sensitivities = np.linspace(sensitivity_start, sensitivity_end, max_steps)
102
+ max_forces = np.linspace(max_force_start, max_force_end, max_steps)
103
+ q_iters = np.linspace(q_iter_start, q_iter_end, max_steps, dtype=int)
104
+ q_init_ufs = np.linspace(q_init_uf_start, q_init_uf_end, max_steps)
105
+ q_final_ufs = np.linspace(q_final_uf_start, q_final_uf_end, max_steps)
106
+ q_switches = np.linspace(q_switch_start, q_switch_end, max_steps)
107
+
108
+ # Initial evaluation
109
+ initial_solver_params = (q_init_ufs[0], q_final_ufs[0], q_switches[0])
110
+ current_radii = compute_max_radii(current_centers, iterations=q_iters[0], update_factor=initial_solver_params)
111
+ current_sum_radii = np.sum(current_radii)
112
+ best_sum_radii = current_sum_radii
113
+
114
+ T = T_initial
115
+
116
+ # 4. Main Langevin SA Loop
117
+ for step in range(max_steps):
118
+ # Anneal parameters based on temperature
119
+ anneal_factor = (T / T_initial)
120
+ step_sz = step_size_initial * anneal_factor**0.5
121
+ - noise_magnitude = noise_initial * anneal_factor
122
+ + noise_magnitude = noise_initial * anneal_factor**0.5 # Aligned with 2.61 ancestor's scaling
123
+
124
+ # Get scheduled parameters for this step
125
+ sensitivity = sensitivities[step]
126
+ max_f = max_forces[step]
127
+ solver_params = (q_init_ufs[step], q_final_ufs[step], q_switches[step])
128
+ q_iter = q_iters[step]
129
+
130
+ # Propose a new state using Langevin dynamics
131
+ forces = _compute_forces(current_centers, current_radii, sensitivity, max_f)
132
+ noise = np.random.randn(n, 2) * noise_magnitude
133
+ move_vector = step_sz * forces + noise
134
+
135
+ candidate_centers = current_centers + move_vector
136
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
137
+
138
+ # Evaluate the new state
139
+ candidate_radii = compute_max_radii(candidate_centers, iterations=q_iter, update_factor=solver_params)
140
+ candidate_sum_radii = np.sum(candidate_radii)
141
+
142
+ # Metropolis-Hastings acceptance criterion (objective is to MAXIMIZE sum of radii)
143
+ delta_sum = candidate_sum_radii - current_sum_radii
144
+ if delta_sum > 0 or (T > 1e-12 and np.random.rand() < np.exp(delta_sum / T)):
145
+ current_centers = candidate_centers
146
+ current_sum_radii = candidate_sum_radii
147
+ current_radii = candidate_radii
148
+
149
+ # Update the best-ever found solution
150
+ if current_sum_radii > best_sum_radii:
151
+ best_sum_radii = current_sum_radii
152
+ best_centers = np.copy(current_centers)
153
+
154
+ # Cool down
155
+ T *= alpha
156
+
157
+ - # 5. Enhanced Final Polish (from high-performing parent)
158
+ - final_radii = compute_max_radii(best_centers, iterations=35000, update_factor=(0.7, 0.2, 0.5))
159
+ + # 5. Enhanced Final Polish (from high-performing parent, adjusted to 2.61 ancestor)
160
+ + final_radii = compute_max_radii(best_centers, iterations=35000, update_factor=(0.7, 0.3, 0.4))
161
+
162
+ return best_centers, final_radii
163
+
164
+
165
+ def compute_max_radii(centers, iterations=5000, update_factor=(0.6, 0.6, 0.0)):
166
+ """
167
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
168
+ This version supports an adaptive damping schedule for the update factor.
169
+ """
170
+ n = centers.shape[0]
171
+ radii = np.full(n, 1e-6)
172
+
173
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
174
+ np.fill_diagonal(dist_matrix, np.inf)
175
+
176
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
177
+
178
+ if isinstance(update_factor, (float, int)):
179
+ initial_uf, final_uf, switch_ratio = float(update_factor), float(update_factor), 0.0
180
+ else:
181
+ initial_uf, final_uf, switch_ratio = update_factor
182
+
183
+ for k in range(iterations):
184
+ radii_old = np.copy(radii)
185
+
186
+ current_uf = initial_uf
187
+ if switch_ratio > 0 and k < iterations * switch_ratio:
188
+ progress = k / (iterations * switch_ratio)
189
+ current_uf = initial_uf + (final_uf - initial_uf) * progress
190
+ elif switch_ratio > 0:
191
+ current_uf = final_uf
192
+
193
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
194
+ potential_r = np.minimum(wall_dists, potential_r_circles)
195
+ new_r = np.maximum(0.0, potential_r)
196
+
197
+ radii = radii_old + current_uf * (new_r - radii_old)
198
+
199
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
200
+ break
201
+
202
+ return radii
203
+ # EVOLVE-BLOCK-END
204
+
205
+
206
+ # This part remains fixed (not evolved)
207
+ def run_packing():
208
+ """Run the circle packing constructor for n=26"""
209
+ centers, radii = construct_packing()
210
+ # Calculate the sum of radii
211
+ sum_radii = np.sum(radii)
212
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/main.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ """
3
+ Implements a long-run, highly adaptive Langevin-dynamics-inspired Simulated
4
+ Annealing (SA) algorithm for the circle packing problem. This hybrid version
5
+ combines the long search of one parent with the proven parameter set of a
6
+ higher-performing parent to achieve a superior result.
7
+ """
8
+
9
+ import numpy as np
10
+
11
+ def _compute_forces(centers, radii, sensitivity, max_force):
12
+ """Calculates repulsion forces based on gaps between circles and walls."""
13
+ n = centers.shape[0]
14
+ force_vectors = np.zeros_like(centers)
15
+
16
+ # Inter-circle forces
17
+ pdiff = centers[:, np.newaxis, :] - centers[np.newaxis, :, :]
18
+ pdist = np.sqrt(np.sum(pdiff**2, axis=-1))
19
+ np.fill_diagonal(pdist, np.inf)
20
+
21
+ radii_sum = radii[:, np.newaxis] + radii[np.newaxis, :]
22
+ gaps = pdist - radii_sum
23
+ force_magnitudes = np.exp(-sensitivity * gaps)
24
+
25
+ # Add a small epsilon to avoid division by zero
26
+ direction_vectors = pdiff / (pdist[..., np.newaxis] + 1e-12)
27
+ force_vectors += np.sum(force_magnitudes[..., np.newaxis] * direction_vectors, axis=1)
28
+
29
+ # Wall forces
30
+ gaps_walls = np.array([centers[:, 0] - radii, (1 - centers[:, 0]) - radii, centers[:, 1] - radii, (1 - centers[:, 1]) - radii]).T
31
+ force_magnitudes_walls = np.exp(-sensitivity * gaps_walls)
32
+ force_vectors[:, 0] += force_magnitudes_walls[:, 0]
33
+ force_vectors[:, 0] -= force_magnitudes_walls[:, 1]
34
+ force_vectors[:, 1] += force_magnitudes_walls[:, 2]
35
+ force_vectors[:, 1] -= force_magnitudes_walls[:, 3]
36
+
37
+ # Cap forces for stability
38
+ norms = np.linalg.norm(force_vectors, axis=1)
39
+ large_force_mask = norms > max_force
40
+ if np.any(large_force_mask):
41
+ force_vectors[large_force_mask] *= (max_force / (norms[large_force_mask, np.newaxis] + 1e-12))
42
+
43
+ return force_vectors
44
+
45
+ def construct_packing():
46
+ """
47
+ Constructs an optimized arrangement of 26 circles using a hybrid
48
+ Langevin-dynamics-inspired Simulated Annealing (SA) algorithm.
49
+ """
50
+ n = 26
51
+
52
+ # 1. Initial State: Proven 5x5 grid with two-stage perturbation.
53
+ centers = np.zeros((n, 2))
54
+ d = 0.09525
55
+ grid_coords = np.linspace(d, 1 - d, 5)
56
+ idx = 0
57
+ for x in grid_coords:
58
+ for y in grid_coords:
59
+ centers[idx] = [x, y]
60
+ idx += 1
61
+ centers[25] = [0.39, 0.41] # Key asymmetric perturbation
62
+
63
+ # Add a small random perturbation to break any remaining symmetries
64
+ perturbation_scale = 0.005
65
+ centers += np.random.uniform(-perturbation_scale, perturbation_scale, centers.shape)
66
+ centers = np.clip(centers, 0.01, 0.99)
67
+
68
+ # 2. Algorithm Parameters: Hybrid of long-run and proven parameters
69
+ max_steps = 150000
70
+ T_initial = 0.005
71
+ T_final = 1e-10 # Lower final temperature for the long run
72
+ alpha = (T_final / T_initial)**(1.0 / max_steps)
73
+
74
+ # Langevin Dynamics Parameters (from high-performing parent)
75
+ step_size_initial = 1.8e-3
76
+ noise_initial = 4.5e-3
77
+
78
+ # Force Calculation Parameter Schedules (from high-performing parent)
79
+ sensitivity_start = 180.0
80
+ sensitivity_end = 350.0 # Increased for sharper forces at end, closer to 2.61 ancestor (380.0)
81
+ max_force_start = 75.0
82
+ max_force_end = 30.0 # Reduced for finer control at end, closer to 2.61 ancestor (25.0)
83
+
84
+ # Radius Solver Parameter Schedules (long-run base with proven tweaks)
85
+ q_iter_start, q_iter_end = 120, 400 # Aligned with 2.61 ancestor
86
+ q_init_uf_start, q_init_uf_end = 0.85, 0.6
87
+ q_final_uf_start, q_final_uf_end = 0.65, 0.4
88
+ q_switch_start, q_switch_end = 0.25, 0.5 # From high-performing parent
89
+
90
+ # 3. Initialization of State Variables and Schedules
91
+ current_centers = np.copy(centers)
92
+ best_centers = np.copy(centers)
93
+
94
+ # Pre-generate schedules for efficiency inside the loop
95
+ sensitivities = np.linspace(sensitivity_start, sensitivity_end, max_steps)
96
+ max_forces = np.linspace(max_force_start, max_force_end, max_steps)
97
+ q_iters = np.linspace(q_iter_start, q_iter_end, max_steps, dtype=int)
98
+ q_init_ufs = np.linspace(q_init_uf_start, q_init_uf_end, max_steps)
99
+ q_final_ufs = np.linspace(q_final_uf_start, q_final_uf_end, max_steps)
100
+ q_switches = np.linspace(q_switch_start, q_switch_end, max_steps)
101
+
102
+ # Initial evaluation
103
+ initial_solver_params = (q_init_ufs[0], q_final_ufs[0], q_switches[0])
104
+ current_radii = compute_max_radii(current_centers, iterations=q_iters[0], update_factor=initial_solver_params)
105
+ current_sum_radii = np.sum(current_radii)
106
+ best_sum_radii = current_sum_radii
107
+
108
+ T = T_initial
109
+
110
+ # 4. Main Langevin SA Loop
111
+ for step in range(max_steps):
112
+ # Anneal parameters based on temperature
113
+ anneal_factor = (T / T_initial)
114
+ step_sz = step_size_initial * anneal_factor**0.5
115
+ noise_magnitude = noise_initial * anneal_factor**0.5 # Aligned with 2.61 ancestor's scaling
116
+
117
+ # Get scheduled parameters for this step
118
+ sensitivity = sensitivities[step]
119
+ max_f = max_forces[step]
120
+ solver_params = (q_init_ufs[step], q_final_ufs[step], q_switches[step])
121
+ q_iter = q_iters[step]
122
+
123
+ # Propose a new state using Langevin dynamics
124
+ forces = _compute_forces(current_centers, current_radii, sensitivity, max_f)
125
+ noise = np.random.randn(n, 2) * noise_magnitude
126
+ move_vector = step_sz * forces + noise
127
+
128
+ candidate_centers = current_centers + move_vector
129
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
130
+
131
+ # Evaluate the new state
132
+ candidate_radii = compute_max_radii(candidate_centers, iterations=q_iter, update_factor=solver_params)
133
+ candidate_sum_radii = np.sum(candidate_radii)
134
+
135
+ # Metropolis-Hastings acceptance criterion (objective is to MAXIMIZE sum of radii)
136
+ delta_sum = candidate_sum_radii - current_sum_radii
137
+ if delta_sum > 0 or (T > 1e-12 and np.random.rand() < np.exp(delta_sum / T)):
138
+ current_centers = candidate_centers
139
+ current_sum_radii = candidate_sum_radii
140
+ current_radii = candidate_radii
141
+
142
+ # Update the best-ever found solution
143
+ if current_sum_radii > best_sum_radii:
144
+ best_sum_radii = current_sum_radii
145
+ best_centers = np.copy(current_centers)
146
+
147
+ # Cool down
148
+ T *= alpha
149
+
150
+ # 5. Enhanced Final Polish (from high-performing parent, adjusted to 2.61 ancestor)
151
+ final_radii = compute_max_radii(best_centers, iterations=35000, update_factor=(0.7, 0.3, 0.4))
152
+
153
+ return best_centers, final_radii
154
+
155
+
156
+ def compute_max_radii(centers, iterations=5000, update_factor=(0.6, 0.6, 0.0)):
157
+ """
158
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
159
+ This version supports an adaptive damping schedule for the update factor.
160
+ """
161
+ n = centers.shape[0]
162
+ radii = np.full(n, 1e-6)
163
+
164
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
165
+ np.fill_diagonal(dist_matrix, np.inf)
166
+
167
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
168
+
169
+ if isinstance(update_factor, (float, int)):
170
+ initial_uf, final_uf, switch_ratio = float(update_factor), float(update_factor), 0.0
171
+ else:
172
+ initial_uf, final_uf, switch_ratio = update_factor
173
+
174
+ for k in range(iterations):
175
+ radii_old = np.copy(radii)
176
+
177
+ current_uf = initial_uf
178
+ if switch_ratio > 0 and k < iterations * switch_ratio:
179
+ progress = k / (iterations * switch_ratio)
180
+ current_uf = initial_uf + (final_uf - initial_uf) * progress
181
+ elif switch_ratio > 0:
182
+ current_uf = final_uf
183
+
184
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
185
+ potential_r = np.minimum(wall_dists, potential_r_circles)
186
+ new_r = np.maximum(0.0, potential_r)
187
+
188
+ radii = radii_old + current_uf * (new_r - radii_old)
189
+
190
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
191
+ break
192
+
193
+ return radii
194
+ # EVOLVE-BLOCK-END
195
+
196
+
197
+ # This part remains fixed (not evolved)
198
+ def run_packing():
199
+ """Run the circle packing constructor for n=26"""
200
+ centers, radii = construct_packing()
201
+ # Calculate the sum of radii
202
+ sum_radii = np.sum(radii)
203
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/original.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ """
3
+ Implements a long-run, highly adaptive Langevin-dynamics-inspired Simulated
4
+ Annealing (SA) algorithm for the circle packing problem. This hybrid version
5
+ combines the long search of one parent with the proven parameter set of a
6
+ higher-performing parent to achieve a superior result.
7
+ """
8
+
9
+ import numpy as np
10
+
11
+ def _compute_forces(centers, radii, sensitivity, max_force):
12
+ """Calculates repulsion forces based on gaps between circles and walls."""
13
+ n = centers.shape[0]
14
+ force_vectors = np.zeros_like(centers)
15
+
16
+ # Inter-circle forces
17
+ pdiff = centers[:, np.newaxis, :] - centers[np.newaxis, :, :]
18
+ pdist = np.sqrt(np.sum(pdiff**2, axis=-1))
19
+ np.fill_diagonal(pdist, np.inf)
20
+
21
+ radii_sum = radii[:, np.newaxis] + radii[np.newaxis, :]
22
+ gaps = pdist - radii_sum
23
+ force_magnitudes = np.exp(-sensitivity * gaps)
24
+
25
+ # Add a small epsilon to avoid division by zero
26
+ direction_vectors = pdiff / (pdist[..., np.newaxis] + 1e-12)
27
+ force_vectors += np.sum(force_magnitudes[..., np.newaxis] * direction_vectors, axis=1)
28
+
29
+ # Wall forces
30
+ gaps_walls = np.array([centers[:, 0] - radii, (1 - centers[:, 0]) - radii, centers[:, 1] - radii, (1 - centers[:, 1]) - radii]).T
31
+ force_magnitudes_walls = np.exp(-sensitivity * gaps_walls)
32
+ force_vectors[:, 0] += force_magnitudes_walls[:, 0]
33
+ force_vectors[:, 0] -= force_magnitudes_walls[:, 1]
34
+ force_vectors[:, 1] += force_magnitudes_walls[:, 2]
35
+ force_vectors[:, 1] -= force_magnitudes_walls[:, 3]
36
+
37
+ # Cap forces for stability
38
+ norms = np.linalg.norm(force_vectors, axis=1)
39
+ large_force_mask = norms > max_force
40
+ if np.any(large_force_mask):
41
+ force_vectors[large_force_mask] *= (max_force / (norms[large_force_mask, np.newaxis] + 1e-12))
42
+
43
+ return force_vectors
44
+
45
+ def construct_packing():
46
+ """
47
+ Constructs an optimized arrangement of 26 circles using a hybrid
48
+ Langevin-dynamics-inspired Simulated Annealing (SA) algorithm.
49
+ """
50
+ n = 26
51
+
52
+ # 1. Initial State: Proven 5x5 grid with two-stage perturbation.
53
+ centers = np.zeros((n, 2))
54
+ d = 0.09525
55
+ grid_coords = np.linspace(d, 1 - d, 5)
56
+ idx = 0
57
+ for x in grid_coords:
58
+ for y in grid_coords:
59
+ centers[idx] = [x, y]
60
+ idx += 1
61
+ centers[25] = [0.39, 0.41] # Key asymmetric perturbation
62
+
63
+ # Add a small random perturbation to break any remaining symmetries
64
+ perturbation_scale = 0.005
65
+ centers += np.random.uniform(-perturbation_scale, perturbation_scale, centers.shape)
66
+ centers = np.clip(centers, 0.01, 0.99)
67
+
68
+ # 2. Algorithm Parameters: Hybrid of long-run and proven parameters
69
+ max_steps = 150000
70
+ T_initial = 0.005
71
+ T_final = 1e-10 # Lower final temperature for the long run
72
+ alpha = (T_final / T_initial)**(1.0 / max_steps)
73
+
74
+ # Langevin Dynamics Parameters (from high-performing parent)
75
+ step_size_initial = 1.8e-3
76
+ noise_initial = 4.5e-3
77
+
78
+ # Force Calculation Parameter Schedules (from high-performing parent)
79
+ sensitivity_start = 180.0
80
+ sensitivity_end = 250.0
81
+ max_force_start = 75.0
82
+ max_force_end = 40.0
83
+
84
+ # Radius Solver Parameter Schedules (long-run base with proven tweaks)
85
+ q_iter_start, q_iter_end = 120, 500
86
+ q_init_uf_start, q_init_uf_end = 0.85, 0.6
87
+ q_final_uf_start, q_final_uf_end = 0.65, 0.4
88
+ q_switch_start, q_switch_end = 0.25, 0.5 # From high-performing parent
89
+
90
+ # 3. Initialization of State Variables and Schedules
91
+ current_centers = np.copy(centers)
92
+ best_centers = np.copy(centers)
93
+
94
+ # Pre-generate schedules for efficiency inside the loop
95
+ sensitivities = np.linspace(sensitivity_start, sensitivity_end, max_steps)
96
+ max_forces = np.linspace(max_force_start, max_force_end, max_steps)
97
+ q_iters = np.linspace(q_iter_start, q_iter_end, max_steps, dtype=int)
98
+ q_init_ufs = np.linspace(q_init_uf_start, q_init_uf_end, max_steps)
99
+ q_final_ufs = np.linspace(q_final_uf_start, q_final_uf_end, max_steps)
100
+ q_switches = np.linspace(q_switch_start, q_switch_end, max_steps)
101
+
102
+ # Initial evaluation
103
+ initial_solver_params = (q_init_ufs[0], q_final_ufs[0], q_switches[0])
104
+ current_radii = compute_max_radii(current_centers, iterations=q_iters[0], update_factor=initial_solver_params)
105
+ current_sum_radii = np.sum(current_radii)
106
+ best_sum_radii = current_sum_radii
107
+
108
+ T = T_initial
109
+
110
+ # 4. Main Langevin SA Loop
111
+ for step in range(max_steps):
112
+ # Anneal parameters based on temperature
113
+ anneal_factor = (T / T_initial)
114
+ step_sz = step_size_initial * anneal_factor**0.5
115
+ noise_magnitude = noise_initial * anneal_factor
116
+
117
+ # Get scheduled parameters for this step
118
+ sensitivity = sensitivities[step]
119
+ max_f = max_forces[step]
120
+ solver_params = (q_init_ufs[step], q_final_ufs[step], q_switches[step])
121
+ q_iter = q_iters[step]
122
+
123
+ # Propose a new state using Langevin dynamics
124
+ forces = _compute_forces(current_centers, current_radii, sensitivity, max_f)
125
+ noise = np.random.randn(n, 2) * noise_magnitude
126
+ move_vector = step_sz * forces + noise
127
+
128
+ candidate_centers = current_centers + move_vector
129
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
130
+
131
+ # Evaluate the new state
132
+ candidate_radii = compute_max_radii(candidate_centers, iterations=q_iter, update_factor=solver_params)
133
+ candidate_sum_radii = np.sum(candidate_radii)
134
+
135
+ # Metropolis-Hastings acceptance criterion (objective is to MAXIMIZE sum of radii)
136
+ delta_sum = candidate_sum_radii - current_sum_radii
137
+ if delta_sum > 0 or (T > 1e-12 and np.random.rand() < np.exp(delta_sum / T)):
138
+ current_centers = candidate_centers
139
+ current_sum_radii = candidate_sum_radii
140
+ current_radii = candidate_radii
141
+
142
+ # Update the best-ever found solution
143
+ if current_sum_radii > best_sum_radii:
144
+ best_sum_radii = current_sum_radii
145
+ best_centers = np.copy(current_centers)
146
+
147
+ # Cool down
148
+ T *= alpha
149
+
150
+ # 5. Enhanced Final Polish (from high-performing parent)
151
+ final_radii = compute_max_radii(best_centers, iterations=35000, update_factor=(0.7, 0.2, 0.5))
152
+
153
+ return best_centers, final_radii
154
+
155
+
156
+ def compute_max_radii(centers, iterations=5000, update_factor=(0.6, 0.6, 0.0)):
157
+ """
158
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
159
+ This version supports an adaptive damping schedule for the update factor.
160
+ """
161
+ n = centers.shape[0]
162
+ radii = np.full(n, 1e-6)
163
+
164
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
165
+ np.fill_diagonal(dist_matrix, np.inf)
166
+
167
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
168
+
169
+ if isinstance(update_factor, (float, int)):
170
+ initial_uf, final_uf, switch_ratio = float(update_factor), float(update_factor), 0.0
171
+ else:
172
+ initial_uf, final_uf, switch_ratio = update_factor
173
+
174
+ for k in range(iterations):
175
+ radii_old = np.copy(radii)
176
+
177
+ current_uf = initial_uf
178
+ if switch_ratio > 0 and k < iterations * switch_ratio:
179
+ progress = k / (iterations * switch_ratio)
180
+ current_uf = initial_uf + (final_uf - initial_uf) * progress
181
+ elif switch_ratio > 0:
182
+ current_uf = final_uf
183
+
184
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
185
+ potential_r = np.minimum(wall_dists, potential_r_circles)
186
+ new_r = np.maximum(0.0, potential_r)
187
+
188
+ radii = radii_old + current_uf * (new_r - radii_old)
189
+
190
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
191
+ break
192
+
193
+ return radii
194
+ # EVOLVE-BLOCK-END
195
+
196
+
197
+ # This part remains fixed (not evolved)
198
+ def run_packing():
199
+ """Run the circle packing constructor for n=26"""
200
+ centers, radii = construct_packing()
201
+ # Calculate the sum of radii
202
+ sum_radii = np.sum(radii)
203
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/results/metrics.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 2.6094239779362547,
3
+ "correct": true,
4
+ "primary": {
5
+ "combined_score": 2.6094239779362547,
6
+ "public": {
7
+ "centers_str": " centers[0] = (0.1147, 0.1147)\n centers[1] = (0.0675, 0.2907)\n centers[2] = (0.0957, 0.4517)\n centers[3] = (0.1064, 0.6536)\n centers[4] = (0.1208, 0.8798)\n centers[5] = (0.3267, 0.0977)\n centers[6] = (0.2560, 0.3052)\n centers[7] = (0.2765, 0.5326)\n centers[8] = (0.3055, 0.7418)\n centers[9] = (0.3134, 0.9254)\n centers[10] = (0.4838, 0.0628)\n centers[11] = (0.4842, 0.2406)\n centers[12] = (0.5673, 0.4119)\n centers[13] = (0.5011, 0.6054)\n centers[14] = (0.5143, 0.8672)\n centers[15] = (0.6418, 0.0966)\n centers[16] = (0.6983, 0.2892)\n centers[17] = (0.7229, 0.4907)\n centers[18] = (0.7347, 0.7201)\n centers[19] = (0.7164, 0.9251)\n centers[20] = (0.8700, 0.1299)\n centers[21] = (0.8942, 0.3643)\n centers[22] = (0.9033, 0.5665)\n centers[23] = (0.9329, 0.7276)\n centers[24] = (0.8949, 0.8952)\n centers[25] = (0.4168, 0.4187)",
8
+ "num_circles": 26
9
+ },
10
+ "private": {
11
+ "reported_sum_of_radii": 2.6094239779362547
12
+ },
13
+ "execution_time_mean": 645.0352613227442,
14
+ "execution_time_std": 0.0,
15
+ "num_valid_runs": 1,
16
+ "num_invalid_runs": 0,
17
+ "all_validation_errors": [],
18
+ "correct": true,
19
+ "validation_error": null
20
+ },
21
+ "auxiliary": {},
22
+ "auxiliary_descriptions": {},
23
+ "timestamp": 1770418650.434517,
24
+ "generation": 194
25
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/best/search_replace.txt ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <NAME>
2
+ align_langevin_params_fix
3
+ </NAME>
4
+
5
+ <DESCRIPTION>
6
+ This is a corrected attempt to align the Langevin dynamics and final polish parameters with a higher-performing ancestor. The previous attempt failed due to an indentation mismatch in the `SEARCH` block.
7
+
8
+ This edit precisely applies the following changes:
9
+
10
+ 1. **Noise Magnitude Scaling:** Adjusts `noise_magnitude` to scale with `anneal_factor**0.5` instead of `anneal_factor`. This matches the successful scaling behavior observed in a higher-performing ancestor (score 2.61), providing a more balanced exploration/exploitation.
11
+ 2. **Force Calculation & Radius Solver Parameters:** Updates `sensitivity_end`, `max_force_end`, and `q_iter_end` to tune the annealing process. `sensitivity_end` is increased for sharper forces at the end, `max_force_end` is reduced for finer control, and `q_iter_end` is slightly reduced to balance performance with the increased `max_steps`. These values are derived from successful ancestors.
12
+ 3. **Final Polish Parameters:** Changes the `update_factor` for the final high-precision polish to `(0.7, 0.3, 0.4)`. This specific tuple for the update factor in `_compute_max_radii` was part of a robust final polish in a high-scoring prior program, and is expected to provide better local optimization.
13
+ </DESCRIPTION>
14
+
15
+ <DIFF>
16
+ <<<<<<< SEARCH
17
+ # Anneal parameters based on temperature
18
+ anneal_factor = (T / T_initial)
19
+ step_sz = step_size_initial * anneal_factor**0.5
20
+ noise_magnitude = noise_initial * anneal_factor
21
+
22
+ # Get scheduled parameters for this step
23
+ sensitivity = sensitivities[step]
24
+ max_f = max_forces[step]
25
+ solver_params = (q_init_ufs[step], q_final_ufs[step], q_switches[step])
26
+ q_iter = q_iters[step]
27
+
28
+ # Propose a new state using Langevin dynamics
29
+ forces = _compute_forces(current_centers, current_radii, sensitivity, max_f)
30
+ noise = np.random.randn(n, 2) * noise_magnitude
31
+ move_vector = step_sz * forces + noise
32
+
33
+ candidate_centers = current_centers + move_vector
34
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
35
+ =======
36
+ # Anneal parameters based on temperature
37
+ anneal_factor = (T / T_initial)
38
+ step_sz = step_size_initial * anneal_factor**0.5
39
+ noise_magnitude = noise_initial * anneal_factor**0.5 # Aligned with 2.61 ancestor's scaling
40
+
41
+ # Get scheduled parameters for this step
42
+ sensitivity = sensitivities[step]
43
+ max_f = max_forces[step]
44
+ solver_params = (q_init_ufs[step], q_final_ufs[step], q_switches[step])
45
+ q_iter = q_iters[step]
46
+
47
+ # Propose a new state using Langevin dynamics
48
+ forces = _compute_forces(current_centers, current_radii, sensitivity, max_f)
49
+ noise = np.random.randn(n, 2) * noise_magnitude
50
+ move_vector = step_sz * forces + noise
51
+
52
+ candidate_centers = current_centers + move_vector
53
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
54
+ >>>>>>> REPLACE
55
+ </DIFF>
56
+
57
+ <DIFF>
58
+ <<<<<<< SEARCH
59
+ sensitivity_start = 180.0
60
+ sensitivity_end = 250.0
61
+ max_force_start = 75.0
62
+ max_force_end = 40.0
63
+
64
+ # Radius Solver Parameter Schedules (long-run base with proven tweaks)
65
+ q_iter_start, q_iter_end = 120, 500
66
+ q_init_uf_start, q_init_uf_end = 0.85, 0.6
67
+ q_final_uf_start, q_final_uf_end = 0.65, 0.4
68
+ q_switch_start, q_switch_end = 0.25, 0.5 # From high-performing parent
69
+ =======
70
+ sensitivity_start = 180.0
71
+ sensitivity_end = 350.0 # Increased for sharper forces at end, closer to 2.61 ancestor (380.0)
72
+ max_force_start = 75.0
73
+ max_force_end = 30.0 # Reduced for finer control at end, closer to 2.61 ancestor (25.0)
74
+
75
+ # Radius Solver Parameter Schedules (long-run base with proven tweaks)
76
+ q_iter_start, q_iter_end = 120, 400 # Aligned with 2.61 ancestor
77
+ q_init_uf_start, q_init_uf_end = 0.85, 0.6
78
+ q_final_uf_start, q_final_uf_end = 0.65, 0.4
79
+ q_switch_start, q_switch_end = 0.25, 0.5 # From high-performing parent
80
+ >>>>>>> REPLACE
81
+ </DIFF>
82
+
83
+ <DIFF>
84
+ <<<<<<< SEARCH
85
+ # 5. Enhanced Final Polish (from high-performing parent)
86
+ final_radii = compute_max_radii(best_centers, iterations=35000, update_factor=(0.7, 0.2, 0.5))
87
+ =======
88
+ # 5. Enhanced Final Polish (from high-performing parent, adjusted to 2.61 ancestor)
89
+ final_radii = compute_max_radii(best_centers, iterations=35000, update_factor=(0.7, 0.3, 0.4))
90
+ >>>>>>> REPLACE
91
+ </DIFF>
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/__pycache__/main.cpython-313.pyc ADDED
Binary file (3.15 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/job_log.err ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ /home/tengxiao/pj/ShinkaEvolve/.venv/lib/python3.13/site-packages/instructor/providers/gemini/client.py:5: FutureWarning:
2
+
3
+ All support for the `google.generativeai` package has ended. It will no longer be receiving
4
+ updates or bug fixes. Please switch to the `google.genai` package as soon as possible.
5
+ See README for more details:
6
+
7
+ https://github.com/google-gemini/deprecated-generative-ai-python/blob/main/README.md
8
+
9
+ import google.generativeai as genai # type: ignore[import-not-found]
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/job_log.out ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Evaluating program: examples/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/main.py
2
+ Saving results to: examples/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results
3
+ Run 1/1 completed in 0.00 seconds
4
+ Detailed packing data saved to examples/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/extra.npz
5
+ Correctness and error status saved to examples/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/correct.json
6
+ Metrics saved to examples/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/metrics.json
7
+ Evaluation and Validation completed successfully.
8
+ Metrics:
9
+ combined_score: 0.9597642169962064
10
+ public: {'centers_str': ' centers[0] = (0.5000, 0.5000)\n centers[1] = (0.8000, 0.5000)\n centers[2] = (0.7121, 0.7121)\n centers[3] = (0.5000, 0.8000)\n centers[4] = (0.2879, 0.7121)\n centers[5] = (0.2000, 0.5000)\n centers[6] = (0.2879, 0.2879)\n centers[7] = (0.5000, 0.2000)\n centers[8] = (0.7121, 0.2879)\n centers[9] = (0.9900, 0.5000)\n centers[10] = (0.9900, 0.7679)\n centers[11] = (0.9900, 0.9900)\n centers[12] = (0.7679, 0.9900)\n centers[13] = (0.5000, 0.9900)\n centers[14] = (0.2321, 0.9900)\n centers[15] = (0.0100, 0.9900)\n centers[16] = (0.0100, 0.7679)\n centers[17] = (0.0100, 0.5000)\n centers[18] = (0.0100, 0.2321)\n centers[19] = (0.0100, 0.0100)\n centers[20] = (0.2321, 0.0100)\n centers[21] = (0.5000, 0.0100)\n centers[22] = (0.7679, 0.0100)\n centers[23] = (0.9900, 0.0100)\n centers[24] = (0.9900, 0.2321)\n centers[25] = (0.0100, 0.0100)', 'num_circles': 26}
11
+ private: {'reported_sum_of_radii': 0.9597642169962064}
12
+ execution_time_mean: 0.0021205758675932884
13
+ execution_time_std: 0.0
14
+ num_valid_runs: 1
15
+ num_invalid_runs: 0
16
+ all_validation_errors: []
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_0/results/metrics.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 0.9597642169962064,
3
+ "public": {
4
+ "centers_str": " centers[0] = (0.5000, 0.5000)\n centers[1] = (0.8000, 0.5000)\n centers[2] = (0.7121, 0.7121)\n centers[3] = (0.5000, 0.8000)\n centers[4] = (0.2879, 0.7121)\n centers[5] = (0.2000, 0.5000)\n centers[6] = (0.2879, 0.2879)\n centers[7] = (0.5000, 0.2000)\n centers[8] = (0.7121, 0.2879)\n centers[9] = (0.9900, 0.5000)\n centers[10] = (0.9900, 0.7679)\n centers[11] = (0.9900, 0.9900)\n centers[12] = (0.7679, 0.9900)\n centers[13] = (0.5000, 0.9900)\n centers[14] = (0.2321, 0.9900)\n centers[15] = (0.0100, 0.9900)\n centers[16] = (0.0100, 0.7679)\n centers[17] = (0.0100, 0.5000)\n centers[18] = (0.0100, 0.2321)\n centers[19] = (0.0100, 0.0100)\n centers[20] = (0.2321, 0.0100)\n centers[21] = (0.5000, 0.0100)\n centers[22] = (0.7679, 0.0100)\n centers[23] = (0.9900, 0.0100)\n centers[24] = (0.9900, 0.2321)\n centers[25] = (0.0100, 0.0100)",
5
+ "num_circles": 26
6
+ },
7
+ "private": {
8
+ "reported_sum_of_radii": 0.9597642169962064
9
+ },
10
+ "execution_time_mean": 0.0021205758675932884,
11
+ "execution_time_std": 0.0,
12
+ "num_valid_runs": 1,
13
+ "num_invalid_runs": 0,
14
+ "all_validation_errors": []
15
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_1/__pycache__/main.cpython-313.pyc ADDED
Binary file (2.76 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_1/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_1/results/metrics.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 1.9200929312704162,
3
+ "correct": true,
4
+ "primary": {
5
+ "combined_score": 1.9200929312704162,
6
+ "public": {
7
+ "centers_str": " centers[0] = (0.1000, 0.1000)\n centers[1] = (0.1000, 0.3000)\n centers[2] = (0.1000, 0.5000)\n centers[3] = (0.1000, 0.7000)\n centers[4] = (0.1000, 0.9000)\n centers[5] = (0.3000, 0.1000)\n centers[6] = (0.3000, 0.3000)\n centers[7] = (0.3000, 0.5000)\n centers[8] = (0.3000, 0.7000)\n centers[9] = (0.3000, 0.9000)\n centers[10] = (0.5000, 0.1000)\n centers[11] = (0.5000, 0.3000)\n centers[12] = (0.5000, 0.5000)\n centers[13] = (0.5000, 0.7000)\n centers[14] = (0.5000, 0.9000)\n centers[15] = (0.7000, 0.1000)\n centers[16] = (0.7000, 0.3000)\n centers[17] = (0.7000, 0.5000)\n centers[18] = (0.7000, 0.7000)\n centers[19] = (0.7000, 0.9000)\n centers[20] = (0.9000, 0.1000)\n centers[21] = (0.9000, 0.3000)\n centers[22] = (0.9000, 0.5000)\n centers[23] = (0.9000, 0.7000)\n centers[24] = (0.9000, 0.9000)\n centers[25] = (0.4000, 0.4000)",
8
+ "num_circles": 26
9
+ },
10
+ "private": {
11
+ "reported_sum_of_radii": 1.9200929312704162
12
+ },
13
+ "execution_time_mean": 0.002143661491572857,
14
+ "execution_time_std": 0.0,
15
+ "num_valid_runs": 1,
16
+ "num_invalid_runs": 0,
17
+ "all_validation_errors": [],
18
+ "correct": true,
19
+ "validation_error": null
20
+ },
21
+ "auxiliary": {},
22
+ "auxiliary_descriptions": {},
23
+ "timestamp": 1770396777.592588,
24
+ "generation": 1
25
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/__pycache__/main.cpython-313.pyc ADDED
Binary file (3.96 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/edit.diff ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ --- a/original.py
2
+ +++ b/original.py
3
+ @@ -1,122 +1,129 @@
4
+ # EVOLVE-BLOCK-START
5
+ """Constructor-based circle packing for n=26 circles combining 5x5 grid layout
6
+ with iterative radius relaxation solver."""
7
+
8
+ import numpy as np
9
+
10
+
11
+ def construct_packing():
12
+ """
13
+ Constructs an arrangement of 26 circles in a unit square based on a
14
+ 5x5 grid pattern plus one extra circle, using an iterative radius
15
+ relaxation solver to maximize the sum of their radii.
16
+
17
+ Returns:
18
+ Tuple of (centers, radii)
19
+ centers: np.array of shape (26, 2) with (x, y) coordinates
20
+ radii: np.array of shape (26) with the radius of each circle
21
+ """
22
+ n = 26
23
+ centers = np.zeros((n, 2))
24
+
25
+ # Place 25 circles in a 5x5 grid pattern.
26
+ # Centers are spaced such that they can initially have radius 0.1 each,
27
+ # fitting perfectly within the unit square if they all had r=0.1.
28
+ x_coords = np.linspace(0.1, 0.9, 5) # [0.1, 0.3, 0.5, 0.7, 0.9]
29
+ y_coords = np.linspace(0.1, 0.9, 5) # [0.1, 0.3, 0.5, 0.7, 0.9]
30
+
31
+ idx = 0
32
+ + # Place 24 circles from the 5x5 grid, skipping the center point
33
+ for i in range(5):
34
+ for j in range(5):
35
+ + # Use np.isclose for robust float comparison of the center point
36
+ + if np.isclose(x_coords[i], 0.5) and np.isclose(y_coords[j], 0.5):
37
+ + continue
38
+ centers[idx] = [x_coords[i], y_coords[j]]
39
+ idx += 1
40
+
41
+ - # Place the 26th circle in a different "hole" of the grid.
42
+ - # Instead of (0.4, 0.4), place it centrally along one of the vertical lines
43
+ - # of the grid, e.g., between (0.5, 0.1) and (0.5, 0.3). This might allow
44
+ - # for a larger radius for the 26th circle or better overall distribution.
45
+ - centers[idx] = [0.5, 0.2] # idx will be 25 here, for the 26th circle
46
+ + # Place two circles symmetrically in the central hole created. This hole
47
+ + # is larger than the standard grid holes. The original grid points
48
+ + # at (0.3, 0.5) and (0.7, 0.5) are 0.4 apart. We place two circles
49
+ + # in between. Placing them at 0.45 and 0.55 balances the space.
50
+ + delta = 0.05
51
+ + centers[idx] = [0.5 - delta, 0.5] # idx is 24
52
+ + idx += 1
53
+ + centers[idx] = [0.5 + delta, 0.5] # idx is 25
54
+
55
+ # Compute maximum valid radii for this configuration using the iterative solver.
56
+ radii = compute_max_radii(centers, iterations=200)
57
+ return centers, radii
58
+
59
+
60
+ def compute_max_radii(centers, iterations=200):
61
+ """
62
+ Computes maximum radii using an iterative relaxation method.
63
+ This method is robust for resolving overlaps and maintaining boundary constraints.
64
+
65
+ Args:
66
+ centers: np.array of shape (n, 2) with (x, y) coordinates
67
+ iterations: The number of relaxation iterations to perform.
68
+
69
+ Returns:
70
+ np.array of shape (n) with the radius of each circle
71
+ """
72
+ n = centers.shape[0]
73
+ radii = np.zeros(n)
74
+
75
+ # 1. Initialize radii based on wall distances
76
+ for i in range(n):
77
+ x, y = centers[i]
78
+ radii[i] = min(x, 1 - x, y, 1 - y)
79
+
80
+ # 2. Iteratively resolve overlaps
81
+ for _ in range(iterations):
82
+ max_change = 0.0
83
+ # Check for overlaps between pairs of circles
84
+ for i in range(n):
85
+ for j in range(i + 1, n):
86
+ dist = np.linalg.norm(centers[i] - centers[j])
87
+
88
+ # Handle extremely close or coincident centers gracefully
89
+ if dist < 1e-9:
90
+ radii[i] = 0.0
91
+ radii[j] = 0.0
92
+ max_change = float('inf') # Indicate a significant change occurred
93
+ continue
94
+
95
+ overlap = radii[i] + radii[j] - dist
96
+ if overlap > 0:
97
+ # Resolve overlap by shrinking radii proportionally to their current size.
98
+ total_radii_sum = radii[i] + radii[j]
99
+
100
+ # Handle case where total_radii_sum is near zero to avoid division by zero
101
+ if total_radii_sum < 1e-9:
102
+ radii[i] = 0.0
103
+ radii[j] = 0.0
104
+ continue
105
+
106
+ reduction_i = overlap * (radii[i] / total_radii_sum)
107
+ reduction_j = overlap * (radii[j] / total_radii_sum)
108
+
109
+ radii[i] -= reduction_i
110
+ radii[j] -= reduction_j
111
+ max_change = max(max_change, reduction_i, reduction_j)
112
+
113
+ # Enforce wall constraints after each pass.
114
+ # This is important as shrinking due to overlaps might allow expansion towards walls.
115
+ for i in range(n):
116
+ x, y = centers[i]
117
+ wall_rad = min(x, 1 - x, y, 1 - y)
118
+ if radii[i] > wall_rad:
119
+ change = radii[i] - wall_rad
120
+ radii[i] = wall_rad
121
+ max_change = max(max_change, change)
122
+
123
+ # If radii have stabilized (change is very small), we can exit early.
124
+ if max_change < 1e-7:
125
+ break
126
+
127
+ return radii
128
+ # EVOLVE-BLOCK-END
129
+
130
+
131
+ # This part remains fixed (not evolved)
132
+ def run_packing():
133
+ """Run the circle packing constructor for n=26"""
134
+ centers, radii = construct_packing()
135
+ # Calculate the sum of radii
136
+ sum_radii = np.sum(radii)
137
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/main.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ """Constructor-based circle packing for n=26 circles combining 5x5 grid layout
3
+ with iterative radius relaxation solver."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def construct_packing():
9
+ """
10
+ Constructs an arrangement of 26 circles in a unit square based on a
11
+ 5x5 grid pattern plus one extra circle, using an iterative radius
12
+ relaxation solver to maximize the sum of their radii.
13
+
14
+ Returns:
15
+ Tuple of (centers, radii)
16
+ centers: np.array of shape (26, 2) with (x, y) coordinates
17
+ radii: np.array of shape (26) with the radius of each circle
18
+ """
19
+ n = 26
20
+ centers = np.zeros((n, 2))
21
+
22
+ # Place 25 circles in a 5x5 grid pattern.
23
+ # Centers are spaced such that they can initially have radius 0.1 each,
24
+ # fitting perfectly within the unit square if they all had r=0.1.
25
+ x_coords = np.linspace(0.1, 0.9, 5) # [0.1, 0.3, 0.5, 0.7, 0.9]
26
+ y_coords = np.linspace(0.1, 0.9, 5) # [0.1, 0.3, 0.5, 0.7, 0.9]
27
+
28
+ idx = 0
29
+ # Place 24 circles from the 5x5 grid, skipping the center point
30
+ for i in range(5):
31
+ for j in range(5):
32
+ # Use np.isclose for robust float comparison of the center point
33
+ if np.isclose(x_coords[i], 0.5) and np.isclose(y_coords[j], 0.5):
34
+ continue
35
+ centers[idx] = [x_coords[i], y_coords[j]]
36
+ idx += 1
37
+
38
+ # Place two circles symmetrically in the central hole created. This hole
39
+ # is larger than the standard grid holes. The original grid points
40
+ # at (0.3, 0.5) and (0.7, 0.5) are 0.4 apart. We place two circles
41
+ # in between. Placing them at 0.45 and 0.55 balances the space.
42
+ delta = 0.05
43
+ centers[idx] = [0.5 - delta, 0.5] # idx is 24
44
+ idx += 1
45
+ centers[idx] = [0.5 + delta, 0.5] # idx is 25
46
+
47
+ # Compute maximum valid radii for this configuration using the iterative solver.
48
+ radii = compute_max_radii(centers, iterations=200)
49
+ return centers, radii
50
+
51
+
52
+ def compute_max_radii(centers, iterations=200):
53
+ """
54
+ Computes maximum radii using an iterative relaxation method.
55
+ This method is robust for resolving overlaps and maintaining boundary constraints.
56
+
57
+ Args:
58
+ centers: np.array of shape (n, 2) with (x, y) coordinates
59
+ iterations: The number of relaxation iterations to perform.
60
+
61
+ Returns:
62
+ np.array of shape (n) with the radius of each circle
63
+ """
64
+ n = centers.shape[0]
65
+ radii = np.zeros(n)
66
+
67
+ # 1. Initialize radii based on wall distances
68
+ for i in range(n):
69
+ x, y = centers[i]
70
+ radii[i] = min(x, 1 - x, y, 1 - y)
71
+
72
+ # 2. Iteratively resolve overlaps
73
+ for _ in range(iterations):
74
+ max_change = 0.0
75
+ # Check for overlaps between pairs of circles
76
+ for i in range(n):
77
+ for j in range(i + 1, n):
78
+ dist = np.linalg.norm(centers[i] - centers[j])
79
+
80
+ # Handle extremely close or coincident centers gracefully
81
+ if dist < 1e-9:
82
+ radii[i] = 0.0
83
+ radii[j] = 0.0
84
+ max_change = float('inf') # Indicate a significant change occurred
85
+ continue
86
+
87
+ overlap = radii[i] + radii[j] - dist
88
+ if overlap > 0:
89
+ # Resolve overlap by shrinking radii proportionally to their current size.
90
+ total_radii_sum = radii[i] + radii[j]
91
+
92
+ # Handle case where total_radii_sum is near zero to avoid division by zero
93
+ if total_radii_sum < 1e-9:
94
+ radii[i] = 0.0
95
+ radii[j] = 0.0
96
+ continue
97
+
98
+ reduction_i = overlap * (radii[i] / total_radii_sum)
99
+ reduction_j = overlap * (radii[j] / total_radii_sum)
100
+
101
+ radii[i] -= reduction_i
102
+ radii[j] -= reduction_j
103
+ max_change = max(max_change, reduction_i, reduction_j)
104
+
105
+ # Enforce wall constraints after each pass.
106
+ # This is important as shrinking due to overlaps might allow expansion towards walls.
107
+ for i in range(n):
108
+ x, y = centers[i]
109
+ wall_rad = min(x, 1 - x, y, 1 - y)
110
+ if radii[i] > wall_rad:
111
+ change = radii[i] - wall_rad
112
+ radii[i] = wall_rad
113
+ max_change = max(max_change, change)
114
+
115
+ # If radii have stabilized (change is very small), we can exit early.
116
+ if max_change < 1e-7:
117
+ break
118
+
119
+ return radii
120
+ # EVOLVE-BLOCK-END
121
+
122
+
123
+ # This part remains fixed (not evolved)
124
+ def run_packing():
125
+ """Run the circle packing constructor for n=26"""
126
+ centers, radii = construct_packing()
127
+ # Calculate the sum of radii
128
+ sum_radii = np.sum(radii)
129
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/original.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ """Constructor-based circle packing for n=26 circles combining 5x5 grid layout
3
+ with iterative radius relaxation solver."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def construct_packing():
9
+ """
10
+ Constructs an arrangement of 26 circles in a unit square based on a
11
+ 5x5 grid pattern plus one extra circle, using an iterative radius
12
+ relaxation solver to maximize the sum of their radii.
13
+
14
+ Returns:
15
+ Tuple of (centers, radii)
16
+ centers: np.array of shape (26, 2) with (x, y) coordinates
17
+ radii: np.array of shape (26) with the radius of each circle
18
+ """
19
+ n = 26
20
+ centers = np.zeros((n, 2))
21
+
22
+ # Place 25 circles in a 5x5 grid pattern.
23
+ # Centers are spaced such that they can initially have radius 0.1 each,
24
+ # fitting perfectly within the unit square if they all had r=0.1.
25
+ x_coords = np.linspace(0.1, 0.9, 5) # [0.1, 0.3, 0.5, 0.7, 0.9]
26
+ y_coords = np.linspace(0.1, 0.9, 5) # [0.1, 0.3, 0.5, 0.7, 0.9]
27
+
28
+ idx = 0
29
+ for i in range(5):
30
+ for j in range(5):
31
+ centers[idx] = [x_coords[i], y_coords[j]]
32
+ idx += 1
33
+
34
+ # Place the 26th circle in a different "hole" of the grid.
35
+ # Instead of (0.4, 0.4), place it centrally along one of the vertical lines
36
+ # of the grid, e.g., between (0.5, 0.1) and (0.5, 0.3). This might allow
37
+ # for a larger radius for the 26th circle or better overall distribution.
38
+ centers[idx] = [0.5, 0.2] # idx will be 25 here, for the 26th circle
39
+
40
+ # Compute maximum valid radii for this configuration using the iterative solver.
41
+ radii = compute_max_radii(centers, iterations=200)
42
+ return centers, radii
43
+
44
+
45
+ def compute_max_radii(centers, iterations=200):
46
+ """
47
+ Computes maximum radii using an iterative relaxation method.
48
+ This method is robust for resolving overlaps and maintaining boundary constraints.
49
+
50
+ Args:
51
+ centers: np.array of shape (n, 2) with (x, y) coordinates
52
+ iterations: The number of relaxation iterations to perform.
53
+
54
+ Returns:
55
+ np.array of shape (n) with the radius of each circle
56
+ """
57
+ n = centers.shape[0]
58
+ radii = np.zeros(n)
59
+
60
+ # 1. Initialize radii based on wall distances
61
+ for i in range(n):
62
+ x, y = centers[i]
63
+ radii[i] = min(x, 1 - x, y, 1 - y)
64
+
65
+ # 2. Iteratively resolve overlaps
66
+ for _ in range(iterations):
67
+ max_change = 0.0
68
+ # Check for overlaps between pairs of circles
69
+ for i in range(n):
70
+ for j in range(i + 1, n):
71
+ dist = np.linalg.norm(centers[i] - centers[j])
72
+
73
+ # Handle extremely close or coincident centers gracefully
74
+ if dist < 1e-9:
75
+ radii[i] = 0.0
76
+ radii[j] = 0.0
77
+ max_change = float('inf') # Indicate a significant change occurred
78
+ continue
79
+
80
+ overlap = radii[i] + radii[j] - dist
81
+ if overlap > 0:
82
+ # Resolve overlap by shrinking radii proportionally to their current size.
83
+ total_radii_sum = radii[i] + radii[j]
84
+
85
+ # Handle case where total_radii_sum is near zero to avoid division by zero
86
+ if total_radii_sum < 1e-9:
87
+ radii[i] = 0.0
88
+ radii[j] = 0.0
89
+ continue
90
+
91
+ reduction_i = overlap * (radii[i] / total_radii_sum)
92
+ reduction_j = overlap * (radii[j] / total_radii_sum)
93
+
94
+ radii[i] -= reduction_i
95
+ radii[j] -= reduction_j
96
+ max_change = max(max_change, reduction_i, reduction_j)
97
+
98
+ # Enforce wall constraints after each pass.
99
+ # This is important as shrinking due to overlaps might allow expansion towards walls.
100
+ for i in range(n):
101
+ x, y = centers[i]
102
+ wall_rad = min(x, 1 - x, y, 1 - y)
103
+ if radii[i] > wall_rad:
104
+ change = radii[i] - wall_rad
105
+ radii[i] = wall_rad
106
+ max_change = max(max_change, change)
107
+
108
+ # If radii have stabilized (change is very small), we can exit early.
109
+ if max_change < 1e-7:
110
+ break
111
+
112
+ return radii
113
+ # EVOLVE-BLOCK-END
114
+
115
+
116
+ # This part remains fixed (not evolved)
117
+ def run_packing():
118
+ """Run the circle packing constructor for n=26"""
119
+ centers, radii = construct_packing()
120
+ # Calculate the sum of radii
121
+ sum_radii = np.sum(radii)
122
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/results/metrics.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 1.826354003799491,
3
+ "correct": true,
4
+ "primary": {
5
+ "combined_score": 1.826354003799491,
6
+ "public": {
7
+ "centers_str": " centers[0] = (0.1000, 0.1000)\n centers[1] = (0.1000, 0.3000)\n centers[2] = (0.1000, 0.5000)\n centers[3] = (0.1000, 0.7000)\n centers[4] = (0.1000, 0.9000)\n centers[5] = (0.3000, 0.1000)\n centers[6] = (0.3000, 0.3000)\n centers[7] = (0.3000, 0.5000)\n centers[8] = (0.3000, 0.7000)\n centers[9] = (0.3000, 0.9000)\n centers[10] = (0.5000, 0.1000)\n centers[11] = (0.5000, 0.3000)\n centers[12] = (0.5000, 0.7000)\n centers[13] = (0.5000, 0.9000)\n centers[14] = (0.7000, 0.1000)\n centers[15] = (0.7000, 0.3000)\n centers[16] = (0.7000, 0.5000)\n centers[17] = (0.7000, 0.7000)\n centers[18] = (0.7000, 0.9000)\n centers[19] = (0.9000, 0.1000)\n centers[20] = (0.9000, 0.3000)\n centers[21] = (0.9000, 0.5000)\n centers[22] = (0.9000, 0.7000)\n centers[23] = (0.9000, 0.9000)\n centers[24] = (0.4500, 0.5000)\n centers[25] = (0.5500, 0.5000)",
8
+ "num_circles": 26
9
+ },
10
+ "private": {
11
+ "reported_sum_of_radii": 1.826354003799491
12
+ },
13
+ "execution_time_mean": 0.003152531571686268,
14
+ "execution_time_std": 0.0,
15
+ "num_valid_runs": 1,
16
+ "num_invalid_runs": 0,
17
+ "all_validation_errors": [],
18
+ "correct": true,
19
+ "validation_error": null
20
+ },
21
+ "auxiliary": {},
22
+ "auxiliary_descriptions": {},
23
+ "timestamp": 1770397837.0687263,
24
+ "generation": 10
25
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_10/search_replace.txt ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <NAME>
2
+ replace_center_with_dimer
3
+ </NAME>
4
+
5
+ <DESCRIPTION>
6
+ The existing best-performing solutions are based on a 5x5 grid with an additional circle placed in one of the grid 'holes'. This suggests the grid structure is promising but needs modification for N=26. The current implementation scores lower (1.88) than the best-seen score (1.92) by placing the 26th circle in a suboptimal position.
7
+
8
+ Instead of simply reverting to the previous best position `(0.4, 0.4)`, this edit proposes a more fundamental and geometrically-motivated change. I will modify the `construct_packing` function to create a known "defect" structure often seen in sphere packing, which might yield a better overall sum of radii.
9
+
10
+ The change is as follows:
11
+ 1. The 5x5 grid is created, but the centermost circle at `(0.5, 0.5)` is omitted. This creates a larger central empty space (a 'vacancy') compared to the standard grid holes.
12
+ 2. Into this larger vacancy, two circles are placed symmetrically instead of one. The horizontal space between grid points `(0.3, 0.5)` and `(0.7, 0.5)` is `0.4`. Placing two circles in this gap requires careful positioning. I've chosen to place them at `(0.45, 0.5)` and `(0.55, 0.5)`. This balances the distance between the two new circles (`0.1`) and their distance to the nearest grid neighbors (`0.15`).
13
+
14
+ This "dimer-in-vacancy" approach breaks the perfect grid symmetry in a controlled way, which can lead to more efficient packing and is a common strategy for accommodating non-matching numbers in lattice-based packing. I also made the floating-point comparison more robust by using `np.isclose`.
15
+ </DESCRIPTION>
16
+
17
+ <DIFF>
18
+ <<<<<<< SEARCH
19
+ idx = 0
20
+ for i in range(5):
21
+ for j in range(5):
22
+ centers[idx] = [x_coords[i], y_coords[j]]
23
+ idx += 1
24
+
25
+ # Place the 26th circle in a different "hole" of the grid.
26
+ # Instead of (0.4, 0.4), place it centrally along one of the vertical lines
27
+ # of the grid, e.g., between (0.5, 0.1) and (0.5, 0.3). This might allow
28
+ # for a larger radius for the 26th circle or better overall distribution.
29
+ centers[idx] = [0.5, 0.2] # idx will be 25 here, for the 26th circle
30
+ =======
31
+ idx = 0
32
+ # Place 24 circles from the 5x5 grid, skipping the center point
33
+ for i in range(5):
34
+ for j in range(5):
35
+ # Use np.isclose for robust float comparison of the center point
36
+ if np.isclose(x_coords[i], 0.5) and np.isclose(y_coords[j], 0.5):
37
+ continue
38
+ centers[idx] = [x_coords[i], y_coords[j]]
39
+ idx += 1
40
+
41
+ # Place two circles symmetrically in the central hole created. This hole
42
+ # is larger than the standard grid holes. The original grid points
43
+ # at (0.3, 0.5) and (0.7, 0.5) are 0.4 apart. We place two circles
44
+ # in between. Placing them at 0.45 and 0.55 balances the space.
45
+ delta = 0.05
46
+ centers[idx] = [0.5 - delta, 0.5] # idx is 24
47
+ idx += 1
48
+ centers[idx] = [0.5 + delta, 0.5] # idx is 25
49
+ >>>>>>> REPLACE
50
+ </DIFF>
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_100/__pycache__/main.cpython-313.pyc ADDED
Binary file (6.57 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_100/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_100/results/metrics.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 2.535779246674928,
3
+ "correct": true,
4
+ "primary": {
5
+ "combined_score": 2.535779246674928,
6
+ "public": {
7
+ "centers_str": " centers[0] = (0.1097, 0.1087)\n centers[1] = (0.0811, 0.2964)\n centers[2] = (0.1174, 0.4812)\n centers[3] = (0.1123, 0.7007)\n centers[4] = (0.0939, 0.9061)\n centers[5] = (0.2985, 0.0817)\n centers[6] = (0.2546, 0.2550)\n centers[7] = (0.2926, 0.5329)\n centers[8] = (0.3008, 0.6849)\n centers[9] = (0.3039, 0.8795)\n centers[10] = (0.4734, 0.0936)\n centers[11] = (0.5042, 0.2915)\n centers[12] = (0.4926, 0.4887)\n centers[13] = (0.4950, 0.6974)\n centers[14] = (0.5125, 0.9072)\n centers[15] = (0.6730, 0.1065)\n centers[16] = (0.7122, 0.3116)\n centers[17] = (0.6804, 0.5095)\n centers[18] = (0.7152, 0.7072)\n centers[19] = (0.7007, 0.9046)\n centers[20] = (0.8853, 0.1058)\n centers[21] = (0.9076, 0.3027)\n centers[22] = (0.8889, 0.5047)\n centers[23] = (0.9089, 0.7052)\n centers[24] = (0.8980, 0.8980)\n centers[25] = (0.3548, 0.3955)",
8
+ "num_circles": 26
9
+ },
10
+ "private": {
11
+ "reported_sum_of_radii": 2.535779246674928
12
+ },
13
+ "execution_time_mean": 47.51581493206322,
14
+ "execution_time_std": 0.0,
15
+ "num_valid_runs": 1,
16
+ "num_invalid_runs": 0,
17
+ "all_validation_errors": [],
18
+ "correct": true,
19
+ "validation_error": null
20
+ },
21
+ "auxiliary": {},
22
+ "auxiliary_descriptions": {},
23
+ "timestamp": 1770405446.6050518,
24
+ "generation": 100
25
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_101/__pycache__/main.cpython-313.pyc ADDED
Binary file (6.52 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_101/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_101/results/metrics.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 2.5307582777428874,
3
+ "correct": true,
4
+ "primary": {
5
+ "combined_score": 2.5307582777428874,
6
+ "public": {
7
+ "centers_str": " centers[0] = (0.1014, 0.1013)\n centers[1] = (0.0949, 0.2973)\n centers[2] = (0.1231, 0.5127)\n centers[3] = (0.0859, 0.7176)\n centers[4] = (0.0986, 0.9015)\n centers[5] = (0.3038, 0.1011)\n centers[6] = (0.2877, 0.2994)\n centers[7] = (0.3098, 0.5117)\n centers[8] = (0.2813, 0.6854)\n centers[9] = (0.2989, 0.8982)\n centers[10] = (0.5091, 0.1035)\n centers[11] = (0.5086, 0.3027)\n centers[12] = (0.5253, 0.5202)\n centers[13] = (0.4924, 0.7186)\n centers[14] = (0.4901, 0.9103)\n centers[15] = (0.7160, 0.1018)\n centers[16] = (0.6947, 0.2928)\n centers[17] = (0.7090, 0.4733)\n centers[18] = (0.7013, 0.6786)\n centers[19] = (0.6833, 0.8959)\n centers[20] = (0.9087, 0.0912)\n centers[21] = (0.8924, 0.2890)\n centers[22] = (0.8990, 0.4972)\n centers[23] = (0.9058, 0.6923)\n centers[24] = (0.8936, 0.8926)\n centers[25] = (0.3978, 0.4182)",
8
+ "num_circles": 26
9
+ },
10
+ "private": {
11
+ "reported_sum_of_radii": 2.5307582777428874
12
+ },
13
+ "execution_time_mean": 60.76680243201554,
14
+ "execution_time_std": 0.0,
15
+ "num_valid_runs": 1,
16
+ "num_invalid_runs": 0,
17
+ "all_validation_errors": [],
18
+ "correct": true,
19
+ "validation_error": null
20
+ },
21
+ "auxiliary": {},
22
+ "auxiliary_descriptions": {},
23
+ "timestamp": 1770405497.4442744,
24
+ "generation": 101
25
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/__pycache__/main.cpython-313.pyc ADDED
Binary file (7.53 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/edit.diff ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ --- a/original.py
2
+ +++ b/original.py
3
+ @@ -1,164 +1,202 @@
4
+ # EVOLVE-BLOCK-START
5
+ """Constructor-based circle packing for n=26 circles combining 5x5 grid layout
6
+ with iterative radius relaxation solver."""
7
+
8
+ import numpy as np
9
+
10
+
11
+ def construct_packing():
12
+ """
13
+ Constructs an optimized arrangement of 26 circles by starting with a strong
14
+ grid-based pattern and refining center positions using a coordinate ascent
15
+ method with a rich neighborhood and dynamic solver parameters.
16
+
17
+ Returns:
18
+ A tuple containing:
19
+ centers: np.array of shape (26, 2) with the final optimized (x, y) coordinates
20
+ radii: np.array of shape (26) with the final radius of each circle
21
+ """
22
+ n = 26
23
+ centers = np.zeros((n, 2))
24
+
25
+ # 1. Initial Placement: Start with a 5x5 grid + central circle pattern.
26
+ # Adopt the optimized margin 'd' from a successful prior for a potentially better
27
+ # initial grid configuration. This value is known to be effective for dense packings.
28
+ d = 0.09525
29
+ grid_coords = np.linspace(d, 1 - d, 5)
30
+ idx = 0
31
+ for x in grid_coords:
32
+ for y in grid_coords:
33
+ centers[idx] = [x, y]
34
+ idx += 1
35
+
36
+ # Perturb the 26th circle to break initial symmetry. This is critical for escaping local optima.
37
+ # Revert to the fixed, proven value instead of a random one for a stable, high-quality start.
38
+ centers[25] = [0.39, 0.41]
39
+
40
+ + # Apply small random perturbations to all centers to help escape local optima
41
+ + # by introducing slight initial asymmetry and exploring varied starting points.
42
+ + # These scales are based on successful prior implementations.
43
+ + perturbation_scale_grid = 0.005 # For the 5x5 grid circles
44
+ + perturbation_scale_26th = 0.01 # For the 26th central circle
45
+ +
46
+ + centers[:25, 0] += np.random.uniform(-perturbation_scale_grid, perturbation_scale_grid, 25)
47
+ + centers[:25, 1] += np.random.uniform(-perturbation_scale_grid, perturbation_scale_grid, 25)
48
+ + centers[25, 0] += np.random.uniform(-perturbation_scale_26th, perturbation_scale_26th)
49
+ + centers[25, 1] += np.random.uniform(-perturbation_scale_26th, perturbation_scale_26th)
50
+ +
51
+ + # Ensure centers remain within the unit square after perturbation.
52
+ + # Clipping to 0.01 and 0.99 prevents centers from being exactly on the boundary,
53
+ + # which can sometimes lead to issues with radius calculation near walls.
54
+ + centers = np.clip(centers, 0.01, 0.99)
55
+ +
56
+ # 2. Iterative Center Refinement using a Hybrid SA-Coordinate Ascent.
57
+ - refinement_steps = 30
58
+ + # Increased refinement steps for a more thorough annealing process.
59
+ + refinement_steps = 100 # Increased from 30
60
+ step_schedule = np.logspace(np.log10(0.05), np.log10(0.00001), refinement_steps)
61
+
62
+ # A richer 5x5 neighborhood for moves allows for finer adjustments. `(0,0)` is included.
63
+ move_multipliers = [-1.0, -0.5, 0.0, 0.5, 1.0]
64
+ moves = [(dx, dy) for dx in move_multipliers for dy in move_multipliers]
65
+
66
+ # Temperature schedule for the SA-like acceptance criterion.
67
+ T_initial = 0.0005 # Tuned to be sensitive to small changes in sum_radii
68
+ T_final = 1e-9
69
+ # Exponential cooling schedule based on the number of refinement steps.
70
+ + # Recalculated for increased refinement_steps.
71
+ cooling_rate = (T_final / T_initial)**(1.0 / refinement_steps)
72
+ T = T_initial
73
+
74
+ for step_idx in range(refinement_steps):
75
+ step_size = step_schedule[step_idx]
76
+
77
+ # Dynamically adjust quick solve parameters for an efficient search.
78
+ if step_idx < refinement_steps // 3:
79
+ quick_solve_iterations = 80
80
+ - quick_solve_update_factor = 0.7
81
+ + quick_solve_adaptive_schedule = (0.7, 0.4, 0.5) # Initial (high), Final (low), Transition Ratio
82
+ elif step_idx < 2 * refinement_steps // 3:
83
+ quick_solve_iterations = 130
84
+ - quick_solve_update_factor = 0.65
85
+ + quick_solve_adaptive_schedule = (0.65, 0.4, 0.5) # Slightly lower initial, same final
86
+ else:
87
+ quick_solve_iterations = 200
88
+ - quick_solve_update_factor = 0.6
89
+ + quick_solve_adaptive_schedule = (0.6, 0.4, 0.5) # Even lower initial, same final
90
+
91
+ # Iterate through circles, applying a probabilistically chosen move.
92
+ for i in np.random.permutation(n):
93
+ original_center = centers[i]
94
+
95
+ # Generate all 25 potential positions from the move set and evaluate their scores.
96
+ potential_positions = [np.clip(original_center + step_size * np.array(m), 0.0, 1.0) for m in moves]
97
+ scores = np.zeros(len(moves))
98
+
99
+ for idx, pos in enumerate(potential_positions):
100
+ test_centers = np.copy(centers)
101
+ test_centers[i] = pos
102
+ - test_radii = compute_max_radii(test_centers, iterations=quick_solve_iterations, update_factor=quick_solve_update_factor)
103
+ + # Pass the adaptive damping schedule to the quick solver
104
+ + test_radii = compute_max_radii(test_centers, iterations=quick_solve_iterations, adaptive_damping_schedule=quick_solve_adaptive_schedule)
105
+ scores[idx] = np.sum(test_radii)
106
+
107
+ # Select a move using a Boltzmann distribution (numerically stable softmax).
108
+ scores_shifted = scores - np.max(scores)
109
+ if T > 1e-12:
110
+ probs = np.exp(scores_shifted / T)
111
+ else: # At negligible temperature, behave greedily.
112
+ probs = np.zeros_like(scores)
113
+ probs[np.argmax(scores)] = 1.0
114
+
115
+ probs_sum = np.sum(probs)
116
+ if probs_sum > 0:
117
+ probs /= probs_sum
118
+ else: # Failsafe for underflow: behave greedily.
119
+ probs = np.zeros_like(scores)
120
+ probs[np.argmax(scores)] = 1.0
121
+
122
+ # Choose and apply one move based on the calculated probabilities.
123
+ chosen_idx = np.random.choice(len(potential_positions), p=probs)
124
+ centers[i] = potential_positions[chosen_idx]
125
+
126
+ # Cool the temperature for the next refinement step.
127
+ T *= cooling_rate
128
+
129
+ # 3. Final high-precision radius calculation on the optimized centers.
130
+ - # Use a proven stable update_factor and many iterations for the final solve.
131
+ - final_radii = compute_max_radii(centers, iterations=10000, update_factor=0.55)
132
+ + # Use an adaptive damping schedule and many iterations for the final solve for maximum accuracy.
133
+ + # The schedule (0.65, 0.5, 0.2) is based on successful prior implementations.
134
+ + final_radii = compute_max_radii(centers, iterations=10000, adaptive_damping_schedule=(0.65, 0.5, 0.2))
135
+
136
+ return centers, final_radii
137
+
138
+
139
+ -def compute_max_radii(centers, iterations=5000, update_factor=0.6):
140
+ +def compute_max_radii(centers, iterations=5000, update_factor=0.6, adaptive_damping_schedule=None):
141
+ """
142
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
143
+ + This version supports an optional adaptive damping schedule.
144
+
145
+ Args:
146
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
147
+ iterations: The number of relaxation iterations to perform.
148
+ - update_factor: Damping factor for radius updates.
149
+ + update_factor: Base damping factor for radius updates (used if adaptive_damping_schedule is None).
150
+ + adaptive_damping_schedule: A tuple (initial_factor, final_factor, transition_ratio)
151
+ + to linearly decay the damping factor over iterations.
152
+ + If None, a fixed `update_factor` is used.
153
+
154
+ Returns:
155
+ np.array of shape (n) with the radius of each circle.
156
+ """
157
+ n = centers.shape[0]
158
+ # Small non-zero start to prevent issues on the first iteration.
159
+ radii = np.full(n, 1e-6)
160
+
161
+ # Pre-calculate distances between centers.
162
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
163
+ # Set diagonal to infinity so a circle isn't constrained by itself.
164
+ np.fill_diagonal(dist_matrix, np.inf)
165
+
166
+ # Pre-calculate wall distances for all circles.
167
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
168
+
169
+ - for _ in range(iterations):
170
+ + for iter_idx in range(iterations): # Changed loop variable to iter_idx
171
+ radii_old = np.copy(radii)
172
+ +
173
+ + # Determine current damping factor based on adaptive schedule or fixed value
174
+ + if adaptive_damping_schedule is not None:
175
+ + initial_uf, final_uf, transition_ratio = adaptive_damping_schedule
176
+ + if iterations == 0: # Avoid division by zero
177
+ + current_update_factor = final_uf
178
+ + elif iter_idx < iterations * transition_ratio:
179
+ + # Linearly decay from initial_uf to final_uf over the transition_ratio of iterations
180
+ + current_update_factor = initial_uf - (initial_uf - final_uf) * (iter_idx / (iterations * transition_ratio))
181
+ + else:
182
+ + # Maintain final_uf for the remaining iterations
183
+ + current_update_factor = final_uf
184
+ + else:
185
+ + current_update_factor = update_factor
186
+
187
+ # Calculate all potential radii based on other circles in a vectorized way.
188
+ # `dist_matrix - radii_old` gives a matrix of potential radii from each other circle.
189
+ # Taking `min(axis=1)` finds the tightest constraint for each circle.
190
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
191
+
192
+ # Combine with wall constraints.
193
+ potential_r = np.minimum(wall_dists, potential_r_circles)
194
+
195
+ # New radii for this iteration (must be non-negative).
196
+ new_r = np.maximum(0.0, potential_r)
197
+
198
+ # Dampen the update to prevent oscillations.
199
+ - radii = radii_old + update_factor * (new_r - radii_old)
200
+ + radii = radii_old + current_update_factor * (new_r - radii_old)
201
+
202
+ # Early exit condition if radii have converged.
203
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
204
+ break
205
+
206
+ return radii
207
+ # EVOLVE-BLOCK-END
208
+
209
+
210
+ # This part remains fixed (not evolved)
211
+ def run_packing():
212
+ """Run the circle packing constructor for n=26"""
213
+ centers, radii = construct_packing()
214
+ # Calculate the sum of radii
215
+ sum_radii = np.sum(radii)
216
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/main.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ """Constructor-based circle packing for n=26 circles combining 5x5 grid layout
3
+ with iterative radius relaxation solver."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def construct_packing():
9
+ """
10
+ Constructs an optimized arrangement of 26 circles by starting with a strong
11
+ grid-based pattern and refining center positions using a coordinate ascent
12
+ method with a rich neighborhood and dynamic solver parameters.
13
+
14
+ Returns:
15
+ A tuple containing:
16
+ centers: np.array of shape (26, 2) with the final optimized (x, y) coordinates
17
+ radii: np.array of shape (26) with the final radius of each circle
18
+ """
19
+ n = 26
20
+ centers = np.zeros((n, 2))
21
+
22
+ # 1. Initial Placement: Start with a 5x5 grid + central circle pattern.
23
+ # Adopt the optimized margin 'd' from a successful prior for a potentially better
24
+ # initial grid configuration. This value is known to be effective for dense packings.
25
+ d = 0.09525
26
+ grid_coords = np.linspace(d, 1 - d, 5)
27
+ idx = 0
28
+ for x in grid_coords:
29
+ for y in grid_coords:
30
+ centers[idx] = [x, y]
31
+ idx += 1
32
+
33
+ # Perturb the 26th circle to break initial symmetry. This is critical for escaping local optima.
34
+ # Revert to the fixed, proven value instead of a random one for a stable, high-quality start.
35
+ centers[25] = [0.39, 0.41]
36
+
37
+ # Apply small random perturbations to all centers to help escape local optima
38
+ # by introducing slight initial asymmetry and exploring varied starting points.
39
+ # These scales are based on successful prior implementations.
40
+ perturbation_scale_grid = 0.005 # For the 5x5 grid circles
41
+ perturbation_scale_26th = 0.01 # For the 26th central circle
42
+
43
+ centers[:25, 0] += np.random.uniform(-perturbation_scale_grid, perturbation_scale_grid, 25)
44
+ centers[:25, 1] += np.random.uniform(-perturbation_scale_grid, perturbation_scale_grid, 25)
45
+ centers[25, 0] += np.random.uniform(-perturbation_scale_26th, perturbation_scale_26th)
46
+ centers[25, 1] += np.random.uniform(-perturbation_scale_26th, perturbation_scale_26th)
47
+
48
+ # Ensure centers remain within the unit square after perturbation.
49
+ # Clipping to 0.01 and 0.99 prevents centers from being exactly on the boundary,
50
+ # which can sometimes lead to issues with radius calculation near walls.
51
+ centers = np.clip(centers, 0.01, 0.99)
52
+
53
+ # 2. Iterative Center Refinement using a Hybrid SA-Coordinate Ascent.
54
+ # Increased refinement steps for a more thorough annealing process.
55
+ refinement_steps = 100 # Increased from 30
56
+ step_schedule = np.logspace(np.log10(0.05), np.log10(0.00001), refinement_steps)
57
+
58
+ # A richer 5x5 neighborhood for moves allows for finer adjustments. `(0,0)` is included.
59
+ move_multipliers = [-1.0, -0.5, 0.0, 0.5, 1.0]
60
+ moves = [(dx, dy) for dx in move_multipliers for dy in move_multipliers]
61
+
62
+ # Temperature schedule for the SA-like acceptance criterion.
63
+ T_initial = 0.0005 # Tuned to be sensitive to small changes in sum_radii
64
+ T_final = 1e-9
65
+ # Exponential cooling schedule based on the number of refinement steps.
66
+ # Recalculated for increased refinement_steps.
67
+ cooling_rate = (T_final / T_initial)**(1.0 / refinement_steps)
68
+ T = T_initial
69
+
70
+ for step_idx in range(refinement_steps):
71
+ step_size = step_schedule[step_idx]
72
+
73
+ # Dynamically adjust quick solve parameters for an efficient search.
74
+ if step_idx < refinement_steps // 3:
75
+ quick_solve_iterations = 80
76
+ quick_solve_adaptive_schedule = (0.7, 0.4, 0.5) # Initial (high), Final (low), Transition Ratio
77
+ elif step_idx < 2 * refinement_steps // 3:
78
+ quick_solve_iterations = 130
79
+ quick_solve_adaptive_schedule = (0.65, 0.4, 0.5) # Slightly lower initial, same final
80
+ else:
81
+ quick_solve_iterations = 200
82
+ quick_solve_adaptive_schedule = (0.6, 0.4, 0.5) # Even lower initial, same final
83
+
84
+ # Iterate through circles, applying a probabilistically chosen move.
85
+ for i in np.random.permutation(n):
86
+ original_center = centers[i]
87
+
88
+ # Generate all 25 potential positions from the move set and evaluate their scores.
89
+ potential_positions = [np.clip(original_center + step_size * np.array(m), 0.0, 1.0) for m in moves]
90
+ scores = np.zeros(len(moves))
91
+
92
+ for idx, pos in enumerate(potential_positions):
93
+ test_centers = np.copy(centers)
94
+ test_centers[i] = pos
95
+ # Pass the adaptive damping schedule to the quick solver
96
+ test_radii = compute_max_radii(test_centers, iterations=quick_solve_iterations, adaptive_damping_schedule=quick_solve_adaptive_schedule)
97
+ scores[idx] = np.sum(test_radii)
98
+
99
+ # Select a move using a Boltzmann distribution (numerically stable softmax).
100
+ scores_shifted = scores - np.max(scores)
101
+ if T > 1e-12:
102
+ probs = np.exp(scores_shifted / T)
103
+ else: # At negligible temperature, behave greedily.
104
+ probs = np.zeros_like(scores)
105
+ probs[np.argmax(scores)] = 1.0
106
+
107
+ probs_sum = np.sum(probs)
108
+ if probs_sum > 0:
109
+ probs /= probs_sum
110
+ else: # Failsafe for underflow: behave greedily.
111
+ probs = np.zeros_like(scores)
112
+ probs[np.argmax(scores)] = 1.0
113
+
114
+ # Choose and apply one move based on the calculated probabilities.
115
+ chosen_idx = np.random.choice(len(potential_positions), p=probs)
116
+ centers[i] = potential_positions[chosen_idx]
117
+
118
+ # Cool the temperature for the next refinement step.
119
+ T *= cooling_rate
120
+
121
+ # 3. Final high-precision radius calculation on the optimized centers.
122
+ # Use an adaptive damping schedule and many iterations for the final solve for maximum accuracy.
123
+ # The schedule (0.65, 0.5, 0.2) is based on successful prior implementations.
124
+ final_radii = compute_max_radii(centers, iterations=10000, adaptive_damping_schedule=(0.65, 0.5, 0.2))
125
+
126
+ return centers, final_radii
127
+
128
+
129
+ def compute_max_radii(centers, iterations=5000, update_factor=0.6, adaptive_damping_schedule=None):
130
+ """
131
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
132
+ This version supports an optional adaptive damping schedule.
133
+
134
+ Args:
135
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
136
+ iterations: The number of relaxation iterations to perform.
137
+ update_factor: Base damping factor for radius updates (used if adaptive_damping_schedule is None).
138
+ adaptive_damping_schedule: A tuple (initial_factor, final_factor, transition_ratio)
139
+ to linearly decay the damping factor over iterations.
140
+ If None, a fixed `update_factor` is used.
141
+
142
+ Returns:
143
+ np.array of shape (n) with the radius of each circle.
144
+ """
145
+ n = centers.shape[0]
146
+ # Small non-zero start to prevent issues on the first iteration.
147
+ radii = np.full(n, 1e-6)
148
+
149
+ # Pre-calculate distances between centers.
150
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
151
+ # Set diagonal to infinity so a circle isn't constrained by itself.
152
+ np.fill_diagonal(dist_matrix, np.inf)
153
+
154
+ # Pre-calculate wall distances for all circles.
155
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
156
+
157
+ for iter_idx in range(iterations): # Changed loop variable to iter_idx
158
+ radii_old = np.copy(radii)
159
+
160
+ # Determine current damping factor based on adaptive schedule or fixed value
161
+ if adaptive_damping_schedule is not None:
162
+ initial_uf, final_uf, transition_ratio = adaptive_damping_schedule
163
+ if iterations == 0: # Avoid division by zero
164
+ current_update_factor = final_uf
165
+ elif iter_idx < iterations * transition_ratio:
166
+ # Linearly decay from initial_uf to final_uf over the transition_ratio of iterations
167
+ current_update_factor = initial_uf - (initial_uf - final_uf) * (iter_idx / (iterations * transition_ratio))
168
+ else:
169
+ # Maintain final_uf for the remaining iterations
170
+ current_update_factor = final_uf
171
+ else:
172
+ current_update_factor = update_factor
173
+
174
+ # Calculate all potential radii based on other circles in a vectorized way.
175
+ # `dist_matrix - radii_old` gives a matrix of potential radii from each other circle.
176
+ # Taking `min(axis=1)` finds the tightest constraint for each circle.
177
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
178
+
179
+ # Combine with wall constraints.
180
+ potential_r = np.minimum(wall_dists, potential_r_circles)
181
+
182
+ # New radii for this iteration (must be non-negative).
183
+ new_r = np.maximum(0.0, potential_r)
184
+
185
+ # Dampen the update to prevent oscillations.
186
+ radii = radii_old + current_update_factor * (new_r - radii_old)
187
+
188
+ # Early exit condition if radii have converged.
189
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
190
+ break
191
+
192
+ return radii
193
+ # EVOLVE-BLOCK-END
194
+
195
+
196
+ # This part remains fixed (not evolved)
197
+ def run_packing():
198
+ """Run the circle packing constructor for n=26"""
199
+ centers, radii = construct_packing()
200
+ # Calculate the sum of radii
201
+ sum_radii = np.sum(radii)
202
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/original.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ """Constructor-based circle packing for n=26 circles combining 5x5 grid layout
3
+ with iterative radius relaxation solver."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def construct_packing():
9
+ """
10
+ Constructs an optimized arrangement of 26 circles by starting with a strong
11
+ grid-based pattern and refining center positions using a coordinate ascent
12
+ method with a rich neighborhood and dynamic solver parameters.
13
+
14
+ Returns:
15
+ A tuple containing:
16
+ centers: np.array of shape (26, 2) with the final optimized (x, y) coordinates
17
+ radii: np.array of shape (26) with the final radius of each circle
18
+ """
19
+ n = 26
20
+ centers = np.zeros((n, 2))
21
+
22
+ # 1. Initial Placement: Start with a 5x5 grid + central circle pattern.
23
+ # Adopt the optimized margin 'd' from a successful prior for a potentially better
24
+ # initial grid configuration. This value is known to be effective for dense packings.
25
+ d = 0.09525
26
+ grid_coords = np.linspace(d, 1 - d, 5)
27
+ idx = 0
28
+ for x in grid_coords:
29
+ for y in grid_coords:
30
+ centers[idx] = [x, y]
31
+ idx += 1
32
+
33
+ # Perturb the 26th circle to break initial symmetry. This is critical for escaping local optima.
34
+ # Revert to the fixed, proven value instead of a random one for a stable, high-quality start.
35
+ centers[25] = [0.39, 0.41]
36
+
37
+ # 2. Iterative Center Refinement using a Hybrid SA-Coordinate Ascent.
38
+ refinement_steps = 30
39
+ step_schedule = np.logspace(np.log10(0.05), np.log10(0.00001), refinement_steps)
40
+
41
+ # A richer 5x5 neighborhood for moves allows for finer adjustments. `(0,0)` is included.
42
+ move_multipliers = [-1.0, -0.5, 0.0, 0.5, 1.0]
43
+ moves = [(dx, dy) for dx in move_multipliers for dy in move_multipliers]
44
+
45
+ # Temperature schedule for the SA-like acceptance criterion.
46
+ T_initial = 0.0005 # Tuned to be sensitive to small changes in sum_radii
47
+ T_final = 1e-9
48
+ # Exponential cooling schedule based on the number of refinement steps.
49
+ cooling_rate = (T_final / T_initial)**(1.0 / refinement_steps)
50
+ T = T_initial
51
+
52
+ for step_idx in range(refinement_steps):
53
+ step_size = step_schedule[step_idx]
54
+
55
+ # Dynamically adjust quick solve parameters for an efficient search.
56
+ if step_idx < refinement_steps // 3:
57
+ quick_solve_iterations = 80
58
+ quick_solve_update_factor = 0.7
59
+ elif step_idx < 2 * refinement_steps // 3:
60
+ quick_solve_iterations = 130
61
+ quick_solve_update_factor = 0.65
62
+ else:
63
+ quick_solve_iterations = 200
64
+ quick_solve_update_factor = 0.6
65
+
66
+ # Iterate through circles, applying a probabilistically chosen move.
67
+ for i in np.random.permutation(n):
68
+ original_center = centers[i]
69
+
70
+ # Generate all 25 potential positions from the move set and evaluate their scores.
71
+ potential_positions = [np.clip(original_center + step_size * np.array(m), 0.0, 1.0) for m in moves]
72
+ scores = np.zeros(len(moves))
73
+
74
+ for idx, pos in enumerate(potential_positions):
75
+ test_centers = np.copy(centers)
76
+ test_centers[i] = pos
77
+ test_radii = compute_max_radii(test_centers, iterations=quick_solve_iterations, update_factor=quick_solve_update_factor)
78
+ scores[idx] = np.sum(test_radii)
79
+
80
+ # Select a move using a Boltzmann distribution (numerically stable softmax).
81
+ scores_shifted = scores - np.max(scores)
82
+ if T > 1e-12:
83
+ probs = np.exp(scores_shifted / T)
84
+ else: # At negligible temperature, behave greedily.
85
+ probs = np.zeros_like(scores)
86
+ probs[np.argmax(scores)] = 1.0
87
+
88
+ probs_sum = np.sum(probs)
89
+ if probs_sum > 0:
90
+ probs /= probs_sum
91
+ else: # Failsafe for underflow: behave greedily.
92
+ probs = np.zeros_like(scores)
93
+ probs[np.argmax(scores)] = 1.0
94
+
95
+ # Choose and apply one move based on the calculated probabilities.
96
+ chosen_idx = np.random.choice(len(potential_positions), p=probs)
97
+ centers[i] = potential_positions[chosen_idx]
98
+
99
+ # Cool the temperature for the next refinement step.
100
+ T *= cooling_rate
101
+
102
+ # 3. Final high-precision radius calculation on the optimized centers.
103
+ # Use a proven stable update_factor and many iterations for the final solve.
104
+ final_radii = compute_max_radii(centers, iterations=10000, update_factor=0.55)
105
+
106
+ return centers, final_radii
107
+
108
+
109
+ def compute_max_radii(centers, iterations=5000, update_factor=0.6):
110
+ """
111
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
112
+
113
+ Args:
114
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
115
+ iterations: The number of relaxation iterations to perform.
116
+ update_factor: Damping factor for radius updates.
117
+
118
+ Returns:
119
+ np.array of shape (n) with the radius of each circle.
120
+ """
121
+ n = centers.shape[0]
122
+ # Small non-zero start to prevent issues on the first iteration.
123
+ radii = np.full(n, 1e-6)
124
+
125
+ # Pre-calculate distances between centers.
126
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
127
+ # Set diagonal to infinity so a circle isn't constrained by itself.
128
+ np.fill_diagonal(dist_matrix, np.inf)
129
+
130
+ # Pre-calculate wall distances for all circles.
131
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
132
+
133
+ for _ in range(iterations):
134
+ radii_old = np.copy(radii)
135
+
136
+ # Calculate all potential radii based on other circles in a vectorized way.
137
+ # `dist_matrix - radii_old` gives a matrix of potential radii from each other circle.
138
+ # Taking `min(axis=1)` finds the tightest constraint for each circle.
139
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
140
+
141
+ # Combine with wall constraints.
142
+ potential_r = np.minimum(wall_dists, potential_r_circles)
143
+
144
+ # New radii for this iteration (must be non-negative).
145
+ new_r = np.maximum(0.0, potential_r)
146
+
147
+ # Dampen the update to prevent oscillations.
148
+ radii = radii_old + update_factor * (new_r - radii_old)
149
+
150
+ # Early exit condition if radii have converged.
151
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
152
+ break
153
+
154
+ return radii
155
+ # EVOLVE-BLOCK-END
156
+
157
+
158
+ # This part remains fixed (not evolved)
159
+ def run_packing():
160
+ """Run the circle packing constructor for n=26"""
161
+ centers, radii = construct_packing()
162
+ # Calculate the sum of radii
163
+ sum_radii = np.sum(radii)
164
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/results/metrics.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 2.5235511803567197,
3
+ "correct": true,
4
+ "primary": {
5
+ "combined_score": 2.5235511803567197,
6
+ "public": {
7
+ "centers_str": " centers[0] = (0.0883, 0.0883)\n centers[1] = (0.1180, 0.2924)\n centers[2] = (0.0934, 0.5023)\n centers[3] = (0.0973, 0.6929)\n centers[4] = (0.1242, 0.8942)\n centers[5] = (0.3013, 0.1279)\n centers[6] = (0.2995, 0.3217)\n centers[7] = (0.2691, 0.5199)\n centers[8] = (0.2959, 0.7028)\n centers[9] = (0.3291, 0.9008)\n centers[10] = (0.5016, 0.0784)\n centers[11] = (0.5025, 0.2788)\n centers[12] = (0.5164, 0.5183)\n centers[13] = (0.4966, 0.7146)\n centers[14] = (0.5221, 0.9062)\n centers[15] = (0.6876, 0.1103)\n centers[16] = (0.7166, 0.3134)\n centers[17] = (0.7085, 0.5030)\n centers[18] = (0.6989, 0.7029)\n centers[19] = (0.7130, 0.9029)\n centers[20] = (0.8969, 0.0962)\n centers[21] = (0.9048, 0.2874)\n centers[22] = (0.9011, 0.4814)\n centers[23] = (0.9005, 0.6799)\n centers[24] = (0.9041, 0.8753)\n centers[25] = (0.3829, 0.4236)",
8
+ "num_circles": 26
9
+ },
10
+ "private": {
11
+ "reported_sum_of_radii": 2.5235511803567197
12
+ },
13
+ "execution_time_mean": 32.92109573353082,
14
+ "execution_time_std": 0.0,
15
+ "num_valid_runs": 1,
16
+ "num_invalid_runs": 0,
17
+ "all_validation_errors": [],
18
+ "correct": true,
19
+ "validation_error": null
20
+ },
21
+ "auxiliary": {},
22
+ "auxiliary_descriptions": {},
23
+ "timestamp": 1770405591.7633276,
24
+ "generation": 102
25
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_102/search_replace.txt ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <NAME>
2
+ adaptive_damping_in_solver
3
+ </NAME>
4
+
5
+ <DESCRIPTION>
6
+ The `compute_max_radii` function is the core solver for determining circle radii.
7
+ Currently, it uses a single, fixed `update_factor` throughout its iterations.
8
+ This edit enhances `compute_max_radii` by allowing an optional `adaptive_damping_schedule`
9
+ tuple `(initial_factor, final_factor, transition_ratio)`. If provided, the damping
10
+ factor will linearly decay from `initial_factor` to `final_factor` over a
11
+ fraction `transition_ratio` of the total iterations, and then remain at `final_factor`.
12
+ This provides more nuanced control over convergence, preventing oscillations
13
+ early on and promoting stability in later stages, which can lead to higher precision
14
+ and better overall radii sums.
15
+ </DESCRIPTION>
16
+
17
+ <DIFF>
18
+ <<<<<<< SEARCH
19
+ def compute_max_radii(centers, iterations=5000, update_factor=0.6):
20
+ """
21
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
22
+
23
+ Args:
24
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
25
+ iterations: The number of relaxation iterations to perform.
26
+ update_factor: Damping factor for radius updates.
27
+
28
+ Returns:
29
+ np.array of shape (n) with the radius of each circle.
30
+ """
31
+ n = centers.shape[0]
32
+ # Small non-zero start to prevent issues on the first iteration.
33
+ radii = np.full(n, 1e-6)
34
+
35
+ # Pre-calculate distances between centers.
36
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
37
+ # Set diagonal to infinity so a circle isn't constrained by itself.
38
+ np.fill_diagonal(dist_matrix, np.inf)
39
+
40
+ # Pre-calculate wall distances for all circles.
41
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
42
+
43
+ for _ in range(iterations):
44
+ radii_old = np.copy(radii)
45
+
46
+ # Calculate all potential radii based on other circles in a vectorized way.
47
+ # `dist_matrix - radii_old` gives a matrix of potential radii from each other circle.
48
+ # Taking `min(axis=1)` finds the tightest constraint for each circle.
49
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
50
+
51
+ # Combine with wall constraints.
52
+ potential_r = np.minimum(wall_dists, potential_r_circles)
53
+
54
+ # New radii for this iteration (must be non-negative).
55
+ new_r = np.maximum(0.0, potential_r)
56
+
57
+ # Dampen the update to prevent oscillations.
58
+ radii = radii_old + update_factor * (new_r - radii_old)
59
+
60
+ # Early exit condition if radii have converged.
61
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
62
+ break
63
+
64
+ return radii
65
+ =======
66
+ def compute_max_radii(centers, iterations=5000, update_factor=0.6, adaptive_damping_schedule=None):
67
+ """
68
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
69
+ This version supports an optional adaptive damping schedule.
70
+
71
+ Args:
72
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
73
+ iterations: The number of relaxation iterations to perform.
74
+ update_factor: Base damping factor for radius updates (used if adaptive_damping_schedule is None).
75
+ adaptive_damping_schedule: A tuple (initial_factor, final_factor, transition_ratio)
76
+ to linearly decay the damping factor over iterations.
77
+ If None, a fixed `update_factor` is used.
78
+
79
+ Returns:
80
+ np.array of shape (n) with the radius of each circle.
81
+ """
82
+ n = centers.shape[0]
83
+ # Small non-zero start to prevent issues on the first iteration.
84
+ radii = np.full(n, 1e-6)
85
+
86
+ # Pre-calculate distances between centers.
87
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
88
+ # Set diagonal to infinity so a circle isn't constrained by itself.
89
+ np.fill_diagonal(dist_matrix, np.inf)
90
+
91
+ # Pre-calculate wall distances for all circles.
92
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
93
+
94
+ for iter_idx in range(iterations): # Changed loop variable to iter_idx
95
+ radii_old = np.copy(radii)
96
+
97
+ # Determine current damping factor based on adaptive schedule or fixed value
98
+ if adaptive_damping_schedule is not None:
99
+ initial_uf, final_uf, transition_ratio = adaptive_damping_schedule
100
+ if iterations == 0: # Avoid division by zero
101
+ current_update_factor = final_uf
102
+ elif iter_idx < iterations * transition_ratio:
103
+ # Linearly decay from initial_uf to final_uf over the transition_ratio of iterations
104
+ current_update_factor = initial_uf - (initial_uf - final_uf) * (iter_idx / (iterations * transition_ratio))
105
+ else:
106
+ # Maintain final_uf for the remaining iterations
107
+ current_update_factor = final_uf
108
+ else:
109
+ current_update_factor = update_factor
110
+
111
+ # Calculate all potential radii based on other circles in a vectorized way.
112
+ # `dist_matrix - radii_old` gives a matrix of potential radii from each other circle.
113
+ # Taking `min(axis=1)` finds the tightest constraint for each circle.
114
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
115
+
116
+ # Combine with wall constraints.
117
+ potential_r = np.minimum(wall_dists, potential_r_circles)
118
+
119
+ # New radii for this iteration (must be non-negative).
120
+ new_r = np.maximum(0.0, potential_r)
121
+
122
+ # Dampen the update to prevent oscillations.
123
+ radii = radii_old + current_update_factor * (new_r - radii_old)
124
+
125
+ # Early exit condition if radii have converged.
126
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
127
+ break
128
+
129
+ return radii
130
+ >>>>>>> REPLACE
131
+ </DIFF>
132
+
133
+ <NAME>
134
+ initial_random_perturbations
135
+ </NAME>
136
+
137
+ <DESCRIPTION>
138
+ To enhance the exploration of the solution space and prevent premature convergence
139
+ to a local optimum, small random perturbations are reintroduced to all circle
140
+ centers immediately after their initial grid placement. This slightly breaks
141
+ the initial symmetry and provides a diverse set of starting configurations for
142
+ the subsequent refinement process. Different perturbation scales are applied
143
+ to the main grid circles and the 26th central circle to reflect their distinct roles.
144
+ Centers are clipped to ensure they remain within the unit square. This strategy
145
+ was present in prior successful programs and can improve the final sum of radii.
146
+ </DESCRIPTION>
147
+
148
+ <DIFF>
149
+ <<<<<<< SEARCH
150
+ # Perturb the 26th circle to break initial symmetry. This is critical for escaping local optima.
151
+ # Revert to the fixed, proven value instead of a random one for a stable, high-quality start.
152
+ centers[25] = [0.39, 0.41]
153
+
154
+ # 2. Iterative Center Refinement using a Hybrid SA-Coordinate Ascent.
155
+ refinement_steps = 30
156
+ step_schedule = np.logspace(np.log10(0.05), np.log10(0.00001), refinement_steps)
157
+ =======
158
+ # Perturb the 26th circle to break initial symmetry. This is critical for escaping local optima.
159
+ # Revert to the fixed, proven value instead of a random one for a stable, high-quality start.
160
+ centers[25] = [0.39, 0.41]
161
+
162
+ # Apply small random perturbations to all centers to help escape local optima
163
+ # by introducing slight initial asymmetry and exploring varied starting points.
164
+ # These scales are based on successful prior implementations.
165
+ perturbation_scale_grid = 0.005 # For the 5x5 grid circles
166
+ perturbation_scale_26th = 0.01 # For the 26th central circle
167
+
168
+ centers[:25, 0] += np.random.uniform(-perturbation_scale_grid, perturbation_scale_grid, 25)
169
+ centers[:25, 1] += np.random.uniform(-perturbation_scale_grid, perturbation_scale_grid, 25)
170
+ centers[25, 0] += np.random.uniform(-perturbation_scale_26th, perturbation_scale_26th)
171
+ centers[25, 1] += np.random.uniform(-perturbation_scale_26th, perturbation_scale_26th)
172
+
173
+ # Ensure centers remain within the unit square after perturbation.
174
+ # Clipping to 0.01 and 0.99 prevents centers from being exactly on the boundary,
175
+ # which can sometimes lead to issues with radius calculation near walls.
176
+ centers = np.clip(centers, 0.01, 0.99)
177
+
178
+ # 2. Iterative Center Refinement using a Hybrid SA-Coordinate Ascent.
179
+ refinement_steps = 30
180
+ step_schedule = np.logspace(np.log10(0.05), np.log10(0.00001), refinement_steps)
181
+ >>>>>>> REPLACE
182
+ </DIFF>
183
+
184
+ <NAME>
185
+ slower_annealing_schedule
186
+ </NAME>
187
+
188
+ <DESCRIPTION>
189
+ The current simulated annealing component cools very rapidly, potentially leading
190
+ to premature convergence to local optima. This edit proposes to increase the
191
+ number of `refinement_steps` from 30 to 100 and re-calculate the `cooling_rate`
192
+ accordingly. This change allows for a significantly slower cooling process and
193
+ more iterations at higher "temperatures," enabling broader exploration of the
194
+ solution space and a greater chance to escape local optima. While increasing
195
+ computation, the improved search quality is expected to yield a higher sum of radii.
196
+ </DESCRIPTION>
197
+
198
+ <DIFF>
199
+ <<<<<<< SEARCH
200
+ # 2. Iterative Center Refinement using a Hybrid SA-Coordinate Ascent.
201
+ refinement_steps = 30
202
+ step_schedule = np.logspace(np.log10(0.05), np.log10(0.00001), refinement_steps)
203
+
204
+ # A richer 5x5 neighborhood for moves allows for finer adjustments. `(0,0)` is included.
205
+ move_multipliers = [-1.0, -0.5, 0.0, 0.5, 1.0]
206
+ moves = [(dx, dy) for dx in move_multipliers for dy in move_multipliers]
207
+
208
+ # Temperature schedule for the SA-like acceptance criterion.
209
+ T_initial = 0.0005 # Tuned to be sensitive to small changes in sum_radii
210
+ T_final = 1e-9
211
+ # Exponential cooling schedule based on the number of refinement steps.
212
+ cooling_rate = (T_final / T_initial)**(1.0 / refinement_steps)
213
+ T = T_initial
214
+ =======
215
+ # 2. Iterative Center Refinement using a Hybrid SA-Coordinate Ascent.
216
+ # Increased refinement steps for a more thorough annealing process.
217
+ refinement_steps = 100 # Increased from 30
218
+ step_schedule = np.logspace(np.log10(0.05), np.log10(0.00001), refinement_steps)
219
+
220
+ # A richer 5x5 neighborhood for moves allows for finer adjustments. `(0,0)` is included.
221
+ move_multipliers = [-1.0, -0.5, 0.0, 0.5, 1.0]
222
+ moves = [(dx, dy) for dx in move_multipliers for dy in move_multipliers]
223
+
224
+ # Temperature schedule for the SA-like acceptance criterion.
225
+ T_initial = 0.0005 # Tuned to be sensitive to small changes in sum_radii
226
+ T_final = 1e-9
227
+ # Exponential cooling schedule based on the number of refinement steps.
228
+ # Recalculated for increased refinement_steps.
229
+ cooling_rate = (T_final / T_initial)**(1.0 / refinement_steps)
230
+ T = T_initial
231
+ >>>>>>> REPLACE
232
+ </DIFF>
233
+
234
+ <NAME>
235
+ adaptive_quick_solve_damping
236
+ </NAME>
237
+
238
+ <DESCRIPTION>
239
+ The intermediate `compute_max_radii` calls are now enhanced by using
240
+ an adaptive damping schedule rather than a fixed `update_factor`. This allows
241
+ the radius solver to be more aggressive early in its own iterations (higher
242
+ initial damping) and then settle into a more stable convergence (lower final damping).
243
+ This change makes the quick radius evaluations more accurate and robust, which
244
+ can better guide the center refinement process. The schedule for each stage
245
+ is tuned based on the fixed factors previously used, ensuring a smooth transition
246
+ and potentially better overall convergence for the main optimization loop.
247
+ </DESCRIPTION>
248
+
249
+ <DIFF>
250
+ <<<<<<< SEARCH
251
+ if step_idx < refinement_steps // 3:
252
+ quick_solve_iterations = 80
253
+ quick_solve_update_factor = 0.7
254
+ elif step_idx < 2 * refinement_steps // 3:
255
+ quick_solve_iterations = 130
256
+ quick_solve_update_factor = 0.65
257
+ else:
258
+ quick_solve_iterations = 200
259
+ quick_solve_update_factor = 0.6
260
+
261
+ # Iterate through circles, applying a probabilistically chosen move.
262
+ for i in np.random.permutation(n):
263
+ original_center = centers[i]
264
+
265
+ # Generate all 25 potential positions from the move set and evaluate their scores.
266
+ potential_positions = [np.clip(original_center + step_size * np.array(m), 0.0, 1.0) for m in moves]
267
+ scores = np.zeros(len(moves))
268
+
269
+ for idx, pos in enumerate(potential_positions):
270
+ test_centers = np.copy(centers)
271
+ test_centers[i] = pos
272
+ test_radii = compute_max_radii(test_centers, iterations=quick_solve_iterations, update_factor=quick_solve_update_factor)
273
+ scores[idx] = np.sum(test_radii)
274
+ =======
275
+ if step_idx < refinement_steps // 3:
276
+ quick_solve_iterations = 80
277
+ quick_solve_adaptive_schedule = (0.7, 0.4, 0.5) # Initial (high), Final (low), Transition Ratio
278
+ elif step_idx < 2 * refinement_steps // 3:
279
+ quick_solve_iterations = 130
280
+ quick_solve_adaptive_schedule = (0.65, 0.4, 0.5) # Slightly lower initial, same final
281
+ else:
282
+ quick_solve_iterations = 200
283
+ quick_solve_adaptive_schedule = (0.6, 0.4, 0.5) # Even lower initial, same final
284
+
285
+ # Iterate through circles, applying a probabilistically chosen move.
286
+ for i in np.random.permutation(n):
287
+ original_center = centers[i]
288
+
289
+ # Generate all 25 potential positions from the move set and evaluate their scores.
290
+ potential_positions = [np.clip(original_center + step_size * np.array(m), 0.0, 1.0) for m in moves]
291
+ scores = np.zeros(len(moves))
292
+
293
+ for idx, pos in enumerate(potential_positions):
294
+ test_centers = np.copy(centers)
295
+ test_centers[i] = pos
296
+ # Pass the adaptive damping schedule to the quick solver
297
+ test_radii = compute_max_radii(test_centers, iterations=quick_solve_iterations, adaptive_damping_schedule=quick_solve_adaptive_schedule)
298
+ scores[idx] = np.sum(test_radii)
299
+ >>>>>>> REPLACE
300
+ </DIFF>
301
+
302
+ <NAME>
303
+ adaptive_final_solve_damping
304
+ </NAME>
305
+
306
+ <DESCRIPTION>
307
+ The final high-precision radius calculation is crucial for the overall sum of radii.
308
+ By applying an adaptive damping schedule to this step, the solver can achieve
309
+ a more stable and accurate convergence. The `(0.65, 0.5, 0.2)` schedule (initial, final, transition_ratio)
310
+ is derived from previously successful implementations, allowing for faster updates
311
+ early in the final solve and very precise fine-tuning towards the end.
312
+ This ensures the reported sum of radii is as accurate as possible for the optimized centers.
313
+ </DESCRIPTION>
314
+
315
+ <DIFF>
316
+ <<<<<<< SEARCH
317
+ # 3. Final high-precision radius calculation on the optimized centers.
318
+ # Use a proven stable update_factor and many iterations for the final solve.
319
+ final_radii = compute_max_radii(centers, iterations=10000, update_factor=0.55)
320
+ =======
321
+ # 3. Final high-precision radius calculation on the optimized centers.
322
+ # Use an adaptive damping schedule and many iterations for the final solve for maximum accuracy.
323
+ # The schedule (0.65, 0.5, 0.2) is based on successful prior implementations.
324
+ final_radii = compute_max_radii(centers, iterations=10000, adaptive_damping_schedule=(0.65, 0.5, 0.2))
325
+ >>>>>>> REPLACE
326
+ </DIFF>
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_103/__pycache__/main.cpython-313.pyc ADDED
Binary file (6.6 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_103/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": false,
3
+ "error": "operands could not be broadcast together with shapes (3,) (26,) "
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_103/results/metrics.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 0.0,
3
+ "correct": false,
4
+ "primary": {
5
+ "combined_score": 0.0,
6
+ "execution_time_mean": 0.0,
7
+ "execution_time_std": 0.0,
8
+ "num_successful_runs": 0,
9
+ "num_valid_runs": 0,
10
+ "num_invalid_runs": 0,
11
+ "all_validation_errors": [],
12
+ "correct": false,
13
+ "validation_error": "operands could not be broadcast together with shapes (3,) (26,) "
14
+ },
15
+ "auxiliary": {},
16
+ "auxiliary_descriptions": {},
17
+ "timestamp": 1770405617.0551147,
18
+ "generation": 103
19
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/__pycache__/main.cpython-313.pyc ADDED
Binary file (6.73 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/edit.diff ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ --- a/original.py
2
+ +++ b/original.py
3
+ @@ -1,185 +1,196 @@
4
+ # EVOLVE-BLOCK-START
5
+ import numpy as np
6
+
7
+ def construct_packing():
8
+ """
9
+ Constructs an optimized arrangement of 26 circles using Simulated Annealing (SA),
10
+ - enhanced with adaptive radius computation parameters, to find a high-quality packing.
11
+ + enhanced with adaptive radius computation parameters, an adaptive move strategy,
12
+ + and a longer cooling schedule to find a high-quality packing.
13
+
14
+ Returns:
15
+ A tuple containing:
16
+ centers: np.array of shape (26, 2) with the final optimized (x, y) coordinates
17
+ radii: np.array of shape (26) with the final radius of each circle
18
+ """
19
+ n = 26
20
+
21
+ # 1. Initial State and SA Parameters
22
+ # Start with a proven high-quality initial grid configuration (from prior successful programs).
23
+ centers = np.zeros((n, 2))
24
+ d = 0.09525
25
+ grid_coords = np.linspace(d, 1 - d, 5)
26
+ idx = 0
27
+ for x in grid_coords:
28
+ for y in grid_coords:
29
+ centers[idx] = [x, y]
30
+ idx += 1
31
+ - # Perturbation to break symmetry, a key element from successful priors.
32
+ - centers[25] = [0.39, 0.41]
33
+ + # Perturbation to break symmetry, now with a small random component for diversity.
34
+ + centers[25] = [0.39 + np.random.uniform(-0.01, 0.01), 0.41 + np.random.uniform(-0.01, 0.01)]
35
+
36
+ - # SA Parameters - tuned for thorough search.
37
+ + # SA Parameters - tuned for a longer, more thorough search (from a high-performing prior).
38
+ T_initial = 0.01 # Initial temperature (allows large uphill moves)
39
+ T_final = 1e-7 # Final temperature (near deterministic local search)
40
+ - alpha = 0.9998 # Cooling rate (slow, for deeper exploration)
41
+ - max_steps = 150000 # Increased steps for more thorough annealing.
42
+ + alpha = 0.99985 # Slower cooling rate for more steps
43
+ + max_steps = 200000 # Increased steps for a deeper search
44
+
45
+ # Move generation parameters
46
+ initial_move_dist = 0.08 # Max move distance at T_initial
47
+ - num_circles_to_move = 3 # Number of circles to perturb each step
48
+ + # num_circles_to_move will now be adaptive, based on temperature.
49
+
50
+ current_centers = np.copy(centers)
51
+ best_centers = np.copy(centers)
52
+
53
+ # Pre-compute schedules for adaptive quick_solve parameters, inspired by Coordinate Ascent.
54
+ # These will provide smoother transitions for evaluation accuracy.
55
+ quick_iter_schedule = np.linspace(80, 250, max_steps, dtype=int)
56
+ quick_update_schedule = np.linspace(0.75, 0.55, max_steps)
57
+
58
+ # Initial energy calculation (Energy = -Sum of Radii)
59
+ # Use the adaptive compute_max_radii, but with constant factor for initial quick evaluation.
60
+ initial_quick_solve_iter = quick_iter_schedule[0]
61
+ initial_quick_solve_uf = quick_update_schedule[0]
62
+ current_radii = compute_max_radii(current_centers, iterations=initial_quick_solve_iter,
63
+ update_factor=(initial_quick_solve_uf, initial_quick_solve_uf, 0.0))
64
+ current_energy = -np.sum(current_radii)
65
+ best_energy = current_energy
66
+
67
+ T = T_initial
68
+ step = 0
69
+
70
+ # 2. Annealing Loop
71
+ while T > T_final and step < max_steps:
72
+ # Generate a new candidate configuration
73
+ candidate_centers = np.copy(current_centers)
74
+
75
+ # Anneal the move distance based on temperature for adaptive step size.
76
+ move_dist = initial_move_dist * (T / T_initial)**0.5
77
+ +
78
+ + # Adaptive number of circles to move (crossover from another SA program)
79
+ + if T > T_initial * 0.1:
80
+ + num_circles_to_move = 4
81
+ + elif T > T_initial * 0.01:
82
+ + num_circles_to_move = 3
83
+ + elif T > T_initial * 0.001:
84
+ + num_circles_to_move = 2
85
+ + else:
86
+ + num_circles_to_move = 1
87
+
88
+ # Randomly pick a few circles to perturb for diverse exploration.
89
+ circles_to_move_indices = np.random.choice(n, num_circles_to_move, replace=False)
90
+
91
+ # Create random move vectors and apply them.
92
+ move_vectors = np.random.uniform(-move_dist, move_dist, size=(num_circles_to_move, 2))
93
+ candidate_centers[circles_to_move_indices] += move_vectors
94
+
95
+ # Clip all centers to ensure they stay within the unit square.
96
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
97
+
98
+ # Determine current quick_solve parameters from schedules for adaptive evaluation.
99
+ current_quick_solve_iter = quick_iter_schedule[step]
100
+ current_quick_solve_uf = quick_update_schedule[step]
101
+
102
+ # Calculate the energy of the new candidate using adaptive solver.
103
+ candidate_radii = compute_max_radii(candidate_centers, iterations=current_quick_solve_iter,
104
+ update_factor=(current_quick_solve_uf, current_quick_solve_uf, 0.0))
105
+ candidate_energy = -np.sum(candidate_radii)
106
+
107
+ # Metropolis-Hastings acceptance criterion: allows "uphill" moves to escape local optima.
108
+ delta_E = candidate_energy - current_energy
109
+ if delta_E < 0 or np.random.rand() < np.exp(-delta_E / T):
110
+ current_centers = candidate_centers
111
+ current_energy = candidate_energy
112
+
113
+ # Update the best-ever found solution.
114
+ if current_energy < best_energy:
115
+ best_energy = current_energy
116
+ best_centers = np.copy(current_centers)
117
+
118
+ # Cool down the temperature.
119
+ T *= alpha
120
+ step += 1
121
+
122
+ # 3. Finalization
123
+ # Run a final high-precision radius calculation on the best configuration found.
124
+ # Uses a sophisticated adaptive damping schedule for maximum accuracy and stability.
125
+ final_radii = compute_max_radii(best_centers, iterations=10000, update_factor=(0.65, 0.45, 0.25))
126
+
127
+ return best_centers, final_radii
128
+
129
+
130
+ def compute_max_radii(centers, iterations=5000, update_factor=(0.6, 0.6, 0.0)):
131
+ """
132
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
133
+ This version supports an adaptive damping schedule for the update factor.
134
+
135
+ Args:
136
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
137
+ iterations: The number of relaxation iterations to perform.
138
+ update_factor: Can be:
139
+ - A single float: constant damping factor.
140
+ - A tuple (initial_uf, final_uf, switch_ratio): adaptive damping.
141
+ `initial_uf` is used at the start, decaying linearly to `final_uf`
142
+ over `iterations * switch_ratio` steps, then `final_uf` for the rest.
143
+
144
+ Returns:
145
+ np.array of shape (n) with the radius of each circle.
146
+ """
147
+ n = centers.shape[0]
148
+ # Small non-zero start to prevent issues on the first iteration.
149
+ radii = np.full(n, 1e-6)
150
+
151
+ # Pre-calculate distances between centers.
152
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
153
+ # Set diagonal to infinity so a circle isn't constrained by itself.
154
+ np.fill_diagonal(dist_matrix, np.inf)
155
+
156
+ # Pre-calculate wall distances for all circles.
157
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
158
+
159
+ # Interpret update_factor parameter for adaptive damping.
160
+ if isinstance(update_factor, (float, int)):
161
+ initial_uf = float(update_factor)
162
+ final_uf = float(update_factor)
163
+ switch_ratio = 0.0 # No adaptive schedule if a single float is provided
164
+ else: # Expecting a tuple (initial_uf, final_uf, switch_ratio)
165
+ initial_uf, final_uf, switch_ratio = update_factor
166
+
167
+ for k in range(iterations):
168
+ radii_old = np.copy(radii)
169
+
170
+ # Determine current damping factor based on iteration progress and schedule.
171
+ current_uf = initial_uf
172
+ if switch_ratio > 0 and k < iterations * switch_ratio:
173
+ # Linear interpolation from initial_uf to final_uf over the switch_ratio duration
174
+ current_uf = initial_uf + (final_uf - initial_uf) * (k / (iterations * switch_ratio))
175
+ elif switch_ratio > 0 and k >= iterations * switch_ratio:
176
+ # After the switch point, use the final damping factor
177
+ current_uf = final_uf
178
+ # If switch_ratio is 0, current_uf remains initial_uf as initialized above.
179
+
180
+ # Calculate all potential radii based on other circles in a vectorized way.
181
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
182
+
183
+ # Combine with wall constraints.
184
+ potential_r = np.minimum(wall_dists, potential_r_circles)
185
+
186
+ # New radii for this iteration (must be non-negative).
187
+ new_r = np.maximum(0.0, potential_r)
188
+
189
+ # Dampen the update to prevent oscillations.
190
+ radii = radii_old + current_uf * (new_r - radii_old)
191
+
192
+ # Early exit condition if radii have converged.
193
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
194
+ break
195
+
196
+ return radii
197
+ # EVOLVE-BLOCK-END
198
+
199
+
200
+ # This part remains fixed (not evolved)
201
+ def run_packing():
202
+ """Run the circle packing constructor for n=26"""
203
+ centers, radii = construct_packing()
204
+ # Calculate the sum of radii
205
+ sum_radii = np.sum(radii)
206
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/main.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ import numpy as np
3
+
4
+ def construct_packing():
5
+ """
6
+ Constructs an optimized arrangement of 26 circles using Simulated Annealing (SA),
7
+ enhanced with adaptive radius computation parameters, an adaptive move strategy,
8
+ and a longer cooling schedule to find a high-quality packing.
9
+
10
+ Returns:
11
+ A tuple containing:
12
+ centers: np.array of shape (26, 2) with the final optimized (x, y) coordinates
13
+ radii: np.array of shape (26) with the final radius of each circle
14
+ """
15
+ n = 26
16
+
17
+ # 1. Initial State and SA Parameters
18
+ # Start with a proven high-quality initial grid configuration (from prior successful programs).
19
+ centers = np.zeros((n, 2))
20
+ d = 0.09525
21
+ grid_coords = np.linspace(d, 1 - d, 5)
22
+ idx = 0
23
+ for x in grid_coords:
24
+ for y in grid_coords:
25
+ centers[idx] = [x, y]
26
+ idx += 1
27
+ # Perturbation to break symmetry, now with a small random component for diversity.
28
+ centers[25] = [0.39 + np.random.uniform(-0.01, 0.01), 0.41 + np.random.uniform(-0.01, 0.01)]
29
+
30
+ # SA Parameters - tuned for a longer, more thorough search (from a high-performing prior).
31
+ T_initial = 0.01 # Initial temperature (allows large uphill moves)
32
+ T_final = 1e-7 # Final temperature (near deterministic local search)
33
+ alpha = 0.99985 # Slower cooling rate for more steps
34
+ max_steps = 200000 # Increased steps for a deeper search
35
+
36
+ # Move generation parameters
37
+ initial_move_dist = 0.08 # Max move distance at T_initial
38
+ # num_circles_to_move will now be adaptive, based on temperature.
39
+
40
+ current_centers = np.copy(centers)
41
+ best_centers = np.copy(centers)
42
+
43
+ # Pre-compute schedules for adaptive quick_solve parameters, inspired by Coordinate Ascent.
44
+ # These will provide smoother transitions for evaluation accuracy.
45
+ quick_iter_schedule = np.linspace(80, 250, max_steps, dtype=int)
46
+ quick_update_schedule = np.linspace(0.75, 0.55, max_steps)
47
+
48
+ # Initial energy calculation (Energy = -Sum of Radii)
49
+ # Use the adaptive compute_max_radii, but with constant factor for initial quick evaluation.
50
+ initial_quick_solve_iter = quick_iter_schedule[0]
51
+ initial_quick_solve_uf = quick_update_schedule[0]
52
+ current_radii = compute_max_radii(current_centers, iterations=initial_quick_solve_iter,
53
+ update_factor=(initial_quick_solve_uf, initial_quick_solve_uf, 0.0))
54
+ current_energy = -np.sum(current_radii)
55
+ best_energy = current_energy
56
+
57
+ T = T_initial
58
+ step = 0
59
+
60
+ # 2. Annealing Loop
61
+ while T > T_final and step < max_steps:
62
+ # Generate a new candidate configuration
63
+ candidate_centers = np.copy(current_centers)
64
+
65
+ # Anneal the move distance based on temperature for adaptive step size.
66
+ move_dist = initial_move_dist * (T / T_initial)**0.5
67
+
68
+ # Adaptive number of circles to move (crossover from another SA program)
69
+ if T > T_initial * 0.1:
70
+ num_circles_to_move = 4
71
+ elif T > T_initial * 0.01:
72
+ num_circles_to_move = 3
73
+ elif T > T_initial * 0.001:
74
+ num_circles_to_move = 2
75
+ else:
76
+ num_circles_to_move = 1
77
+
78
+ # Randomly pick a few circles to perturb for diverse exploration.
79
+ circles_to_move_indices = np.random.choice(n, num_circles_to_move, replace=False)
80
+
81
+ # Create random move vectors and apply them.
82
+ move_vectors = np.random.uniform(-move_dist, move_dist, size=(num_circles_to_move, 2))
83
+ candidate_centers[circles_to_move_indices] += move_vectors
84
+
85
+ # Clip all centers to ensure they stay within the unit square.
86
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
87
+
88
+ # Determine current quick_solve parameters from schedules for adaptive evaluation.
89
+ current_quick_solve_iter = quick_iter_schedule[step]
90
+ current_quick_solve_uf = quick_update_schedule[step]
91
+
92
+ # Calculate the energy of the new candidate using adaptive solver.
93
+ candidate_radii = compute_max_radii(candidate_centers, iterations=current_quick_solve_iter,
94
+ update_factor=(current_quick_solve_uf, current_quick_solve_uf, 0.0))
95
+ candidate_energy = -np.sum(candidate_radii)
96
+
97
+ # Metropolis-Hastings acceptance criterion: allows "uphill" moves to escape local optima.
98
+ delta_E = candidate_energy - current_energy
99
+ if delta_E < 0 or np.random.rand() < np.exp(-delta_E / T):
100
+ current_centers = candidate_centers
101
+ current_energy = candidate_energy
102
+
103
+ # Update the best-ever found solution.
104
+ if current_energy < best_energy:
105
+ best_energy = current_energy
106
+ best_centers = np.copy(current_centers)
107
+
108
+ # Cool down the temperature.
109
+ T *= alpha
110
+ step += 1
111
+
112
+ # 3. Finalization
113
+ # Run a final high-precision radius calculation on the best configuration found.
114
+ # Uses a sophisticated adaptive damping schedule for maximum accuracy and stability.
115
+ final_radii = compute_max_radii(best_centers, iterations=10000, update_factor=(0.65, 0.45, 0.25))
116
+
117
+ return best_centers, final_radii
118
+
119
+
120
+ def compute_max_radii(centers, iterations=5000, update_factor=(0.6, 0.6, 0.0)):
121
+ """
122
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
123
+ This version supports an adaptive damping schedule for the update factor.
124
+
125
+ Args:
126
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
127
+ iterations: The number of relaxation iterations to perform.
128
+ update_factor: Can be:
129
+ - A single float: constant damping factor.
130
+ - A tuple (initial_uf, final_uf, switch_ratio): adaptive damping.
131
+ `initial_uf` is used at the start, decaying linearly to `final_uf`
132
+ over `iterations * switch_ratio` steps, then `final_uf` for the rest.
133
+
134
+ Returns:
135
+ np.array of shape (n) with the radius of each circle.
136
+ """
137
+ n = centers.shape[0]
138
+ # Small non-zero start to prevent issues on the first iteration.
139
+ radii = np.full(n, 1e-6)
140
+
141
+ # Pre-calculate distances between centers.
142
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
143
+ # Set diagonal to infinity so a circle isn't constrained by itself.
144
+ np.fill_diagonal(dist_matrix, np.inf)
145
+
146
+ # Pre-calculate wall distances for all circles.
147
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
148
+
149
+ # Interpret update_factor parameter for adaptive damping.
150
+ if isinstance(update_factor, (float, int)):
151
+ initial_uf = float(update_factor)
152
+ final_uf = float(update_factor)
153
+ switch_ratio = 0.0 # No adaptive schedule if a single float is provided
154
+ else: # Expecting a tuple (initial_uf, final_uf, switch_ratio)
155
+ initial_uf, final_uf, switch_ratio = update_factor
156
+
157
+ for k in range(iterations):
158
+ radii_old = np.copy(radii)
159
+
160
+ # Determine current damping factor based on iteration progress and schedule.
161
+ current_uf = initial_uf
162
+ if switch_ratio > 0 and k < iterations * switch_ratio:
163
+ # Linear interpolation from initial_uf to final_uf over the switch_ratio duration
164
+ current_uf = initial_uf + (final_uf - initial_uf) * (k / (iterations * switch_ratio))
165
+ elif switch_ratio > 0 and k >= iterations * switch_ratio:
166
+ # After the switch point, use the final damping factor
167
+ current_uf = final_uf
168
+ # If switch_ratio is 0, current_uf remains initial_uf as initialized above.
169
+
170
+ # Calculate all potential radii based on other circles in a vectorized way.
171
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
172
+
173
+ # Combine with wall constraints.
174
+ potential_r = np.minimum(wall_dists, potential_r_circles)
175
+
176
+ # New radii for this iteration (must be non-negative).
177
+ new_r = np.maximum(0.0, potential_r)
178
+
179
+ # Dampen the update to prevent oscillations.
180
+ radii = radii_old + current_uf * (new_r - radii_old)
181
+
182
+ # Early exit condition if radii have converged.
183
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
184
+ break
185
+
186
+ return radii
187
+ # EVOLVE-BLOCK-END
188
+
189
+
190
+ # This part remains fixed (not evolved)
191
+ def run_packing():
192
+ """Run the circle packing constructor for n=26"""
193
+ centers, radii = construct_packing()
194
+ # Calculate the sum of radii
195
+ sum_radii = np.sum(radii)
196
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/original.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ import numpy as np
3
+
4
+ def construct_packing():
5
+ """
6
+ Constructs an optimized arrangement of 26 circles using Simulated Annealing (SA),
7
+ enhanced with adaptive radius computation parameters, to find a high-quality packing.
8
+
9
+ Returns:
10
+ A tuple containing:
11
+ centers: np.array of shape (26, 2) with the final optimized (x, y) coordinates
12
+ radii: np.array of shape (26) with the final radius of each circle
13
+ """
14
+ n = 26
15
+
16
+ # 1. Initial State and SA Parameters
17
+ # Start with a proven high-quality initial grid configuration (from prior successful programs).
18
+ centers = np.zeros((n, 2))
19
+ d = 0.09525
20
+ grid_coords = np.linspace(d, 1 - d, 5)
21
+ idx = 0
22
+ for x in grid_coords:
23
+ for y in grid_coords:
24
+ centers[idx] = [x, y]
25
+ idx += 1
26
+ # Perturbation to break symmetry, a key element from successful priors.
27
+ centers[25] = [0.39, 0.41]
28
+
29
+ # SA Parameters - tuned for thorough search.
30
+ T_initial = 0.01 # Initial temperature (allows large uphill moves)
31
+ T_final = 1e-7 # Final temperature (near deterministic local search)
32
+ alpha = 0.9998 # Cooling rate (slow, for deeper exploration)
33
+ max_steps = 150000 # Increased steps for more thorough annealing.
34
+
35
+ # Move generation parameters
36
+ initial_move_dist = 0.08 # Max move distance at T_initial
37
+ num_circles_to_move = 3 # Number of circles to perturb each step
38
+
39
+ current_centers = np.copy(centers)
40
+ best_centers = np.copy(centers)
41
+
42
+ # Pre-compute schedules for adaptive quick_solve parameters, inspired by Coordinate Ascent.
43
+ # These will provide smoother transitions for evaluation accuracy.
44
+ quick_iter_schedule = np.linspace(80, 250, max_steps, dtype=int)
45
+ quick_update_schedule = np.linspace(0.75, 0.55, max_steps)
46
+
47
+ # Initial energy calculation (Energy = -Sum of Radii)
48
+ # Use the adaptive compute_max_radii, but with constant factor for initial quick evaluation.
49
+ initial_quick_solve_iter = quick_iter_schedule[0]
50
+ initial_quick_solve_uf = quick_update_schedule[0]
51
+ current_radii = compute_max_radii(current_centers, iterations=initial_quick_solve_iter,
52
+ update_factor=(initial_quick_solve_uf, initial_quick_solve_uf, 0.0))
53
+ current_energy = -np.sum(current_radii)
54
+ best_energy = current_energy
55
+
56
+ T = T_initial
57
+ step = 0
58
+
59
+ # 2. Annealing Loop
60
+ while T > T_final and step < max_steps:
61
+ # Generate a new candidate configuration
62
+ candidate_centers = np.copy(current_centers)
63
+
64
+ # Anneal the move distance based on temperature for adaptive step size.
65
+ move_dist = initial_move_dist * (T / T_initial)**0.5
66
+
67
+ # Randomly pick a few circles to perturb for diverse exploration.
68
+ circles_to_move_indices = np.random.choice(n, num_circles_to_move, replace=False)
69
+
70
+ # Create random move vectors and apply them.
71
+ move_vectors = np.random.uniform(-move_dist, move_dist, size=(num_circles_to_move, 2))
72
+ candidate_centers[circles_to_move_indices] += move_vectors
73
+
74
+ # Clip all centers to ensure they stay within the unit square.
75
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
76
+
77
+ # Determine current quick_solve parameters from schedules for adaptive evaluation.
78
+ current_quick_solve_iter = quick_iter_schedule[step]
79
+ current_quick_solve_uf = quick_update_schedule[step]
80
+
81
+ # Calculate the energy of the new candidate using adaptive solver.
82
+ candidate_radii = compute_max_radii(candidate_centers, iterations=current_quick_solve_iter,
83
+ update_factor=(current_quick_solve_uf, current_quick_solve_uf, 0.0))
84
+ candidate_energy = -np.sum(candidate_radii)
85
+
86
+ # Metropolis-Hastings acceptance criterion: allows "uphill" moves to escape local optima.
87
+ delta_E = candidate_energy - current_energy
88
+ if delta_E < 0 or np.random.rand() < np.exp(-delta_E / T):
89
+ current_centers = candidate_centers
90
+ current_energy = candidate_energy
91
+
92
+ # Update the best-ever found solution.
93
+ if current_energy < best_energy:
94
+ best_energy = current_energy
95
+ best_centers = np.copy(current_centers)
96
+
97
+ # Cool down the temperature.
98
+ T *= alpha
99
+ step += 1
100
+
101
+ # 3. Finalization
102
+ # Run a final high-precision radius calculation on the best configuration found.
103
+ # Uses a sophisticated adaptive damping schedule for maximum accuracy and stability.
104
+ final_radii = compute_max_radii(best_centers, iterations=10000, update_factor=(0.65, 0.45, 0.25))
105
+
106
+ return best_centers, final_radii
107
+
108
+
109
+ def compute_max_radii(centers, iterations=5000, update_factor=(0.6, 0.6, 0.0)):
110
+ """
111
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
112
+ This version supports an adaptive damping schedule for the update factor.
113
+
114
+ Args:
115
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
116
+ iterations: The number of relaxation iterations to perform.
117
+ update_factor: Can be:
118
+ - A single float: constant damping factor.
119
+ - A tuple (initial_uf, final_uf, switch_ratio): adaptive damping.
120
+ `initial_uf` is used at the start, decaying linearly to `final_uf`
121
+ over `iterations * switch_ratio` steps, then `final_uf` for the rest.
122
+
123
+ Returns:
124
+ np.array of shape (n) with the radius of each circle.
125
+ """
126
+ n = centers.shape[0]
127
+ # Small non-zero start to prevent issues on the first iteration.
128
+ radii = np.full(n, 1e-6)
129
+
130
+ # Pre-calculate distances between centers.
131
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
132
+ # Set diagonal to infinity so a circle isn't constrained by itself.
133
+ np.fill_diagonal(dist_matrix, np.inf)
134
+
135
+ # Pre-calculate wall distances for all circles.
136
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
137
+
138
+ # Interpret update_factor parameter for adaptive damping.
139
+ if isinstance(update_factor, (float, int)):
140
+ initial_uf = float(update_factor)
141
+ final_uf = float(update_factor)
142
+ switch_ratio = 0.0 # No adaptive schedule if a single float is provided
143
+ else: # Expecting a tuple (initial_uf, final_uf, switch_ratio)
144
+ initial_uf, final_uf, switch_ratio = update_factor
145
+
146
+ for k in range(iterations):
147
+ radii_old = np.copy(radii)
148
+
149
+ # Determine current damping factor based on iteration progress and schedule.
150
+ current_uf = initial_uf
151
+ if switch_ratio > 0 and k < iterations * switch_ratio:
152
+ # Linear interpolation from initial_uf to final_uf over the switch_ratio duration
153
+ current_uf = initial_uf + (final_uf - initial_uf) * (k / (iterations * switch_ratio))
154
+ elif switch_ratio > 0 and k >= iterations * switch_ratio:
155
+ # After the switch point, use the final damping factor
156
+ current_uf = final_uf
157
+ # If switch_ratio is 0, current_uf remains initial_uf as initialized above.
158
+
159
+ # Calculate all potential radii based on other circles in a vectorized way.
160
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
161
+
162
+ # Combine with wall constraints.
163
+ potential_r = np.minimum(wall_dists, potential_r_circles)
164
+
165
+ # New radii for this iteration (must be non-negative).
166
+ new_r = np.maximum(0.0, potential_r)
167
+
168
+ # Dampen the update to prevent oscillations.
169
+ radii = radii_old + current_uf * (new_r - radii_old)
170
+
171
+ # Early exit condition if radii have converged.
172
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
173
+ break
174
+
175
+ return radii
176
+ # EVOLVE-BLOCK-END
177
+
178
+
179
+ # This part remains fixed (not evolved)
180
+ def run_packing():
181
+ """Run the circle packing constructor for n=26"""
182
+ centers, radii = construct_packing()
183
+ # Calculate the sum of radii
184
+ sum_radii = np.sum(radii)
185
+ return centers, radii, sum_radii
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/results/metrics.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 2.5368049435910565,
3
+ "correct": true,
4
+ "primary": {
5
+ "combined_score": 2.5368049435910565,
6
+ "public": {
7
+ "centers_str": " centers[0] = (0.1099, 0.1236)\n centers[1] = (0.0707, 0.3000)\n centers[2] = (0.1128, 0.4787)\n centers[3] = (0.0988, 0.6938)\n centers[4] = (0.1037, 0.8962)\n centers[5] = (0.3104, 0.0928)\n centers[6] = (0.2609, 0.2991)\n centers[7] = (0.2872, 0.5195)\n centers[8] = (0.2879, 0.6832)\n centers[9] = (0.3208, 0.8852)\n centers[10] = (0.4911, 0.0880)\n centers[11] = (0.4930, 0.2886)\n centers[12] = (0.5326, 0.5010)\n centers[13] = (0.4947, 0.7079)\n centers[14] = (0.5188, 0.9104)\n centers[15] = (0.7014, 0.1256)\n centers[16] = (0.6840, 0.3343)\n centers[17] = (0.7089, 0.4999)\n centers[18] = (0.7335, 0.7044)\n centers[19] = (0.6901, 0.9144)\n centers[20] = (0.9125, 0.0874)\n centers[21] = (0.8815, 0.2909)\n centers[22] = (0.8961, 0.5141)\n centers[23] = (0.9270, 0.6884)\n centers[24] = (0.8865, 0.8823)\n centers[25] = (0.3886, 0.4340)",
8
+ "num_circles": 26
9
+ },
10
+ "private": {
11
+ "reported_sum_of_radii": 2.5368049435910565
12
+ },
13
+ "execution_time_mean": 43.77116736583412,
14
+ "execution_time_std": 0.0,
15
+ "num_valid_runs": 1,
16
+ "num_invalid_runs": 0,
17
+ "all_validation_errors": [],
18
+ "correct": true,
19
+ "validation_error": null
20
+ },
21
+ "auxiliary": {},
22
+ "auxiliary_descriptions": {},
23
+ "timestamp": 1770405697.9377902,
24
+ "generation": 104
25
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_104/rewrite.txt ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EVOLVE-BLOCK-START
2
+ import numpy as np
3
+
4
+ def construct_packing():
5
+ """
6
+ Constructs an optimized arrangement of 26 circles using Simulated Annealing (SA),
7
+ enhanced with adaptive radius computation parameters, an adaptive move strategy,
8
+ and a longer cooling schedule to find a high-quality packing.
9
+
10
+ Returns:
11
+ A tuple containing:
12
+ centers: np.array of shape (26, 2) with the final optimized (x, y) coordinates
13
+ radii: np.array of shape (26) with the final radius of each circle
14
+ """
15
+ n = 26
16
+
17
+ # 1. Initial State and SA Parameters
18
+ # Start with a proven high-quality initial grid configuration (from prior successful programs).
19
+ centers = np.zeros((n, 2))
20
+ d = 0.09525
21
+ grid_coords = np.linspace(d, 1 - d, 5)
22
+ idx = 0
23
+ for x in grid_coords:
24
+ for y in grid_coords:
25
+ centers[idx] = [x, y]
26
+ idx += 1
27
+ # Perturbation to break symmetry, now with a small random component for diversity.
28
+ centers[25] = [0.39 + np.random.uniform(-0.01, 0.01), 0.41 + np.random.uniform(-0.01, 0.01)]
29
+
30
+ # SA Parameters - tuned for a longer, more thorough search (from a high-performing prior).
31
+ T_initial = 0.01 # Initial temperature (allows large uphill moves)
32
+ T_final = 1e-7 # Final temperature (near deterministic local search)
33
+ alpha = 0.99985 # Slower cooling rate for more steps
34
+ max_steps = 200000 # Increased steps for a deeper search
35
+
36
+ # Move generation parameters
37
+ initial_move_dist = 0.08 # Max move distance at T_initial
38
+ # num_circles_to_move will now be adaptive, based on temperature.
39
+
40
+ current_centers = np.copy(centers)
41
+ best_centers = np.copy(centers)
42
+
43
+ # Pre-compute schedules for adaptive quick_solve parameters, inspired by Coordinate Ascent.
44
+ # These will provide smoother transitions for evaluation accuracy.
45
+ quick_iter_schedule = np.linspace(80, 250, max_steps, dtype=int)
46
+ quick_update_schedule = np.linspace(0.75, 0.55, max_steps)
47
+
48
+ # Initial energy calculation (Energy = -Sum of Radii)
49
+ # Use the adaptive compute_max_radii, but with constant factor for initial quick evaluation.
50
+ initial_quick_solve_iter = quick_iter_schedule[0]
51
+ initial_quick_solve_uf = quick_update_schedule[0]
52
+ current_radii = compute_max_radii(current_centers, iterations=initial_quick_solve_iter,
53
+ update_factor=(initial_quick_solve_uf, initial_quick_solve_uf, 0.0))
54
+ current_energy = -np.sum(current_radii)
55
+ best_energy = current_energy
56
+
57
+ T = T_initial
58
+ step = 0
59
+
60
+ # 2. Annealing Loop
61
+ while T > T_final and step < max_steps:
62
+ # Generate a new candidate configuration
63
+ candidate_centers = np.copy(current_centers)
64
+
65
+ # Anneal the move distance based on temperature for adaptive step size.
66
+ move_dist = initial_move_dist * (T / T_initial)**0.5
67
+
68
+ # Adaptive number of circles to move (crossover from another SA program)
69
+ if T > T_initial * 0.1:
70
+ num_circles_to_move = 4
71
+ elif T > T_initial * 0.01:
72
+ num_circles_to_move = 3
73
+ elif T > T_initial * 0.001:
74
+ num_circles_to_move = 2
75
+ else:
76
+ num_circles_to_move = 1
77
+
78
+ # Randomly pick a few circles to perturb for diverse exploration.
79
+ circles_to_move_indices = np.random.choice(n, num_circles_to_move, replace=False)
80
+
81
+ # Create random move vectors and apply them.
82
+ move_vectors = np.random.uniform(-move_dist, move_dist, size=(num_circles_to_move, 2))
83
+ candidate_centers[circles_to_move_indices] += move_vectors
84
+
85
+ # Clip all centers to ensure they stay within the unit square.
86
+ candidate_centers = np.clip(candidate_centers, 0.0, 1.0)
87
+
88
+ # Determine current quick_solve parameters from schedules for adaptive evaluation.
89
+ current_quick_solve_iter = quick_iter_schedule[step]
90
+ current_quick_solve_uf = quick_update_schedule[step]
91
+
92
+ # Calculate the energy of the new candidate using adaptive solver.
93
+ candidate_radii = compute_max_radii(candidate_centers, iterations=current_quick_solve_iter,
94
+ update_factor=(current_quick_solve_uf, current_quick_solve_uf, 0.0))
95
+ candidate_energy = -np.sum(candidate_radii)
96
+
97
+ # Metropolis-Hastings acceptance criterion: allows "uphill" moves to escape local optima.
98
+ delta_E = candidate_energy - current_energy
99
+ if delta_E < 0 or np.random.rand() < np.exp(-delta_E / T):
100
+ current_centers = candidate_centers
101
+ current_energy = candidate_energy
102
+
103
+ # Update the best-ever found solution.
104
+ if current_energy < best_energy:
105
+ best_energy = current_energy
106
+ best_centers = np.copy(current_centers)
107
+
108
+ # Cool down the temperature.
109
+ T *= alpha
110
+ step += 1
111
+
112
+ # 3. Finalization
113
+ # Run a final high-precision radius calculation on the best configuration found.
114
+ # Uses a sophisticated adaptive damping schedule for maximum accuracy and stability.
115
+ final_radii = compute_max_radii(best_centers, iterations=10000, update_factor=(0.65, 0.45, 0.25))
116
+
117
+ return best_centers, final_radii
118
+
119
+
120
+ def compute_max_radii(centers, iterations=5000, update_factor=(0.6, 0.6, 0.0)):
121
+ """
122
+ Computes maximum radii using a fast, vectorized, damped Jacobi-style solver.
123
+ This version supports an adaptive damping schedule for the update factor.
124
+
125
+ Args:
126
+ centers: np.array of shape (n, 2) with (x, y) coordinates.
127
+ iterations: The number of relaxation iterations to perform.
128
+ update_factor: Can be:
129
+ - A single float: constant damping factor.
130
+ - A tuple (initial_uf, final_uf, switch_ratio): adaptive damping.
131
+ `initial_uf` is used at the start, decaying linearly to `final_uf`
132
+ over `iterations * switch_ratio` steps, then `final_uf` for the rest.
133
+
134
+ Returns:
135
+ np.array of shape (n) with the radius of each circle.
136
+ """
137
+ n = centers.shape[0]
138
+ # Small non-zero start to prevent issues on the first iteration.
139
+ radii = np.full(n, 1e-6)
140
+
141
+ # Pre-calculate distances between centers.
142
+ dist_matrix = np.sqrt(((centers[:, np.newaxis, :] - centers[np.newaxis, :, :])**2).sum(axis=2))
143
+ # Set diagonal to infinity so a circle isn't constrained by itself.
144
+ np.fill_diagonal(dist_matrix, np.inf)
145
+
146
+ # Pre-calculate wall distances for all circles.
147
+ wall_dists = np.min(np.hstack([centers, 1.0 - centers]), axis=1)
148
+
149
+ # Interpret update_factor parameter for adaptive damping.
150
+ if isinstance(update_factor, (float, int)):
151
+ initial_uf = float(update_factor)
152
+ final_uf = float(update_factor)
153
+ switch_ratio = 0.0 # No adaptive schedule if a single float is provided
154
+ else: # Expecting a tuple (initial_uf, final_uf, switch_ratio)
155
+ initial_uf, final_uf, switch_ratio = update_factor
156
+
157
+ for k in range(iterations):
158
+ radii_old = np.copy(radii)
159
+
160
+ # Determine current damping factor based on iteration progress and schedule.
161
+ current_uf = initial_uf
162
+ if switch_ratio > 0 and k < iterations * switch_ratio:
163
+ # Linear interpolation from initial_uf to final_uf over the switch_ratio duration
164
+ current_uf = initial_uf + (final_uf - initial_uf) * (k / (iterations * switch_ratio))
165
+ elif switch_ratio > 0 and k >= iterations * switch_ratio:
166
+ # After the switch point, use the final damping factor
167
+ current_uf = final_uf
168
+ # If switch_ratio is 0, current_uf remains initial_uf as initialized above.
169
+
170
+ # Calculate all potential radii based on other circles in a vectorized way.
171
+ potential_r_circles = np.min(dist_matrix - radii_old, axis=1)
172
+
173
+ # Combine with wall constraints.
174
+ potential_r = np.minimum(wall_dists, potential_r_circles)
175
+
176
+ # New radii for this iteration (must be non-negative).
177
+ new_r = np.maximum(0.0, potential_r)
178
+
179
+ # Dampen the update to prevent oscillations.
180
+ radii = radii_old + current_uf * (new_r - radii_old)
181
+
182
+ # Early exit condition if radii have converged.
183
+ if np.max(np.abs(radii - radii_old)) < 1e-9:
184
+ break
185
+
186
+ return radii
187
+ # EVOLVE-BLOCK-END
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_105/__pycache__/main.cpython-313.pyc ADDED
Binary file (5.41 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_105/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": false,
3
+ "error": "operands could not be broadcast together with shapes (3,) (26,) "
4
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_105/results/metrics.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "combined_score": 0.0,
3
+ "correct": false,
4
+ "primary": {
5
+ "combined_score": 0.0,
6
+ "execution_time_mean": 0.0,
7
+ "execution_time_std": 0.0,
8
+ "num_successful_runs": 0,
9
+ "num_valid_runs": 0,
10
+ "num_invalid_runs": 0,
11
+ "all_validation_errors": [],
12
+ "correct": false,
13
+ "validation_error": "operands could not be broadcast together with shapes (3,) (26,) "
14
+ },
15
+ "auxiliary": {},
16
+ "auxiliary_descriptions": {},
17
+ "timestamp": 1770405677.2668953,
18
+ "generation": 105
19
+ }
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_106/__pycache__/main.cpython-313.pyc ADDED
Binary file (7.16 kB). View file
 
examples_deprecated/circle_packing/results/results_full_gen200_period1000_20260206_165141/gen_106/results/correct.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "correct": true,
3
+ "error": null
4
+ }