Skip to content

Commit 8ee83bc

Browse files
authored
Merge pull request #91 from codelion/feat-add-signal-processing-example
Feat add signal processing example
2 parents 54ec173 + 9171448 commit 8ee83bc

File tree

12 files changed

+1079
-13
lines changed

12 files changed

+1079
-13
lines changed

configs/default_config.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ random_seed: null # Random seed for reproducibility (null =
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
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
# Real-Time Adaptive Signal Processing Algorithm Evolution
2+
3+
This example demonstrates how to use OpenEvolve to automatically discover and optimize real-time signal processing algorithms for non-stationary time series data. The challenge involves developing algorithms that can filter volatile signals while preserving important dynamics and minimizing computational latency.
4+
5+
## Problem Overview
6+
7+
### The Challenge
8+
We need to develop a real-time signal processing algorithm that can:
9+
10+
1. **Filter noise** from volatile, non-stationary time series data
11+
2. **Preserve genuine signal dynamics** and trend changes
12+
3. **Minimize spurious directional reversals** caused by noise
13+
4. **Achieve near-zero phase delay** for real-time applications
14+
5. **Operate efficiently** within computational constraints
15+
16+
### Input Signal Characteristics
17+
- **Type**: Univariate time series (1D array of real-valued samples)
18+
- **Properties**:
19+
- Non-linear dynamics
20+
- Non-stationary statistical properties
21+
- Aperiodic (non-seasonal) behavior
22+
- High frequency variability and volatility
23+
- Rapidly changing spectral characteristics
24+
25+
### Technical Constraints
26+
- **Causal Processing**: Must use finite-length sliding window
27+
- **Fixed Latency**: Output length = Input length - Window size
28+
- **Real-time Capability**: Process samples as they arrive
29+
- **Memory Efficiency**: Bounded memory usage
30+
31+
## Multi-Objective Optimization Framework
32+
33+
The algorithm performance is evaluated using a composite metric based on the research specification:
34+
35+
### Optimization Function
36+
```
37+
J(θ) = α₁·S(θ) + α₂·L_recent(θ) + α₃·L_avg(θ) + α₄·R(θ)
38+
```
39+
40+
Where:
41+
- **S(θ)**: **Slope Change Penalty** - Counts directional reversals in the filtered signal
42+
- **L_recent(θ)**: **Instantaneous Lag Error** - |y[n] - x[n]| at the most recent sample
43+
- **L_avg(θ)**: **Average Tracking Error** - Mean absolute error over the processing window
44+
- **R(θ)**: **False Reversal Penalty** - Trend changes that don't match the clean signal
45+
- **Weighting coefficients**: α₁=0.3, α₂=α₃=0.2, α₄=0.3
46+
47+
### Additional Evaluation Metrics
48+
- **Signal Fidelity**: Correlation with ground truth clean signal
49+
- **Noise Reduction**: Improvement in signal-to-noise ratio
50+
- **Computational Efficiency**: Processing time per sample
51+
- **Robustness**: Consistent performance across diverse signal types
52+
53+
## Proposed Algorithmic Approaches
54+
55+
The initial implementation provides a foundation that evolution can improve upon:
56+
57+
### 1. Baseline Implementation
58+
- Simple moving average filter
59+
- Weighted exponential moving average
60+
61+
### 2. Potential Advanced Techniques (for evolution to discover)
62+
- **Adaptive Filtering**: Kalman filters, particle filters, adaptive weights
63+
- **Multi-Scale Processing**: Wavelet decomposition, empirical mode decomposition
64+
- **Predictive Enhancement**: Local polynomial fitting, neural network prediction
65+
- **Trend Detection**: Change point detection, momentum indicators
66+
- **Hybrid Approaches**: Ensemble methods combining multiple techniques
67+
68+
## File Structure
69+
70+
```
71+
signal_processing/
72+
├── README.md # This documentation
73+
├── config.yaml # OpenEvolve configuration
74+
├── initial_program.py # Initial signal processing implementation
75+
├── evaluator.py # Multi-objective evaluation system
76+
├── requirements.txt # Python dependencies
77+
└── results/ # Generated results (after running)
78+
```
79+
80+
## How to Run
81+
82+
### Prerequisites
83+
1. Install OpenEvolve and its dependencies
84+
2. Install example-specific requirements:
85+
```bash
86+
pip install -r requirements.txt
87+
```
88+
3. Set up your LLM API key (e.g., `OPENAI_API_KEY` environment variable)
89+
90+
### Testing the Setup (Recommended)
91+
First, validate that everything is working correctly:
92+
```bash
93+
cd examples/signal_processing
94+
python test_setup.py
95+
```
96+
97+
This will test the initial implementation and evaluator to ensure everything is ready for evolution.
98+
99+
### Running the Evolution
100+
From the OpenEvolve root directory:
101+
```bash
102+
python openevolve-run.py examples/signal_processing/config.yaml
103+
```
104+
105+
Or from the signal_processing directory:
106+
```bash
107+
python ../../openevolve-run.py config.yaml
108+
```
109+
110+
### Monitoring Progress
111+
The evolution will create an `openevolve_output` directory containing:
112+
- **Checkpoints**: Saved population states at regular intervals
113+
- **Logs**: Detailed evolution progress and metrics
114+
- **Best Programs**: Top-performing algorithm implementations
115+
116+
## Understanding the Results
117+
118+
### Key Metrics to Watch
119+
1. **Overall Score**: Primary selection metric (higher is better)
120+
2. **Composite Score**: The main J(θ) optimization function
121+
3. **Correlation**: How well the filtered signal matches the clean ground truth
122+
4. **Noise Reduction**: Improvement in signal quality
123+
5. **Slope Changes**: Number of directional reversals (lower is better)
124+
6. **Success Rate**: Fraction of test signals processed successfully
125+
126+
### Actual Evolution Patterns (Observed)
127+
- **Early iterations (1-10)**: Discovered Savitzky-Golay filtering with adaptive polynomial order
128+
- **Mid evolution (10-100)**: Parameter optimization and performance stabilization around 0.37 score
129+
- **Advanced stages (100-130)**: Breakthrough to full Kalman Filter implementation with state-space modeling
130+
131+
## Test Signal Characteristics
132+
133+
The evaluator uses 5 different synthetic test signals to ensure robustness:
134+
135+
1. **Smooth Sinusoidal**: Basic sinusoid with linear trend
136+
2. **Multi-Frequency**: Multiple frequency components combined
137+
3. **Non-Stationary**: Frequency-modulated signal
138+
4. **Step Changes**: Sudden level changes to test responsiveness
139+
5. **Random Walk**: Stochastic process with trend
140+
141+
Each signal has different noise levels and lengths to test algorithm adaptability.
142+
143+
## Initial Algorithm Analysis
144+
145+
The starting point includes:
146+
- **Basic moving average**: Simple but may over-smooth
147+
- **Weighted moving average**: Emphasizes recent samples
148+
- **Exponential weighting**: Exponentially decaying weights for trend preservation
149+
150+
This provides a baseline that evolution can significantly improve upon by discovering:
151+
- Advanced filtering techniques
152+
- Adaptive parameter adjustment
153+
- Multi-scale processing
154+
- Predictive elements
155+
- Robust trend detection
156+
157+
## Interpreting Evolution Results
158+
159+
### Successful Evolution Indicators
160+
- **Decreasing slope changes**: Algorithm learns to reduce noise-induced reversals
161+
- **Improving correlation**: Better preservation of true signal structure
162+
- **Balanced metrics**: Good performance across all test signals
163+
- **Stable improvements**: Consistent gains over multiple iterations
164+
165+
### Common Evolution Discoveries
166+
- **Adaptive window sizing**: Dynamic adjustment based on signal characteristics
167+
- **Multi-pass filtering**: Combining multiple filtering stages
168+
- **Outlier detection**: Identifying and handling anomalous samples
169+
- **Frequency analysis**: Spectral-based filtering decisions
170+
- **Predictive elements**: Using future sample prediction to reduce lag
171+
172+
## Configuration Options
173+
174+
Key parameters in `config.yaml`:
175+
- **max_iterations**: Total evolution steps (200 recommended)
176+
- **population_size**: Number of candidate algorithms (80)
177+
- **cascade_thresholds**: Quality gates for evaluation stages
178+
- **system_message**: Guides LLM toward signal processing expertise
179+
180+
## Extending the Example
181+
182+
### Adding New Test Signals
183+
Modify `generate_test_signals()` in `evaluator.py` to include:
184+
- Real-world datasets (financial, sensor, biomedical)
185+
- Domain-specific signal characteristics
186+
- Different noise models and intensities
187+
188+
### Customizing Evaluation Metrics
189+
Adjust weights in the composite function or add new metrics:
190+
- Phase delay measurement
191+
- Spectral preservation
192+
- Computational complexity analysis
193+
- Memory usage optimization
194+
195+
### Advanced Algorithmic Constraints
196+
Modify the evolution block to explore:
197+
- Specific filtering architectures
198+
- Hardware-optimized implementations
199+
- Online learning capabilities
200+
- Multi-channel processing
201+
202+
## Research Applications
203+
204+
This framework can be adapted for various domains:
205+
- **Financial Markets**: High-frequency trading signal processing
206+
- **Biomedical Engineering**: Real-time biosignal filtering
207+
- **Sensor Networks**: Environmental monitoring and noise reduction
208+
- **Control Systems**: Real-time feedback signal conditioning
209+
- **Communications**: Adaptive signal processing for wireless systems
210+
211+
## Actual Evolution Results ✨
212+
213+
**After 130 iterations, OpenEvolve achieved a major algorithmic breakthrough!**
214+
215+
### Key Discoveries:
216+
- **🎯 Full Kalman Filter Implementation**: Complete state-space modeling with position-velocity tracking
217+
- **📈 23% Performance Improvement**: Composite score improved from ~0.30 to 0.3712
218+
- **⚡ 2x Faster Execution**: Optimized from 20ms to 11ms processing time
219+
- **🔧 Advanced Parameter Tuning**: Discovered optimal noise covariance matrices
220+
221+
### Evolution Timeline:
222+
1. **Early Stage (1-10 iterations)**: Discovered Savitzky-Golay adaptive filtering
223+
2. **Mid Evolution (10-100)**: Parameter optimization and technique refinement
224+
3. **Breakthrough (100-130)**: Full Kalman Filter with adaptive initialization
225+
226+
### Final Performance Metrics:
227+
- **Composite Score**: 0.3712 (multi-objective optimization function)
228+
- **Slope Changes**: 322.8 (19% reduction in spurious reversals)
229+
- **Correlation**: 0.147 (22% improvement in signal fidelity)
230+
- **Lag Error**: 0.914 (24% reduction in responsiveness delay)
231+
232+
📊 **[View Detailed Results](EVOLUTION_RESULTS.md)** - Complete analysis with technical details
233+
234+
### Algorithmic Sophistication Achieved:
235+
```python
236+
# Discovered Kalman Filter with optimized parameters:
237+
class KalmanFilter:
238+
def __init__(self, sigma_a_sq=1.0, measurement_noise=0.04):
239+
# State transition for constant velocity model
240+
self.F = np.array([[1, dt], [0, 1]])
241+
# Optimized process noise (100x improvement)
242+
self.Q = G @ G.T * sigma_a_sq
243+
# Tuned measurement trust (55% improvement)
244+
self.R = measurement_noise
245+
```
246+
247+
The evolved solution demonstrates that **automated algorithm discovery can achieve expert-level signal processing implementations**, discovering sophisticated techniques like Kalman filtering and optimal parameter combinations that would typically require months of engineering effort.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
PROPOSED FIX for OpenEvolve Configuration Bug
3+
4+
Issue: diff_based_evolution=True and allow_full_rewrites=True are incompatible
5+
but no validation prevents this configuration from being used.
6+
7+
PROBLEM:
8+
- Prompt sampler uses allow_full_rewrites to choose template
9+
- Controller uses diff_based_evolution to choose parser
10+
- These can create contradictory behavior
11+
12+
SOLUTION:
13+
Add validation to Config class __post_init__ method
14+
"""
15+
16+
# Add this to openevolve/config.py in the Config class __post_init__ method:
17+
18+
def __post_init__(self):
19+
"""Post-initialization validation"""
20+
21+
# Validate evolution settings compatibility
22+
if self.diff_based_evolution and self.allow_full_rewrites:
23+
raise ValueError(
24+
"Configuration Error: diff_based_evolution=True and allow_full_rewrites=True "
25+
"are incompatible. Use one of these combinations:\n"
26+
" - diff_based_evolution=True, allow_full_rewrites=False (diff-based evolution)\n"
27+
" - diff_based_evolution=False, allow_full_rewrites=True (rewrite-based evolution)\n"
28+
" - diff_based_evolution=False, allow_full_rewrites=False (rewrite with diff template)"
29+
)
30+
31+
# Other existing validations...
32+
33+
34+
# Alternative: Add a helper method to validate and suggest fixes:
35+
36+
def validate_evolution_settings(self) -> None:
37+
"""Validate evolution configuration and provide helpful error messages"""
38+
39+
if self.diff_based_evolution and self.allow_full_rewrites:
40+
suggested_configs = [
41+
"# Option 1: Pure diff-based evolution (recommended for iterative improvements)",
42+
"diff_based_evolution: true",
43+
"allow_full_rewrites: false",
44+
"",
45+
"# Option 2: Pure rewrite-based evolution (recommended for major changes)",
46+
"diff_based_evolution: false",
47+
"allow_full_rewrites: true"
48+
]
49+
50+
raise ValueError(
51+
f"❌ Configuration Error: Incompatible evolution settings detected!\n\n"
52+
f"Current settings:\n"
53+
f" diff_based_evolution: {self.diff_based_evolution}\n"
54+
f" allow_full_rewrites: {self.allow_full_rewrites}\n\n"
55+
f"🔧 Suggested fixes:\n" + "\n".join(suggested_configs) + "\n\n"
56+
f"💡 Explanation:\n"
57+
f" - diff_based_evolution=True makes the controller parse responses as diff blocks\n"
58+
f" - allow_full_rewrites=True makes the prompt ask for complete code rewrites\n"
59+
f" - These create a contradiction: LLM returns complete code but controller expects diffs\n"
60+
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Configuration for Real-Time Adaptive Signal Processing Example
2+
max_iterations: 100
3+
checkpoint_interval: 10
4+
log_level: "INFO"
5+
6+
# LLM configuration
7+
llm:
8+
primary_model: "gemini-2.5-flash-lite-preview-06-17"
9+
primary_model_weight: 0.8
10+
secondary_model: "gemini-2.5-flash"
11+
secondary_model_weight: 0.2
12+
api_base: "https://generativelanguage.googleapis.com/v1beta/openai/"
13+
temperature: 0.6
14+
top_p: 0.95
15+
max_tokens: 32000
16+
17+
# Prompt configuration
18+
prompt:
19+
system_message: "You are an expert signal processing engineer specializing in real-time adaptive filtering algorithms. Your task is to improve a signal processing algorithm that filters volatile, non-stationary time series data using a sliding window approach. The algorithm must minimize noise while preserving signal dynamics with minimal computational latency and phase delay. Focus on the multi-objective optimization of: (1) Slope change minimization - reducing spurious directional reversals, (2) Lag error minimization - maintaining responsiveness, (3) Tracking accuracy - preserving genuine signal trends, and (4) False reversal penalty - avoiding noise-induced trend changes. Consider advanced techniques like adaptive filtering (Kalman filters, particle filters), multi-scale processing (wavelets, EMD), predictive enhancement (polynomial fitting, neural networks), and trend detection methods."
20+
num_top_programs: 3
21+
use_template_stochasticity: true
22+
23+
# Database configuration
24+
database:
25+
population_size: 80
26+
archive_size: 30
27+
num_islands: 4
28+
elite_selection_ratio: 0.15
29+
exploitation_ratio: 0.65
30+
31+
# Evaluator configuration
32+
evaluator:
33+
timeout: 120
34+
cascade_evaluation: true
35+
cascade_thresholds: [0.3, 0.6]
36+
parallel_evaluations: 4
37+
use_llm_feedback: false
38+
39+
# Evolution settings
40+
diff_based_evolution: true
41+
max_code_length: 60000

0 commit comments

Comments
 (0)