# Protocol 11: Multi-Objective Optimization Support **Status:** MANDATORY **Applies To:** ALL optimization studies **Last Updated:** 2025-11-21 ## Overview ALL optimization engines in Atomizer MUST support both single-objective and multi-objective optimization without requiring code changes. This is a **critical requirement** that prevents runtime failures. ## The Problem Previously, IntelligentOptimizer (Protocol 10) only supported single-objective optimization. When used with multi-objective studies, it would: 1. Successfully run all trials 2. Save trials to the Optuna database (`study.db`) 3. **CRASH** when trying to compile results, causing: - No intelligent optimizer tracking files (confidence_history.json, strategy_transitions.json) - No optimization_summary.json - No final reports - Silent failures that are hard to debug ## The Root Cause Optuna has different APIs for single vs. multi-objective studies: ### Single-Objective ```python study.best_trial # Returns single Trial object study.best_params # Returns dict of parameters study.best_value # Returns float ``` ### Multi-Objective ```python study.best_trials # Returns LIST of Pareto-optimal trials study.best_params # ❌ RAISES RuntimeError study.best_value # ❌ RAISES RuntimeError study.best_trial # ❌ RAISES RuntimeError ``` ## The Solution ### 1. Always Check Study Type ```python is_multi_objective = len(study.directions) > 1 ``` ### 2. Use Conditional Access Patterns ```python if is_multi_objective: best_trials = study.best_trials if best_trials: # Select representative trial (e.g., first Pareto solution) representative_trial = best_trials[0] best_params = representative_trial.params best_value = representative_trial.values # Tuple best_trial_num = representative_trial.number else: best_params = {} best_value = None best_trial_num = None else: # Single-objective: safe to use standard API best_params = study.best_params best_value = study.best_value best_trial_num = study.best_trial.number ``` ### 3. Return Rich Metadata Always include in results: ```python { 'best_params': best_params, 'best_value': best_value, # float or tuple 'best_trial': best_trial_num, 'is_multi_objective': is_multi_objective, 'pareto_front_size': len(study.best_trials) if is_multi_objective else 1, # ... other fields } ``` ## Implementation Checklist When creating or modifying any optimization component: - [ ] **Study Creation**: Support `directions` parameter ```python if directions: study = optuna.create_study(directions=directions, ...) else: study = optuna.create_study(direction='minimize', ...) ``` - [ ] **Result Compilation**: Check `len(study.directions) > 1` - [ ] **Best Trial Access**: Use conditional logic (single vs. multi) - [ ] **Logging**: Print Pareto front size for multi-objective - [ ] **Reports**: Handle tuple objectives in visualization - [ ] **Testing**: Test with BOTH single and multi-objective cases ## Files Fixed - ✅ `optimization_engine/intelligent_optimizer.py` - `_compile_results()` method - `_run_fallback_optimization()` method ## Files That Need Review Check these files for similar issues: - [ ] `optimization_engine/study_continuation.py` (lines 96, 259-260) - [ ] `optimization_engine/hybrid_study_creator.py` (line 468) - [ ] `optimization_engine/intelligent_setup.py` (line 606) - [ ] `optimization_engine/llm_optimization_runner.py` (line 384) ## Testing Protocol Before marking any optimization study as complete: 1. **Single-Objective Test** ```python directions=None # or ['minimize'] # Should complete without errors ``` 2. **Multi-Objective Test** ```python directions=['minimize', 'minimize'] # Should complete without errors # Should generate ALL tracking files ``` 3. **Verify Outputs** - `2_results/study.db` exists - `2_results/intelligent_optimizer/` has tracking files - `2_results/optimization_summary.json` exists - No RuntimeError in logs ## Design Principle **"Write Once, Run Anywhere"** Any optimization component should: 1. Accept both single and multi-objective problems 2. Automatically detect the study type 3. Handle result compilation appropriately 4. Never raise RuntimeError due to API misuse ## Example: Bracket Study The bracket_stiffness_optimization study is multi-objective: - Objective 1: Maximize stiffness (minimize -stiffness) - Objective 2: Minimize mass - Constraint: mass ≤ 0.2 kg This study exposed the bug because: ```python directions = ["minimize", "minimize"] # Multi-objective ``` After the fix, it should: - Run all 50 trials successfully - Generate Pareto front with multiple solutions - Save all intelligent optimizer tracking files - Create complete reports with tuple objectives ## Future Work - Add explicit validation in `IntelligentOptimizer.__init__()` to warn about common mistakes - Create helper function `get_best_solution(study)` that handles both cases - Add unit tests for multi-objective support in all optimizers --- **Remember:** Multi-objective support is NOT optional. It's a core requirement for production-ready optimization engines.