Skip to content

Commit 91467e6

Browse files
committed
Merge branch 'main' into pr/73
2 parents 675ae97 + fa1ff18 commit 91467e6

29 files changed

+7893
-45
lines changed

.github/workflows/release.yml

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: Upload Python Package and Docker Image on Release
2+
on:
3+
release:
4+
types: [created]
5+
6+
jobs:
7+
pypi-publish:
8+
name: Publish release to PyPI
9+
runs-on: ubuntu-latest
10+
environment:
11+
name: pypi
12+
url: https://pypi.org/p/openevolve
13+
permissions:
14+
id-token: write
15+
steps:
16+
- uses: actions/checkout@v4
17+
- name: Set up Python
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: "3.x"
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install build
25+
- name: Build package
26+
run: |
27+
python -m build
28+
- name: Publish package distributions to PyPI
29+
uses: pypa/gh-action-pypi-publish@release/v1
30+
31+
docker-publish:
32+
name: Publish Docker image
33+
runs-on: ubuntu-22.04
34+
needs: pypi-publish
35+
permissions:
36+
contents: read
37+
packages: write
38+
steps:
39+
- uses: actions/checkout@v4
40+
41+
# Add aggressive cleanup before any Docker operations
42+
- name: Free disk space
43+
run: |
44+
# Clean Docker
45+
docker system prune -af
46+
docker image prune -af
47+
docker builder prune -af
48+
49+
df -h
50+
51+
- name: Set up QEMU
52+
uses: docker/setup-qemu-action@v3
53+
54+
- name: Set up Docker Buildx
55+
uses: docker/setup-buildx-action@v3
56+
with:
57+
driver-opts: |
58+
image=moby/buildkit:buildx-stable-1
59+
network=host
60+
buildkitd-flags: --debug
61+
62+
- name: Log in to GitHub Container Registry
63+
uses: docker/login-action@v3
64+
with:
65+
registry: ghcr.io
66+
username: ${{ github.actor }}
67+
password: ${{ secrets.GITHUB_TOKEN }}
68+
69+
# Extract metadata for Docker image
70+
- name: Extract metadata for Docker
71+
id: meta
72+
uses: docker/metadata-action@v5
73+
with:
74+
images: ghcr.io/${{ github.repository }}
75+
tags: |
76+
type=semver,pattern={{version}}
77+
type=semver,pattern={{major}}.{{minor}}
78+
type=raw,value=latest
79+
80+
# Build and push Docker image for AMD64
81+
- name: Build and push Docker image AMD64
82+
uses: docker/build-push-action@v5
83+
with:
84+
context: .
85+
file: Dockerfile
86+
push: true
87+
platforms: linux/amd64
88+
tags: ${{ steps.meta.outputs.tags }}
89+
labels: ${{ steps.meta.outputs.labels }}
90+
cache-from: type=gha,scope=openevolve-amd64
91+
cache-to: type=gha,scope=openevolve-amd64,mode=max
92+
outputs: type=registry,compression=zstd,compression-level=5
93+
94+
# Cleanup after AMD64 build
95+
- name: Cleanup after AMD64 build
96+
run: |
97+
docker system prune -af
98+
docker builder prune -af
99+
df -h
100+
101+
# Build and push Docker image for ARM64
102+
- name: Build and push Docker image ARM64
103+
uses: docker/build-push-action@v5
104+
with:
105+
context: .
106+
file: Dockerfile
107+
push: true
108+
platforms: linux/arm64
109+
tags: ${{ steps.meta.outputs.tags }}
110+
labels: ${{ steps.meta.outputs.labels }}
111+
cache-from: type=gha,scope=openevolve-arm64
112+
cache-to: type=gha,scope=openevolve-arm64,mode=max
113+
outputs: type=registry,compression=zstd,compression-level=5
114+
115+
# Final cleanup
116+
- name: Final cleanup
117+
run: |
118+
docker system prune -af
119+
docker builder prune -af
120+
find /tmp -type f -user $(id -u) -exec rm -f {} + 2>/dev/null || true
121+
df -h
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# EVOLVE-BLOCK-START
2+
"""Advanced circle packing for n=26 circles in a unit square"""
3+
import numpy as np
4+
from scipy.optimize import minimize
5+
6+
7+
def construct_packing():
8+
"""
9+
Construct an optimized arrangement of 26 circles in a unit square
10+
using mathematical principles and optimization techniques.
11+
12+
Returns:
13+
Tuple of (centers, radii, sum_of_radii)
14+
centers: np.array of shape (26, 2) with (x, y) coordinates
15+
radii: np.array of shape (26) with radius of each circle
16+
sum_of_radii: Sum of all radii
17+
"""
18+
n = 26
19+
20+
# Initial guess: Strategic placement with some randomness
21+
centers = np.zeros((n, 2))
22+
radii = np.zeros(n)
23+
24+
# Heuristic placement for better initial guess: place larger circles in center
25+
radii[:] = np.linspace(0.12, 0.05, n) # Linear distribution of radii
26+
27+
# Initial placement: approximate hexagonal grid
28+
grid_x = int(np.sqrt(n))
29+
grid_y = int(n / grid_x)
30+
31+
x_coords = np.linspace(0.15, 0.85, grid_x)
32+
y_coords = np.linspace(0.15, 0.85, grid_y)
33+
34+
count = 0
35+
for i in range(grid_x):
36+
for j in range(grid_y):
37+
if count < n:
38+
centers[count] = [x_coords[i] + 0.05 * (j % 2), y_coords[j]]
39+
count += 1
40+
41+
# Place remaining circles randomly
42+
while count < n:
43+
centers[count] = np.random.rand(2) * 0.7 + 0.15
44+
count += 1
45+
46+
# Objective function: Negative sum of radii (to maximize)
47+
def objective(x):
48+
centers = x[: 2 * n].reshape(n, 2)
49+
radii = x[2 * n :]
50+
return -np.sum(radii)
51+
52+
# Constraint: No overlaps and circles stay within the unit square
53+
def constraint(x):
54+
centers = x[: 2 * n].reshape(n, 2)
55+
radii = x[2 * n :]
56+
57+
# Overlap constraint
58+
overlap_constraints = []
59+
for i in range(n):
60+
for j in range(i + 1, n):
61+
dist = np.sqrt(np.sum((centers[i] - centers[j]) ** 2))
62+
overlap_constraints.append(dist - (radii[i] + radii[j]))
63+
64+
# Boundary constraints
65+
boundary_constraints = []
66+
for i in range(n):
67+
boundary_constraints.append(centers[i, 0] - radii[i]) # x >= radius
68+
boundary_constraints.append(1 - centers[i, 0] - radii[i]) # x <= 1 - radius
69+
boundary_constraints.append(centers[i, 1] - radii[i]) # y >= radius
70+
boundary_constraints.append(1 - centers[i, 1] - radii[i]) # y <= 1 - radius
71+
72+
return np.array(overlap_constraints + boundary_constraints)
73+
74+
# Initial guess vector
75+
x0 = np.concatenate([centers.flatten(), radii])
76+
77+
# Bounds: Circles stay within the unit square and radii are positive
78+
bounds = [(0, 1)] * (2 * n) + [(0.03, 0.2)] * n # radii are positive, up to 0.2
79+
80+
# Constraints dictionary
81+
constraints = {"type": "ineq", "fun": constraint}
82+
83+
# Optimization using SLSQP
84+
result = minimize(
85+
objective,
86+
x0,
87+
method="SLSQP",
88+
bounds=bounds,
89+
constraints=constraints,
90+
options={"maxiter": 1000, "ftol": 1e-8},
91+
)
92+
93+
# Extract optimized centers and radii
94+
optimized_centers = result.x[: 2 * n].reshape(n, 2)
95+
optimized_radii = result.x[2 * n :]
96+
97+
# Ensure radii are not negative (numerical stability)
98+
optimized_radii = np.maximum(optimized_radii, 0.001)
99+
100+
# Calculate the sum of radii
101+
sum_radii = np.sum(optimized_radii)
102+
103+
return optimized_centers, optimized_radii, sum_radii
104+
105+
106+
# EVOLVE-BLOCK-END
107+
108+
109+
# This part remains fixed (not evolved)
110+
def run_packing():
111+
"""Run the circle packing constructor for n=26"""
112+
centers, radii, sum_radii = construct_packing()
113+
return centers, radii, sum_radii
114+
115+
116+
def visualize(centers, radii):
117+
"""
118+
Visualize the circle packing
119+
120+
Args:
121+
centers: np.array of shape (n, 2) with (x, y) coordinates
122+
radii: np.array of shape (n) with radius of each circle
123+
"""
124+
import matplotlib.pyplot as plt
125+
from matplotlib.patches import Circle
126+
127+
fig, ax = plt.subplots(figsize=(8, 8))
128+
129+
# Draw unit square
130+
ax.set_xlim(0, 1)
131+
ax.set_ylim(0, 1)
132+
ax.set_aspect("equal")
133+
ax.grid(True)
134+
135+
# Draw circles
136+
for i, (center, radius) in enumerate(zip(centers, radii)):
137+
circle = Circle(center, radius, alpha=0.5)
138+
ax.add_patch(circle)
139+
ax.text(center[0], center[1], str(i), ha="center", va="center")
140+
141+
plt.title(f"Circle Packing (n={len(centers)}, sum={sum(radii):.6f})")
142+
plt.show()
143+
144+
145+
if __name__ == "__main__":
146+
centers, radii, sum_radii = run_packing()
147+
print(f"Sum of radii: {sum_radii}")
148+
# AlphaEvolve improved this to 2.635
149+
150+
# Uncomment to visualize:
151+
# visualize(centers, radii)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"id": "f6cbff44-9b16-4e6c-af58-b10b6625621a",
3+
"generation": 10,
4+
"iteration": 0,
5+
"timestamp": 1747709506.546607,
6+
"parent_id": "b7f51a09-7ba5-4cdb-bc15-9c431ec8885f",
7+
"metrics": {
8+
"validity": 1.0,
9+
"sum_radii": 2.634292402141039,
10+
"target_ratio": 0.9997314619131079,
11+
"combined_score": 0.9997314619131079,
12+
"eval_time": 0.6134955883026123
13+
},
14+
"language": "python",
15+
"saved_at": 1748016967.553278
16+
}

0 commit comments

Comments
 (0)