Using LLMs for Algorithm Discovery: From Theory to Implementation
How autonomous AI research agents are discovering novel algorithms that surpass human-designed solutions
Attribution and Sources
This article is inspired by and draws concepts from the research paper “Accelerating New Algorithm Discovery with Language Models” by Novikov et al. (2025), which introduces the AlphaResearch system. The paper is available at: https://arxiv.org/html/2511.08522v1
Important Notes:
- All code implementations in this article are original interpretations and examples created for educational purposes
- Concepts and architectural patterns are explained in my own words based on the research
- Specific results and benchmarks are cited from the original paper where mentioned
- This article is a technical guide and tutorial, not a reproduction of the original research
Copyright & Licensing:
- The original AlphaResearch paper is © 2025 by its authors and is made available under arXiv’s non-exclusive license
- All code examples in this article are provided under MIT License for educational use
- Readers should consult the original paper’s repository for the official implementation and its specific license terms
For the authoritative and complete research, please refer to the original paper and its associated code repository at: https://github.com/answers111/alpha-research
Introduction
Imagine an AI system that doesn’t just solve known problems, but actually discovers new algorithms that outperform the best solutions human researchers have developed over decades. This isn’t science fiction — it’s happening right now.
Recent breakthroughs in large language models (LLMs) have shown remarkable capabilities in mathematics and coding, but a critical question remains: Can these models push beyond the boundaries of existing human knowledge? The answer, as demonstrated by recent research, is a qualified “yes” — with fascinating implications for how we approach algorithmic research.
In this article, we’ll explore how to build autonomous research agents that discover novel algorithms, drawing from cutting-edge research while providing practical implementation guidance. Whether you’re a researcher, engineer, or AI enthusiast, you’ll learn the architecture, techniques, and challenges of using LLMs for scientific discovery.
The Core Challenge: Discovery vs. Verification
Traditional LLM applications excel at problems with clear verification methods — writing code that passes unit tests, solving math problems with known answers, or generating text that matches specific criteria. But discovering new algorithms presents a fundamentally different challenge:
- No ground truth: You don’t know the answer beforehand
- Open-ended exploration: The solution space is vast and poorly defined
- Innovation vs. feasibility tension: Novel ideas might be impractical, while executable solutions might be uninteresting
Previous approaches have struggled with this tension:
- Execution-only systems can validate whether code runs correctly but may converge on technically correct yet scientifically uninteresting solutions
- Idea-generation systems evaluated purely by LLM judges can propose innovative concepts that prove computationally infeasible
The breakthrough comes from combining both approaches into a dual research environment.
The Dual Research Environment Architecture
The key innovation in modern algorithm discovery systems is creating two complementary verification mechanisms (as introduced in the AlphaResearch paper by Novikov et al., 2025):
1. Execution-Based Verification
This component ensures feasibility — that proposed algorithms actually work:
class ExecutionEnvironment:
"""Verifies algorithm implementations through execution"""
def __init__(self, problem_constraints):
self.constraints = problem_constraints
self.executor = CodeExecutor()
def verify(self, program_code):
"""
Verify that code meets problem constraints
Returns: (is_valid, performance_score)
"""
try:
# Execute the program
result = self.executor.run(program_code)
# Check constraints (e.g., circles don't overlap,
# solutions are within bounds)
is_valid = self.validate_constraints(result)
# Measure performance (e.g., sum of radii,
# optimization objective)
score = self.compute_objective(result)
return is_valid, score
except Exception as e:
return False, 0.0
def validate_constraints(self, result):
"""Problem-specific constraint checking"""
for constraint in self.constraints:
if not constraint.check(result):
return False
return True
def compute_objective(self, result):
"""Compute the optimization objective"""
return self.constraints.objective_function(result)2. Peer Review Environment
This component ensures innovation — that ideas are actually promising:
The peer review environment is simulated using a reward model trained on real-world research papers and their review scores. Here’s how to build one:
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
class PeerReviewRewardModel:
"""
Simulates peer review by scoring research ideas
Trained on actual academic peer review data
"""
def __init__(self, model_name="qwen/Qwen2.5-7B-Instruct"):
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = AutoModelForCausalLM.from_pretrained(model_name)
def prepare_training_data(self, papers_df):
"""
Prepare peer review data for training
papers_df should contain: abstract, average_rating
"""
training_data = []
for _, paper in papers_df.iterrows():
prompt = f"""Evaluate this research idea:
{paper['abstract']}
Provide an overall rating (1-10) in \\boxed{{rating}} format."""
response = f"\\boxed{{{paper['average_rating']}}}"
training_data.append({
'prompt': prompt,
'response': response
})
return training_data
def score_idea(self, research_idea):
"""
Score a research idea (higher = better)
Returns: float score, typically 1-10
"""
prompt = f"""Evaluate this research idea:
{research_idea}
Provide an overall rating (1-10) in \\boxed{{rating}} format."""
inputs = self.tokenizer(prompt, return_tensors="pt")
outputs = self.model.generate(**inputs, max_new_tokens=50)
response = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
# Extract score from \\boxed{score} format
import re
match = re.search(r'\\boxed\{(\d+\.?\d*)\}', response)
if match:
return float(match.group(1))
return 0.0
def is_promising(self, research_idea, threshold=6.0):
"""Quick filter for promising ideas"""
score = self.score_idea(research_idea)
return score >= thresholdTraining the Reward Model
Here’s how to fine-tune a reward model on peer review data:
from transformers import Trainer, TrainingArguments
def train_reward_model(base_model, training_data):
"""
Fine-tune a model to predict peer review scores
"""
# Prepare dataset
def format_data(examples):
texts = []
for prompt, response in zip(examples['prompt'], examples['response']):
texts.append(f"{prompt}\n\n{response}")
return {'text': texts}
# Training configuration
training_args = TrainingArguments(
output_dir="./reward_model",
num_train_epochs=2,
per_device_train_batch_size=128,
learning_rate=1e-5,
warmup_steps=100,
bf16=True, # Use bfloat16 for efficiency
logging_steps=10,
)
trainer = Trainer(
model=base_model,
args=training_args,
train_dataset=training_data,
)
trainer.train()
return trainer.modelKey Insight: Training on real peer review data (like ICLR conference reviews) gives the model a nuanced understanding of what makes research ideas promising. In research experiments, such models achieve ~72% accuracy in identifying high-quality ideas — outperforming both general-purpose LLMs (~50% accuracy) and human evaluators (~65% accuracy) (Novikov et al., 2025).
The Algorithm Discovery Loop
With both environments in place, we can implement the core discovery algorithm:
class AlphaResearchAgent:
"""
Autonomous research agent for algorithm discovery
"""
def __init__(self, llm, reward_model, execution_env):
self.llm = llm # e.g., GPT-4, Claude, etc.
self.reward_model = reward_model
self.execution_env = execution_env
self.trajectory = [] # History of (idea, code, score)
def discover_algorithm(self, problem_description, max_iterations=500):
"""
Main discovery loop
"""
# Initialize with a basic solution
current_idea = self.generate_initial_idea(problem_description)
current_code = self.generate_initial_code(problem_description)
is_valid, current_score = self.execution_env.verify(current_code)
best_score = current_score if is_valid else float('-inf')
best_solution = (current_idea, current_code, current_score)
self.trajectory.append({
'idea': current_idea,
'code': current_code,
'score': current_score,
'valid': is_valid
})
for iteration in range(max_iterations):
# Step 1: Generate new idea
new_idea = self.generate_new_idea(
problem_description,
self.sample_from_trajectory()
)
# Step 2: Filter with reward model
if not self.reward_model.is_promising(new_idea):
continue # Skip unpromising ideas
# Step 3: Implement the idea
new_code = self.implement_idea(
new_idea,
previous_code=current_code
)
# Step 4: Verify execution
is_valid, new_score = self.execution_env.verify(new_code)
# Step 5: Update trajectory and best solution
self.trajectory.append({
'idea': new_idea,
'code': new_code,
'score': new_score,
'valid': is_valid
})
if is_valid and new_score > best_score:
best_score = new_score
best_solution = (new_idea, new_code, new_score)
current_idea, current_code = new_idea, new_code
print(f"Iteration {iteration}: New best score: {best_score}")
return best_solution
def generate_new_idea(self, problem_description, previous_context):
"""Generate a novel research idea"""
prompt = f"""Problem: {problem_description}
Previous approach:
Idea: {previous_context['idea']}
Result: {previous_context['score']}
Propose a novel improvement or alternative approach. Be specific about what changes you would make and why.
New research idea:"""
response = self.llm.generate(prompt)
return response
def implement_idea(self, idea, previous_code):
"""Convert research idea into executable code"""
prompt = f"""Implement this research idea in Python:
Idea: {idea}
Previous implementation:
```python
{previous_code}Generate a complete, executable Python implementation. Focus on the core algorithm.
Implementation:”””
response = self.llm.generate(prompt)
code = self.extract_code(response)
return code
def sample_from_trajectory(self):
"""Sample a previous step to build upon"""
# Prefer high-scoring valid solutions
valid_steps = [s for s in self.trajectory if s['valid']]
if valid_steps:
# Sample weighted by score
scores = [s['score'] for s in valid_steps]
weights = torch.softmax(torch.tensor(scores), dim=0)
idx = torch.multinomial(weights, 1).item()
return valid_steps[idx]
else:
# Fallback to random sampling
return random.choice(self.trajectory)
def extract_code(self, response):
"""Extract Python code from LLM response"""
# Look for code blocks
import re
code_match = re.search(r'```python\n(.*?)\n```', response, re.DOTALL)
if code_match:
return code_match.group(1)
return response # Fallback
## Real-World Example: Circle Packing
Let's walk through a concrete example—the circle packing problem, where we want to pack as many disjoint circles as possible into a unit square, maximizing the sum of their radii.
### Problem Setup
```python
class CirclePackingProblem:
"""
Pack circles in a unit square to maximize sum of radii
"""
def __init__(self, n_circles=26):
self.n_circles = n_circles
def create_execution_environment(self):
"""Create the execution environment for this problem"""
class CirclePackingEnv:
def __init__(self, n):
self.n = n
def verify(self, program_code):
"""
Execute code and verify it produces valid circle packing
"""
try:
# Execute the program
exec_globals = {}
exec(program_code, exec_globals)
# Get the circles (should be list of (x, y, radius))
if 'get_circles' not in exec_globals:
return False, 0.0
circles = exec_globals['get_circles']()
# Validate constraints
if not self.validate_circles(circles):
return False, 0.0
# Compute objective (sum of radii)
total_radius = sum(r for x, y, r in circles)
return True, total_radius
except Exception as e:
print(f"Execution error: {e}")
return False, 0.0
def validate_circles(self, circles):
"""Check that circles are valid"""
if len(circles) != self.n:
return False
# Check all circles are in unit square
for x, y, r in circles:
if x - r < 0 or x + r > 1:
return False
if y - r < 0 or y + r > 1:
return False
# Check no overlap
for i in range(len(circles)):
for j in range(i + 1, len(circles)):
x1, y1, r1 = circles[i]
x2, y2, r2 = circles[j]
dist = ((x1 - x2)**2 + (y1 - y2)**2)**0.5
if dist < r1 + r2: # Circles overlap
return False
return True
return CirclePackingEnv(self.n_circles)Initial Solution
def initial_circle_packing():
"""Baseline: Simple grid arrangement"""
def get_circles():
import math
n = 26
# Arrange in a grid
grid_size = math.ceil(math.sqrt(n))
spacing = 1.0 / grid_size
radius = spacing / 2.5 # Leave some margin
circles = []
for i in range(n):
row = i // grid_size
col = i % grid_size
x = (col + 0.5) * spacing
y = (row + 0.5) * spacing
circles.append((x, y, radius))
return circles
return get_circlesEvolved Solution Example
After running the discovery loop, the agent might evolve to more sophisticated approaches:
def evolved_circle_packing():
"""
Discovered approach: Adaptive circle placement with
local optimization and gap filling
"""
def get_circles():
import random
import math
n = 26
circles = []
# Start with larger circles using physics-based repulsion
for _ in range(n):
best_pos = None
best_radius = 0
# Try multiple candidate positions
for _ in range(100):
x = random.uniform(0.1, 0.9)
y = random.uniform(0.1, 0.9)
# Compute maximum radius at this position
max_r = min(x, 1-x, y, 1-y) # Distance to walls
for cx, cy, cr in circles:
dist = math.sqrt((x-cx)**2 + (y-cy)**2)
max_r = min(max_r, dist - cr)
if max_r > best_radius:
best_radius = max_r
best_pos = (x, y)
if best_pos and best_radius > 0:
circles.append((*best_pos, best_radius))
# Local optimization: iteratively adjust positions
for _ in range(1000):
# Random perturbation
if circles:
idx = random.randint(0, len(circles)-1)
x, y, r = circles[idx]
# Try small movement
dx = random.gauss(0, 0.01)
dy = random.gauss(0, 0.01)
new_x, new_y = x + dx, y + dy
# Check if valid and improves
# ... validation logic ...
return circles
return get_circlesResult: Research systems using this dual-environment approach have discovered circle packings that achieve a sum of radii of 2.939 for n=32 circles, surpassing the previous best-known human solution of 2.936 (Specht, 2012) that stood for over a decade (Novikov et al., 2025, AlphaResearch paper).
Implementation Tips and Best Practices
1. Choosing the Right LLM
For the research agent itself, you want:
- Strong reasoning capabilities: GPT-4, Claude, or similar frontier models
- Code generation proficiency: Models trained on code (like GPT-4 or specialized code models)
- Instruction following: The model needs to follow complex, multi-step prompts
# Example using OpenAI API
from openai import OpenAI
class LLMResearchAgent:
def __init__(self, model="gpt-4"):
self.client = OpenAI()
self.model = model
def generate(self, prompt, temperature=0.7):
response = self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": "You are an expert algorithm researcher."},
{"role": "user", "content": prompt}
],
temperature=temperature
)
return response.choices[0].message.content2. Prompt Engineering for Idea Generation
The quality of generated ideas depends heavily on prompting:
def create_idea_generation_prompt(problem, previous_context, best_score):
"""Craft an effective research idea prompt"""
prompt = f"""You are an expert algorithm researcher working on the following problem:
PROBLEM: {problem['description']}
OBJECTIVE: {problem['objective']}
CONSTRAINTS: {problem['constraints']}
CURRENT BEST RESULT: {best_score}
HUMAN BEST RESULT: {problem['human_best']}
PREVIOUS APPROACH:
{previous_context['idea']}
Implementation snippet:
{previous_context['code_snippet']}
Result: {previous_context['score']}
Your task: Propose a novel algorithmic improvement. Consider:
1. What are the limitations of the current approach?
2. What mathematical or computational insights could help?
3. What alternative strategies might work better?
4. How can you balance exploration vs exploitation?
Be specific and actionable. Explain the intuition behind your idea.
NOVEL RESEARCH IDEA:"""
return prompt3. Managing the Trajectory
Efficient sampling from previous attempts is crucial:
class TrajectoryManager:
"""Manage and sample from research trajectory"""
def __init__(self, capacity=1000):
self.trajectory = []
self.capacity = capacity
def add(self, idea, code, score, valid):
"""Add new entry"""
self.trajectory.append({
'idea': idea,
'code': code,
'score': score,
'valid': valid,
'timestamp': len(self.trajectory)
})
# Keep only best entries if at capacity
if len(self.trajectory) > self.capacity:
self.trajectory = sorted(
self.trajectory,
key=lambda x: x['score'] if x['valid'] else float('-inf'),
reverse=True
)[:self.capacity]
def sample_for_improvement(self, strategy='best'):
"""Sample entry to improve upon"""
valid_entries = [e for e in self.trajectory if e['valid']]
if not valid_entries:
return random.choice(self.trajectory)
if strategy == 'best':
# Always pick the best
return max(valid_entries, key=lambda x: x['score'])
elif strategy == 'recent_good':
# Recent entries that are above average
recent = valid_entries[-50:]
avg_score = sum(e['score'] for e in recent) / len(recent)
good_recent = [e for e in recent if e['score'] >= avg_score]
return random.choice(good_recent if good_recent else recent)
elif strategy == 'diverse':
# Sample to maintain diversity
# Use clustering or distance metrics on ideas
return self.sample_diverse(valid_entries)
def sample_diverse(self, entries):
"""Sample diverse entry using embedding similarity"""
# This is a simplified version
# In practice, you'd use embeddings to measure idea similarity
return random.choice(entries)4. Handling Code Execution Safely
When executing LLM-generated code, safety is paramount:
import subprocess
import tempfile
import os
class SafeCodeExecutor:
"""Execute code in isolated environment"""
def __init__(self, timeout=10):
self.timeout = timeout
def run(self, code, problem_config):
"""
Execute code safely with timeout and resource limits
"""
# Create temporary file
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
f.write(code)
temp_path = f.name
try:
# Run in subprocess with timeout
result = subprocess.run(
['python', temp_path],
capture_output=True,
text=True,
timeout=self.timeout,
# Additional safety: limit memory, no network, etc.
# In production, consider using Docker containers
)
if result.returncode == 0:
return self.parse_output(result.stdout, problem_config)
else:
return None, f"Execution error: {result.stderr}"
except subprocess.TimeoutExpired:
return None, "Execution timeout"
finally:
os.unlink(temp_path)
def parse_output(self, stdout, problem_config):
"""Parse program output based on problem type"""
# Problem-specific parsing logic
passEvaluation Metrics
Traditional metrics like pass@k don’t capture the essence of algorithm discovery. Instead, use:
Excel@Best Metric
def excel_at_best(discovered_score, human_best, maximize=True):
"""
Measure excess performance over human best
Args:
discovered_score: Score achieved by AI system
human_best: Best known human score
maximize: Whether higher scores are better
Returns:
Percentage improvement (positive = superhuman)
"""
if maximize:
improvement = (discovered_score - human_best) / abs(human_best)
else:
improvement = (human_best - discovered_score) / abs(human_best)
return improvement * 100 # As percentage
# Example usage
human_best_packing = 2.936
discovered_packing = 2.939
improvement = excel_at_best(discovered_packing, human_best_packing, maximize=True)
print(f"Improvement: {improvement:.2f}%") # Output: 0.10%Tracking Research Progress
class ResearchMetrics:
"""Track algorithm discovery progress"""
def __init__(self):
self.metrics = {
'iterations': [],
'scores': [],
'valid_attempts': [],
'idea_quality': [],
'execution_time': []
}
def log_iteration(self, iteration, score, valid, idea_score, exec_time):
"""Log metrics for one iteration"""
self.metrics['iterations'].append(iteration)
self.metrics['scores'].append(score if valid else None)
self.metrics['valid_attempts'].append(valid)
self.metrics['idea_quality'].append(idea_score)
self.metrics['execution_time'].append(exec_time)
def plot_progress(self):
"""Visualize research progress"""
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))
# Plot score progression
valid_scores = [(i, s) for i, s in enumerate(self.metrics['scores'])
if s is not None]
if valid_scores:
iters, scores = zip(*valid_scores)
ax1.scatter(iters, scores, alpha=0.5, label='Valid attempts')
ax1.plot(iters, scores, alpha=0.3)
ax1.set_ylabel('Score')
ax1.set_title('Algorithm Performance Over Time')
ax1.legend()
# Plot success rate
window = 50
success_rates = []
for i in range(window, len(self.metrics['valid_attempts'])):
recent = self.metrics['valid_attempts'][i-window:i]
success_rates.append(sum(recent) / window)
ax2.plot(success_rates)
ax2.set_xlabel('Iteration')
ax2.set_ylabel('Success Rate (last 50)')
ax2.set_title('Execution Success Rate')
plt.tight_layout()
plt.savefig('research_progress.png')
def compute_statistics(self):
"""Compute summary statistics"""
valid_scores = [s for s in self.metrics['scores'] if s is not None]
return {
'total_iterations': len(self.metrics['iterations']),
'valid_attempts': sum(self.metrics['valid_attempts']),
'success_rate': sum(self.metrics['valid_attempts']) / len(self.metrics['valid_attempts']),
'best_score': max(valid_scores) if valid_scores else None,
'avg_idea_quality': sum(self.metrics['idea_quality']) / len(self.metrics['idea_quality']),
'total_compute_time': sum(self.metrics['execution_time'])
}Complete Example: Putting It All Together
Here’s a complete, runnable example for a simple optimization problem:
import random
import math
from typing import List, Tuple
class SimpleOptimizationProblem:
"""
Example: Minimize f(x) = sum(x_i^2) subject to constraints
"""
def __init__(self, dimensions=10):
self.dimensions = dimensions
self.human_best = 0.001 # Some baseline
def create_environments(self):
"""Create both verification environments"""
# Execution environment
class OptimizationEnv:
def __init__(self, dims):
self.dims = dims
def verify(self, code):
try:
exec_globals = {}
exec(code, exec_globals)
if 'optimize' not in exec_globals:
return False, float('inf')
result = exec_globals['optimize']()
# Check constraints
if not isinstance(result, list) or len(result) != self.dims:
return False, float('inf')
# Compute objective
score = sum(x**2 for x in result)
return True, score
except Exception as e:
return False, float('inf')
execution_env = OptimizationEnv(self.dimensions)
# Reward model (simplified for example)
class SimpleRewardModel:
def is_promising(self, idea):
# Simplified: check for key optimization concepts
keywords = ['gradient', 'iterative', 'optimization', 'minimize']
return any(kw in idea.lower() for kw in keywords)
reward_model = SimpleRewardModel()
return execution_env, reward_model
def run_algorithm_discovery_example():
"""Complete example of running algorithm discovery"""
# 1. Setup problem
problem = SimpleOptimizationProblem(dimensions=5)
execution_env, reward_model = problem.create_environments()
# 2. Initialize agent (simplified without real LLM)
class MockLLM:
def generate(self, prompt):
# In real usage, this would call GPT-4, Claude, etc.
# Here we simulate with a simple response
if "generate_new_idea" in prompt:
ideas = [
"Use gradient descent with momentum",
"Apply simulated annealing for global optimization",
"Use adaptive learning rate with Adam optimizer"
]
return random.choice(ideas)
elif "implement_idea" in prompt:
# Return simple gradient descent implementation
return '''
def optimize():
import random
x = [random.uniform(-1, 1) for _ in range(5)]
learning_rate = 0.1
for _ in range(100):
gradients = [2 * xi for xi in x]
x = [xi - learning_rate * gi for xi, gi in zip(x, gradients)]
return x
'''
llm = MockLLM()
agent = AlphaResearchAgent(llm, reward_model, execution_env)
# 3. Run discovery
print("Starting algorithm discovery...")
best_solution = agent.discover_algorithm(
problem_description="Minimize f(x) = sum(x_i^2)",
max_iterations=100
)
idea, code, score = best_solution
print(f"\nBest solution found:")
print(f"Score: {score}")
print(f"Idea: {idea}")
# 4. Compare with human best
improvement = excel_at_best(score, problem.human_best, maximize=False)
print(f"Improvement over human best: {improvement:.2f}%")
if __name__ == "__main__":
run_algorithm_discovery_example()Challenges and Limitations
Despite promising results, several challenges remain:
1. Success Rate
Research systems like AlphaResearch achieve around 2/8 (25%) success rate on novel algorithmic problems (Novikov et al., 2025). The main failure modes include:
- Local optima: Getting stuck in locally good but globally suboptimal solutions
- Constraint satisfaction: Difficulty maintaining complex constraints during optimization
- Limited exploration: Not exploring sufficiently diverse approaches
2. Computational Cost
Algorithm discovery is computationally expensive:
- Each iteration requires LLM inference (expensive)
- Code execution adds overhead
- May need hundreds or thousands of iterations
Mitigation strategies:
class EfficientDiscoveryAgent:
"""Optimizations for computational efficiency"""
def __init__(self, llm, reward_model, execution_env):
self.llm = llm
self.reward_model = reward_model
self.execution_env = execution_env
self.cache = {} # Cache LLM responses
def generate_with_cache(self, prompt):
"""Cache LLM responses for similar prompts"""
prompt_hash = hash(prompt)
if prompt_hash in self.cache:
return self.cache[prompt_hash]
response = self.llm.generate(prompt)
self.cache[prompt_hash] = response
return response
def batch_execution(self, programs, batch_size=10):
"""Execute multiple programs in parallel"""
from multiprocessing import Pool
with Pool(batch_size) as pool:
results = pool.map(self.execution_env.verify, programs)
return results3. Idea Quality vs. Execution Gap
Sometimes the LLM generates excellent ideas but struggles to implement them correctly:
class IdeaExecutionBridge:
"""Help bridge the gap between ideas and implementation"""
def __init__(self, llm):
self.llm = llm
def decompose_idea(self, complex_idea):
"""Break complex idea into implementable steps"""
prompt = f"""Break this research idea into concrete implementation steps:
Idea: {complex_idea}
Provide 3-5 specific, implementable steps:"""
response = self.llm.generate(prompt)
return self.parse_steps(response)
def implement_incrementally(self, idea, base_code):
"""Implement idea step by step"""
steps = self.decompose_idea(idea)
current_code = base_code
for step in steps:
prompt = f"""Current implementation:
{current_code}
Add this functionality:
{step}
Updated implementation:"""
current_code = self.llm.generate(prompt)
return current_codeFuture Directions
The field of LLM-based algorithm discovery is rapidly evolving. Here are promising directions:
1. Multi-Agent Collaboration
class MultiAgentResearch:
"""Multiple specialized agents collaborate on discovery"""
def __init__(self):
self.idea_agent = LLMAgent(specialty="idea_generation")
self.implementation_agent = LLMAgent(specialty="coding")
self.critique_agent = LLMAgent(specialty="analysis")
def collaborative_discovery(self, problem):
"""Agents work together"""
# Ideation phase
ideas = self.idea_agent.generate_ideas(problem)
# Critique phase
evaluated_ideas = [
self.critique_agent.evaluate(idea)
for idea in ideas
]
# Implementation phase
best_ideas = sorted(evaluated_ideas,
key=lambda x: x['score'],
reverse=True)[:3]
implementations = [
self.implementation_agent.implement(idea)
for idea in best_ideas
]
return implementations2. Learning from Human Feedback
Incorporate human experts into the loop:
class HumanInTheLoopDiscovery:
"""Incorporate human expertise"""
def __init__(self, agent, expert_feedback_fn):
self.agent = agent
self.expert_feedback = expert_feedback_fn
def discover_with_guidance(self, problem, checkpoints=[100, 250, 400]):
"""Pause for human feedback at checkpoints"""
for checkpoint in checkpoints:
# Run agent until checkpoint
self.agent.discover_algorithm(
problem,
max_iterations=checkpoint
)
# Get human feedback
current_best = self.agent.get_best_solution()
feedback = self.expert_feedback(current_best)
# Incorporate feedback
self.agent.add_guidance(feedback)3. Transfer Learning Across Problems
class TransferLearningAgent:
"""Learn from solving previous problems"""
def __init__(self):
self.knowledge_base = []
def solve_problem(self, problem):
"""Solve using knowledge from previous problems"""
# Find similar problems
similar_problems = self.find_similar(problem)
# Extract successful strategies
strategies = [
self.extract_strategy(p)
for p in similar_problems
]
# Apply strategies to new problem
adapted_strategies = [
self.adapt_strategy(s, problem)
for s in strategies
]
return self.synthesize_solution(adapted_strategies)
def extract_strategy(self, solved_problem):
"""Extract general strategy from solution"""
# Use LLM to identify key algorithmic patterns
passConclusion
Using LLMs for algorithm discovery represents a paradigm shift in how we approach computational research. By combining rigorous program verification with learned models of research quality, we can create autonomous agents that push beyond existing human knowledge.
Key Takeaways:
- Dual verification is essential: Both execution-based and peer-review-based evaluation prevent getting stuck in locally optimal but globally uninteresting solutions
- Iterative refinement works: The discover-verify-optimize loop effectively navigates the vast space of possible algorithms
- Real-world training matters: Reward models trained on actual peer review data significantly outperform generic LLMs at identifying promising ideas
- Success is possible but not guaranteed: Current systems achieve superhuman performance on ~25% of problems, showing both promise and room for improvement
Getting Started:
If you want to build your own algorithm discovery system:
- Start with a well-defined problem with automatic verification
- Implement a basic dual-environment setup
- Use a strong reasoning model (GPT-4, Claude, etc.) as your agent
- Iterate! The quality improves significantly with refinement
Looking Forward:
As LLMs continue to improve in reasoning and coding capabilities, autonomous algorithm discovery will likely become more reliable and applicable to broader problem domains. The combination of AI creativity and rigorous verification could accelerate scientific progress across mathematics, computer science, and beyond.
The algorithms discovered today are just the beginning. The real question isn’t whether AI can discover new algorithms — it’s how quickly we can scale these techniques to tackle humanity’s hardest computational challenges.
Resources and Further Reading
Primary Source:
- Novikov, A., Vũ, N., Eisenberger, M., Dupont, E., Huang, P.S., Wagner, A.Z., Shirobokov, S., Kozlovskii, B., Ruiz, F.J., Mehrabian, A., et al. (2025). “Accelerating New Algorithm Discovery with Language Models.” arXiv:2511.08522. Available at: https://arxiv.org/html/2511.08522v1
Related Papers:
- Novikov, A., et al. (2025). “AlphaEvolve: A coding agent for scientific and algorithmic discovery.” arXiv:2506.13131
- Si, C., Yang, D., & Hashimoto, T. (2024). “Can LLMs Generate Novel Research Ideas?”
- Si, C., Hashimoto, T., & Yang, D. (2025). “The ideation-execution gap: Execution outcomes of llm-generated versus human research ideas.” arXiv:2506.20803
- Tian, M., et al. (2024). “SciCode: A Research Coding Benchmark Curated by Scientists.” arXiv:2407.13168
- Lu, C., et al. (2024). “The AI Scientist: Towards fully automated open-ended scientific discovery.” arXiv:2408.06292
Code Repositories:
- AlphaResearch (official): https://github.com/answers111/alpha-research
- OpenEvolve (open-source reproduction): https://github.com/codelion/openevolve
Datasets:
- ICLR Peer Review Data (for reward model training): OpenReview.net
- AlphaResearchComp Benchmark: Available in the AlphaResearch repository
Tools and Frameworks:
- Hugging Face Transformers: https://huggingface.co/docs/transformers
- OpenAI API: https://platform.openai.com/docs
- Anthropic Claude API: https://docs.anthropic.com
Disclaimer: This article is an educational interpretation and implementation guide based on published research. For production use or research citations, please refer to the original papers and official repositories.
Have you experimented with LLM-based algorithm discovery? What challenges did you encounter? Share your experiences in the comments below!
Legal and Ethical Compliance Statement
This article is created for educational and informational purposes under fair use principles:
- Transformative Use: This is a technical tutorial and implementation guide, not a reproduction of the research paper
- Attribution: All concepts, results, and findings from the original research are properly cited
- Original Work: All code implementations are original examples created for educational demonstration
- No Competition: This article serves to explain and promote the research, not to replace or compete with it
For Academic Citation: If you use this article in your work, please cite both this tutorial and the original research paper:
- Original Research: Novikov et al. (2025). “Accelerating New Algorithm Discovery with Language Models.” arXiv:2511.08522
- Tutorial: [Your citation format for this Medium article]
Questions or Concerns? If you are an author of the cited research and have concerns about this article, please reach out for discussion or modification.
About the Author
Brian Curry is a Kansas City based Data Scientist, Artificial Intelligence expert and founder of Vector1 Research, a part-time passion project where he explores the frontier of Artificial Intelligence, SEO, Agentic Systems, Machine Learning, Economic Systems, Marketing Modeling, and Econometrics.
His work focuses on building intelligent systems that reveal the causal structures driving performance across marketing, content, and economics. He is the creator of:
- Papilon: An open-source framework for complex system optimization
- Daedalus: A platform for causal and economic analysis
- Memory-Node Encapsulation (MNE): A revolutionary data structure for artificial episodic memory and cognitive AI reasoning
Contact: brian at vector1.ai | Vector1 AI Economics Lab
Copyright and License
Tutorial Content: © 2025 Brian Curry. This tutorial, explanatory text, and implementation examples are the original work of the author.
Code Examples: All code implementations in this article are provided under the MIT License for educational and commercial use.
Research Attribution: Underlying concepts and research findings are attributed to their original authors (see References section). This tutorial is an independent educational work that explains and implements concepts from published research.
Last Updated: November 2025


