Files
Atomizer/tests/unit/test_adaptive_characterization.py

165 lines
5.3 KiB
Python
Raw Normal View History

"""
Test script for Protocol 10 v2.0 Adaptive Characterization.
This script demonstrates the new adaptive characterization feature that
intelligently determines when enough landscape exploration has been done.
Expected behavior:
- Simple problems: Stop at ~10-15 trials
- Complex problems: Continue to ~20-30 trials
"""
import numpy as np
import optuna
from pathlib import Path
from optimization_engine.processors.adaptive_characterization import CharacterizationStoppingCriterion
from optimization_engine.reporting.landscape_analyzer import LandscapeAnalyzer
def simple_smooth_function(trial):
"""Simple smooth quadratic function (should stop early ~10-15 trials)."""
x = trial.suggest_float('x', -10, 10)
y = trial.suggest_float('y', -10, 10)
# Simple quadratic bowl
return (x - 3)**2 + (y + 2)**2
def complex_multimodal_function(trial):
"""Complex multimodal function (should need more trials ~20-30)."""
x = trial.suggest_float('x', -5, 5)
y = trial.suggest_float('y', -5, 5)
# Rastrigin function (multimodal, many local minima)
A = 10
n = 2
return A * n + ((x**2 - A * np.cos(2 * np.pi * x)) +
(y**2 - A * np.cos(2 * np.pi * y)))
def test_adaptive_characterization(
objective_function,
function_name: str,
expected_trials_range: tuple
):
"""Test adaptive characterization on a given function."""
print(f"\n{'='*70}")
print(f" TESTING: {function_name}")
print(f" Expected trials: {expected_trials_range[0]}-{expected_trials_range[1]}")
print(f"{'='*70}\n")
# Setup tracking directory
tracking_dir = Path(f"test_results/adaptive_char_{function_name.lower().replace(' ', '_')}")
tracking_dir.mkdir(parents=True, exist_ok=True)
# Create components
analyzer = LandscapeAnalyzer(min_trials_for_analysis=10)
stopping_criterion = CharacterizationStoppingCriterion(
min_trials=10,
max_trials=30,
confidence_threshold=0.85,
check_interval=5,
verbose=True,
tracking_dir=tracking_dir
)
# Create study
study = optuna.create_study(
study_name=f"test_{function_name.lower().replace(' ', '_')}",
direction='minimize',
sampler=optuna.samplers.RandomSampler()
)
# Run adaptive characterization
check_interval = 5
while not stopping_criterion.should_stop(study):
# Run batch of trials
study.optimize(objective_function, n_trials=check_interval)
# Analyze landscape
landscape = analyzer.analyze(study)
# Update stopping criterion
if landscape.get('ready', False):
completed_trials = [t for t in study.trials if t.state == optuna.trial.TrialState.COMPLETE]
stopping_criterion.update(landscape, len(completed_trials))
# Print results
completed_trials = [t for t in study.trials if t.state == optuna.trial.TrialState.COMPLETE]
actual_trials = len(completed_trials)
print(stopping_criterion.get_summary_report())
# Verify expectation
in_range = expected_trials_range[0] <= actual_trials <= expected_trials_range[1]
status = "PASS" if in_range else "FAIL"
print(f"\n{'='*70}")
print(f" RESULT: {status}")
print(f" Actual trials: {actual_trials}")
print(f" Expected range: {expected_trials_range[0]}-{expected_trials_range[1]}")
print(f" In range: {'YES' if in_range else 'NO'}")
print(f" Stop reason: {stopping_criterion.stop_reason}")
print(f" Final confidence: {stopping_criterion.final_confidence:.1%}")
print(f"{'='*70}\n")
return {
'function': function_name,
'expected_range': expected_trials_range,
'actual_trials': actual_trials,
'in_range': in_range,
'stop_reason': stopping_criterion.stop_reason,
'confidence': stopping_criterion.final_confidence
}
def main():
"""Run all adaptive characterization tests."""
print("\n" + "="*70)
print(" PROTOCOL 10 v2.0: ADAPTIVE CHARACTERIZATION TESTS")
print("="*70)
results = []
# Test 1: Simple smooth function (should stop early)
result1 = test_adaptive_characterization(
objective_function=simple_smooth_function,
function_name="Simple Smooth Quadratic",
expected_trials_range=(10, 20)
)
results.append(result1)
# Test 2: Complex multimodal function (should need more trials)
result2 = test_adaptive_characterization(
objective_function=complex_multimodal_function,
function_name="Complex Multimodal (Rastrigin)",
expected_trials_range=(15, 30)
)
results.append(result2)
# Summary
print("\n" + "="*70)
print(" TEST SUMMARY")
print("="*70)
for result in results:
status = "PASS" if result['in_range'] else "FAIL"
print(f"\n [{status}] {result['function']}")
print(f" Expected: {result['expected_range'][0]}-{result['expected_range'][1]} trials")
print(f" Actual: {result['actual_trials']} trials")
print(f" Confidence: {result['confidence']:.1%}")
# Overall pass/fail
all_passed = all(r['in_range'] for r in results)
overall_status = "ALL TESTS PASSED" if all_passed else "SOME TESTS FAILED"
print(f"\n{'='*70}")
print(f" {overall_status}")
print(f"{'='*70}\n")
if __name__ == "__main__":
main()