Skip to content

Latest commit

 

History

History
112 lines (84 loc) · 3.66 KB

CONTRIBUTING.md

File metadata and controls

112 lines (84 loc) · 3.66 KB

Contributing to ex-opt 🐦

Thanks for your interest in contributing! ex-opt is a C++20 black-box optimization framework, and we welcome contributions of all kinds — bug fixes, new algorithms, documentation, or performance improvements.

Getting Started

Prerequisites

  • A modern C++20 compiler (GCC >= 11, Clang >= 13)
  • CMake >= 3.25
  • Git

Setting Up

git clone --recursive https://github.com/SYSUljz/ex-opt.git
cd ex-opt
cmake -B build -S . -DEX_OPT_BUILD_TESTS=ON -DEX_OPT_BUILD_EXAMPLES=ON
cmake --build build -j$(nproc)

Run the test suite to make sure everything works:

cd build && ctest --output-on-failure

Development Workflow

  1. Fork the repository and create your branch from main.
  2. Write code following the project's style conventions (see below).
  3. Add tests for any new functionality. We target high coverage.
  4. Run the full test suite to ensure nothing is broken.
  5. Format your code using the provided script:
    python3 scripts/format.py
  6. Submit a pull request with a clear description of your changes.

Commit Messages

Use conventional commit prefixes to keep history readable:

  • [feat] — new feature or algorithm
  • [fix] — bug fix
  • [refactor] — code restructuring without behavior change
  • [docs] — documentation only
  • [test] — test additions or improvements
  • [build] — build system, CI, or dependency changes

Example: [feat] add Differential Evolution policy

Pull Requests

  • Keep PRs focused. One feature or fix per PR.
  • Link any related issues.
  • Make sure CI passes before requesting review.
  • New algorithms must include convergence tests on standard benchmark functions.

Code Style

We use clang-format with a Google-style-based configuration (120-column limit, C++20 include regrouping). The project follows modern C++20 idioms:

  • Prefer concepts over SFINAE or std::enable_if
  • Use std::span for array views, std::ranges algorithms where applicable
  • Document public APIs with Doxygen-style comments
  • Match the existing naming conventions: PascalCase for types, snake_case for functions
  • Put algorithm-specific code under include/policy/ and src/policy/

Adding a New Algorithm

ex-opt separates algorithm logic from execution scheduling. When adding an algorithm:

  1. Decide whether it's batch (population-based) or Stream (sequential).
  2. Implement a *Policy class inheriting from BatchPolicy<State> or StreamPolicy<State>.
  3. Put settings, solver, and result types in the same header.
  4. Add an overload in include/optimize.h for the convenience API.
  5. Add tests in test/ that verify convergence on at least the Sphere function.

Project Architecture

include/
├── ex_opt.h          # Core framework: WorkActor, Orchestrator, StreamOrchestrator
├── optimize.h           # Convenience optimize() API
├── boundary.h           # Search space / boundary definitions
├── logging.h            # spdlog wrappers
└── policy/
    ├── base_policy.h                # Abstract BatchPolicy / StreamPolicy
    ├── mapped_policy.h              # Mapper adapters for custom structs
    ├── particle_swarm_optimization.h
    ├── genetic_algorithm.h
    └── simulated_annealing.h

src/
├── logging.cpp
└── policy/
    ├── particle_swarm_optimization.cpp
    ├── genetic_algorithm.cpp
    └── simulated_annealing.cpp

test/
├── pso_test.cc
├── ga_test.cc
├── sa_test.cc
├── orchestrator_test.cc
└── struct_test.cc

Questions?

Feel free to open an issue on GitHub or start a discussion. We're happy to help!