Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OOPPG: Optimization as Scheduling

A Contextual Policy over Composable Optimizers

License: MIT Python 3.10+

Quick Start

git clone https://github.com/optimization-os/ooppg-core.git
cd ooppg-core
pip install -e .
PYTHONPATH=. python3 examples/quick_start.py

Benchmark Results

Two benchmarks on dim=20, budget=1500, 10 trials each:

DynaSwitch (Rastrigin → Rosenbrock, single switch)

Method Mean ± Std Regret (vs DE)
DE 30.71 ± 14.58 1.00
OOPPG v3 42.98 ± 16.66 1.40
Random Search 125.53 ± 17.14 4.09

RegimeReturn (Rastrigin → Sphere → Rastrigin, regime return)

Method Mean ± Std Regret (vs DE)
OOPPG v3 221.96 ± 18.41 0.79
Random Search 239.72 ± 14.11 0.85
DE 280.44 ± 23.93 1.00

On regime-return landscapes where the same regime reappears after a detour, OOPPG achieves ~20.9% improvement over static DE (221.96 vs 280.44), while stateless Random Search reaches 239.72. On single-switch benchmarks, static DE remains stronger (30.71 vs 42.98). Benchmarks managed via dyna-switch-benchmark.

How It Works

OOPPG is a meta-scheduler that automatically selects and switches between optimization algorithms based on the current landscape context:

  1. Observe optimization trajectory
  2. Encode landscape context (5D vector: variance, recent improvement, budget ratio, stagnation count, regime change)
  3. Select optimal optimizer via contextual bandit (LinUCB)
  4. Dispatch selected optimizer to executor
  5. Update scheduler policy based on improvement

Architecture

Gene Abstraction

The core abstraction is the Gene — a stateful optimizer primitive <Phi, Omega, Gamma, T>:

Component Role
StochasticKernel (Phi) Exploration pattern: gaussian_local, gaussian_global, momentum, de_full, de_mini, jump_to_best
ActivationPredicate (Omega) 3D predicate (stochastic, differential, temporal) gating when a gene activates
Gene Stateful unit with checkpoint/load for population persistence
Program Ordered composition of genes executed sequentially
GenePool Manages genes/programs, implements LinUCB scoring and 2-step MCTS look-ahead

Available Genes

Gene File Description
DE (full/mini) gene.py Differential Evolution with full or reduced population
CMA-ES cma_gene.py Covariance Matrix Adaptation with cross-algorithm state continuity
PSO pso_gene.py Particle Swarm Optimization with swarm state persistence
Bayesian Optimization bo_gene.py Gaussian Process surrogate with acquisition functions
Adversarial adversarial_gene.py Robust gene for deceptive gradients, rapid switching, oscillating regimes
Local Search gene.py Gaussian local perturbation

Core Modules

Module Description
core/gene.py Gene/Program/GenePool core abstractions (~1490 lines)
core/state_mapper.py Cross-algorithm state mapping (DE ↔ CMA-ES, PSO, BO)
core/cpd.py Change point detection (CUSUM / BOCPD / Hybrid)
core/cma_gene.py CMA-ES gene implementation
core/pso_gene.py PSO gene implementation
core/bo_gene.py Bayesian Optimization gene implementation
core/adversarial_gene.py Adversarial perturbation gene implementation
optimizers/ooppg_meta.py Main LinUCB contextual meta-scheduler (OOPPGMeta.optimize())
optimizers/baselines_scheduler.py Baseline schedulers (Static, Random, Oracle)
utils/baselines.py Standard baseline algorithm wrappers
utils/context_features.py 5D landscape context feature extraction

High-Level SDK

import numpy as np
from ooppg import OptimizationOS, Gene, StochasticKernel, ActivationPredicate

# 1. Define standard optimization Genes
de_gene = Gene(
    name='de_full',
    kernel=StochasticKernel('de_full', {'pop_size': 20, 'F': 0.8, 'CR': 0.9}),
    predicate=ActivationPredicate('de_full', {'temporal': {'tau_min': 0.0, 'tau_max': 0.9}})
)

local_gene = Gene(
    name='local_search',
    kernel=StochasticKernel('gaussian_local', {'sigma': 0.1}),
    predicate=ActivationPredicate('local_search', {})
)

# 2. Initialize the Meta-Scheduler with your Genes
scheduler = OptimizationOS(genes=[de_gene, local_gene])

# 3. Minimize your objective function
def objective(x): return np.sum(x**2)

best_x = scheduler.minimize(
    f=objective,
    budget=1000,
    domain=[(-5.12, 5.12)] * 10
)

When to Use OOPPG

  • Non-stationary optimization landscapes
  • Problems with recurring regimes or phase shifts
  • When no single optimizer dominates all phases

When NOT to Use OOPPG

  • Static, well-characterized problems
  • When a single algorithm is already optimized for your domain
  • When computational overhead is critical

Citation

If you use OOPPG in your research or application, please cite:

@software{ooppg2026,
  author = {Yingjie Gao},
  title = {OOPPG: A Contextual Policy over Composable Optimizers},
  url = {https://github.com/optimization-os/ooppg-core},
  year = {2026}
}

License

MIT License - see LICENSE for details.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors