Skip to content

Refactor: Replace if-elif chain with optimizer config dict #470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

aries043
Copy link
Contributor

Summary

This PR refactors the benchmarking script by replacing the 80+ line if-elif chain for optimizer selection with a centralized, maintainable configuration system. The change improves code readability, maintainability, and makes it easier to add new optimizers in the future.

Problem

The current benchmarking script (benchmarking_lsbbo_2.py) contains a very long if-elif chain (80+ lines) for optimizer selection:

if params['optimizer'] == 'PRS':
    from pypop7.optimizers.rs.prs import PRS as Optimizer
elif params['optimizer'] == 'SRS':
    from pypop7.optimizers.rs.srs import SRS as Optimizer
elif params['optimizer'] == 'GS':
    from pypop7.optimizers.rs.gs import GS as Optimizer
# ... 80+ more lines

This approach has several issues:

  • Hard to maintain: Adding new optimizers requires modifying the long chain
  • Error-prone: Easy to make typos or miss entries
  • Poor readability: The logic is scattered across many lines
  • Code duplication: Similar import patterns repeated many times

Solution

1. Centralized Configuration

Replaced the if-elif chain with a dictionary-based configuration system:

OPTIMIZER_CONFIGS: Dict[str, OptimizerConfig] = {
    'PRS': OptimizerConfig('pypop7.optimizers.rs.prs', 'PRS', True),
    'SRS': OptimizerConfig('pypop7.optimizers.rs.srs', 'SRS', True),
    # ... all optimizers in one place
}

2. Dynamic Import Function

Created a clean function to handle optimizer loading:

def get_optimizer_class(optimizer_name: str) -> Type[Any]:
    """Dynamically import and return optimizer class based on name."""

3. Improved Error Handling

Added proper validation and helpful error messages:

  • Clear error when optimizer is not found
  • List of available optimizers in error message
  • Proper exception handling for import failures

4. Type Safety

Added comprehensive type hints throughout the code for better IDE support and catch potential issues early.

Key Benefits

  • ✅ Maintainability: Adding new optimizers now requires only one line in the config dictionary
  • ✅ Readability: All optimizer configurations are in one clear location
  • ✅ Error Prevention: Type hints and validation catch issues early
  • ✅ Consistency: Uniform handling of all optimizers
  • ✅ Extensibility: Easy to add metadata (like sigma requirements) for optimizers

Backward Compatibility

  • ✅ Command-line interface unchanged: All existing scripts and commands work exactly the same
  • ✅ All optimizers supported: Every optimizer from the original code is included
  • ✅ Same functionality: No behavioral changes, only structural improvements
  • ✅ Same output format: Results are saved in identical format

Testing

Added comprehensive GitHub Actions workflow that tests:

  • ✅ Syntax validation across Python 3.8-3.11
  • ✅ Optimizer class loading for all configured optimizers
  • ✅ Argument validation and error handling
  • ✅ Code quality (flake8, black, mypy)
  • ✅ Quick integration test with CMAES optimizer

Code Quality Improvements

  • Type hints: Full type annotation for better IDE support
  • Documentation: Added docstrings for all new functions
  • Error messages: More helpful and informative error reporting
  • Code organization: Logical separation of concerns

Files Changed

  • tutorials/benchmarking_lsbbo_2.py - Direct refactoring of the original file
  • .github/workflows/test-refactoring.yml - Comprehensive test suite

Future Enhancements

This refactoring lays the groundwork for future improvements:

  • Parallel execution support
  • Configuration file-based experiments
  • Enhanced logging and monitoring
  • Memory usage optimization

However, this PR focuses solely on the structural improvement to keep changes focused and reviewable.


Testing Instructions:

# Test the refactored script with any optimizer
python tutorials/benchmarking_lsbbo_2.py --start 0 --end 0 --optimizer CMAES --ndim_problem 10

# Verify all optimizers are loadable
python -c "from tutorials.benchmarking_lsbbo_2 import OPTIMIZER_CONFIGS; print(f'Configured optimizers: {len(OPTIMIZER_CONFIGS)}')"

aries043 added 8 commits May 28, 2025 15:19
…stry

- Replace 80+ line if-elif chain with centralized OPTIMIZER_CONFIGS dictionary
- Add type hints and proper error handling
- Improve code maintainability and readability
- Add comprehensive GitHub Actions testing workflow
- Include argument validation and better error messages

Fixes: Long if-elif chain making code hard to maintain
@Evolutionary-Intelligence
Copy link
Owner

@aries043 Thanks very much for your kindly suggestions. I will integrate this wonderful suggestion after I check it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants