Skip to content

Commit 515d864

Browse files
authored
Merge branch 'codelion:main' into feat/tp_add_trading_example
2 parents 21f937a + 3b3bdb4 commit 515d864

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+9175
-161
lines changed

.github/workflows/python-lint.yml

Lines changed: 0 additions & 17 deletions
This file was deleted.

.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

CONTRIBUTING.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ source env/bin/activate # On Windows: env\Scripts\activate
1919
pip install -e ".[dev]"
2020
```
2121

22-
## Code Style
23-
24-
We follow the [Black](https://black.readthedocs.io/) code style. Please format your code before submitting a pull request:
25-
26-
```bash
27-
black openevolve tests examples
28-
```
29-
3022
## Pull Request Process
3123

3224
1. Create a new branch for your feature or bugfix: `git checkout -b feat-your-feature-name`

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ help:
1616
@echo " test - Run tests"
1717
@echo " docker-build - Build the Docker image"
1818
@echo " docker-run - Run the Docker container with the example"
19+
@echo " visualizer - Run the visualization script"
1920

2021
.PHONY: all
2122
all: install test

README.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ See the [Configuration Guide](configs/default_config.yaml) for a full list of op
185185

186186
## Artifacts Channel
187187

188-
OpenEvolve includes a **artifacts side-channel** that allows evaluators to capture build errors, profiling results, etc. to provide better feedback to the LLM in subsequent generations. This feature enhances the evolution process by giving the LLM context about what went wrong and how to fix it.
188+
OpenEvolve includes an **artifacts side-channel** that allows evaluators to capture build errors, profiling results, etc. to provide better feedback to the LLM in subsequent generations. This feature enhances the evolution process by giving the LLM context about what went wrong and how to fix it.
189189

190190
The artifacts channel operates alongside the traditional fitness metrics.
191191

@@ -205,17 +205,28 @@ return EvaluationResult(
205205
```
206206

207207
The next generation prompt will include:
208-
```
208+
```markdown
209209
## Last Execution Output
210210
### Stderr
211-
```
212211
SyntaxError: invalid syntax (line 15)
213-
```
212+
214213
### Traceback
215-
```
216214
...
217215
```
216+
217+
## Example: LLM Feedback
218+
219+
An example for an LLM artifact side channel is part of the default evaluation template, which ends with
220+
```markdown
221+
Return your evaluation as a JSON object with the following format:
222+
{{
223+
"readability": [score],
224+
"maintainability": [score],
225+
"efficiency": [score],
226+
"reasoning": "[brief explanation of scores]"
227+
}}
218228
```
229+
The non-float values, in this case the "reasoning" key of the json response that the evaluator LLM generates, will be available within the next generation prompt.
219230

220231
### Configuration
221232

@@ -240,7 +251,7 @@ export ENABLE_ARTIFACTS=false
240251
### Benefits
241252

242253
- **Faster convergence** - LLMs can see what went wrong and fix it directly
243-
- **Better error handling** - Compilation and runtime failures become learning opportunities
254+
- **Better error handling** - Compilation and runtime failures become learning opportunities
244255
- **Rich debugging context** - Full stack traces and error messages guide improvements
245256
- **Zero overhead** - When disabled, no performance impact on evaluation
246257

configs/default_config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ max_iterations: 1000 # Maximum number of evolution iterations
77
checkpoint_interval: 50 # Save checkpoints every N iterations
88
log_level: "INFO" # Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
99
log_dir: null # Custom directory for logs (default: output_dir/logs)
10-
random_seed: null # Random seed for reproducibility (null = random)
10+
random_seed: 42 # Random seed for reproducibility (null = random, 42 = default)
1111

1212
# Evolution settings
1313
diff_based_evolution: true # Use diff-based evolution (true) or full rewrites (false)
14-
allow_full_rewrites: false # Allow occasional full rewrites even in diff-based mode
1514
max_code_length: 10000 # Maximum allowed code length in characters
1615

1716
# LLM configuration
@@ -71,6 +70,7 @@ database:
7170
# General settings
7271
db_path: null # Path to persist database (null = in-memory only)
7372
in_memory: true # Keep database in memory for faster access
73+
log_prompts: true # If true, log all prompts and responses into the database
7474

7575
# Evolutionary parameters
7676
population_size: 1000 # Maximum number of programs to keep in memory
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)

0 commit comments

Comments
 (0)