hoptimal 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. hoptimal-0.1.0/.dockerignore +26 -0
  2. hoptimal-0.1.0/.github/workflows/ci.yml +39 -0
  3. hoptimal-0.1.0/.github/workflows/release.yml +86 -0
  4. hoptimal-0.1.0/.gitignore +35 -0
  5. hoptimal-0.1.0/CMakeLists.txt +121 -0
  6. hoptimal-0.1.0/Dockerfile +48 -0
  7. hoptimal-0.1.0/LICENSE +21 -0
  8. hoptimal-0.1.0/PKG-INFO +188 -0
  9. hoptimal-0.1.0/README.md +138 -0
  10. hoptimal-0.1.0/benchmarks/python/bench_speed.py +138 -0
  11. hoptimal-0.1.0/benchmarks/python/competitors/__init__.py +0 -0
  12. hoptimal-0.1.0/benchmarks/python/competitors/bench_competitors.py +218 -0
  13. hoptimal-0.1.0/benchmarks/python/ml/__init__.py +0 -0
  14. hoptimal-0.1.0/benchmarks/python/ml/bench_sklearn.py +100 -0
  15. hoptimal-0.1.0/benchmarks/python/results/regret_curves.png +0 -0
  16. hoptimal-0.1.0/benchmarks/python/results/regret_curves.svg +12350 -0
  17. hoptimal-0.1.0/benchmarks/python/run_all.py +69 -0
  18. hoptimal-0.1.0/benchmarks/python/synthetic/__init__.py +0 -0
  19. hoptimal-0.1.0/benchmarks/python/synthetic/bench_synthetic.py +66 -0
  20. hoptimal-0.1.0/benchmarks/python/synthetic/functions.py +120 -0
  21. hoptimal-0.1.0/benchmarks/python/visualize.py +106 -0
  22. hoptimal-0.1.0/examples/demo.ipynb +280 -0
  23. hoptimal-0.1.0/examples/test_catboost.py +30 -0
  24. hoptimal-0.1.0/examples/test_jax.py +36 -0
  25. hoptimal-0.1.0/examples/test_lightgbm.py +30 -0
  26. hoptimal-0.1.0/examples/test_pytorch.py +50 -0
  27. hoptimal-0.1.0/examples/test_sklearn.py +36 -0
  28. hoptimal-0.1.0/examples/test_tensorflow.py +40 -0
  29. hoptimal-0.1.0/examples/test_xgboost.py +31 -0
  30. hoptimal-0.1.0/include/hoptimal/core/pruner.hpp +21 -0
  31. hoptimal-0.1.0/include/hoptimal/core/sampler.hpp +43 -0
  32. hoptimal-0.1.0/include/hoptimal/core/search_space.hpp +79 -0
  33. hoptimal-0.1.0/include/hoptimal/core/storage.hpp +34 -0
  34. hoptimal-0.1.0/include/hoptimal/core/study.hpp +105 -0
  35. hoptimal-0.1.0/include/hoptimal/core/trial.hpp +109 -0
  36. hoptimal-0.1.0/include/hoptimal/core/types.hpp +25 -0
  37. hoptimal-0.1.0/include/hoptimal/gp/acquisition.hpp +48 -0
  38. hoptimal-0.1.0/include/hoptimal/gp/gaussian_process.hpp +59 -0
  39. hoptimal-0.1.0/include/hoptimal/gp/kernel.hpp +86 -0
  40. hoptimal-0.1.0/include/hoptimal/pruners/hyperband_pruner.hpp +42 -0
  41. hoptimal-0.1.0/include/hoptimal/pruners/median_pruner.hpp +26 -0
  42. hoptimal-0.1.0/include/hoptimal/samplers/gp_sampler.hpp +79 -0
  43. hoptimal-0.1.0/include/hoptimal/samplers/random_sampler.hpp +34 -0
  44. hoptimal-0.1.0/include/hoptimal/storage/memory_storage.hpp +32 -0
  45. hoptimal-0.1.0/include/hoptimal/utils/lbfgs.hpp +36 -0
  46. hoptimal-0.1.0/include/hoptimal/utils/linalg.hpp +37 -0
  47. hoptimal-0.1.0/include/hoptimal/utils/statistics.hpp +20 -0
  48. hoptimal-0.1.0/pyproject.toml +59 -0
  49. hoptimal-0.1.0/python/bindings/bindings.cpp +199 -0
  50. hoptimal-0.1.0/python/hoptimal/__init__.py +66 -0
  51. hoptimal-0.1.0/python/hoptimal/integrations/__init__.py +1 -0
  52. hoptimal-0.1.0/python/hoptimal/integrations/catboost.py +126 -0
  53. hoptimal-0.1.0/python/hoptimal/integrations/jax_flax.py +97 -0
  54. hoptimal-0.1.0/python/hoptimal/integrations/lightgbm.py +152 -0
  55. hoptimal-0.1.0/python/hoptimal/integrations/pytorch.py +115 -0
  56. hoptimal-0.1.0/python/hoptimal/integrations/sklearn.py +156 -0
  57. hoptimal-0.1.0/python/hoptimal/integrations/tensorflow.py +165 -0
  58. hoptimal-0.1.0/python/hoptimal/integrations/xgboost.py +166 -0
  59. hoptimal-0.1.0/src/core/search_space.cpp +133 -0
  60. hoptimal-0.1.0/src/core/study.cpp +265 -0
  61. hoptimal-0.1.0/src/core/trial.cpp +84 -0
  62. hoptimal-0.1.0/src/gp/acquisition.cpp +133 -0
  63. hoptimal-0.1.0/src/gp/gaussian_process.cpp +139 -0
  64. hoptimal-0.1.0/src/gp/kernel.cpp +97 -0
  65. hoptimal-0.1.0/src/pruners/hyperband_pruner.cpp +70 -0
  66. hoptimal-0.1.0/src/pruners/median_pruner.cpp +51 -0
  67. hoptimal-0.1.0/src/samplers/gp_sampler.cpp +203 -0
  68. hoptimal-0.1.0/src/samplers/random_sampler.cpp +69 -0
  69. hoptimal-0.1.0/src/storage/memory_storage.cpp +50 -0
  70. hoptimal-0.1.0/src/utils/lbfgs.cpp +128 -0
  71. hoptimal-0.1.0/tests/integration/CMakeLists.txt +18 -0
  72. hoptimal-0.1.0/tests/integration/test_sampler_convergence.cpp +117 -0
  73. hoptimal-0.1.0/tests/integration/test_study_e2e.cpp +166 -0
  74. hoptimal-0.1.0/tests/unit/CMakeLists.txt +24 -0
  75. hoptimal-0.1.0/tests/unit/test_acquisition.cpp +117 -0
  76. hoptimal-0.1.0/tests/unit/test_gaussian_process.cpp +145 -0
  77. hoptimal-0.1.0/tests/unit/test_kernel.cpp +122 -0
  78. hoptimal-0.1.0/tests/unit/test_pruners.cpp +109 -0
  79. hoptimal-0.1.0/tests/unit/test_search_space.cpp +195 -0
  80. hoptimal-0.1.0/tests/unit/test_storage.cpp +218 -0
  81. hoptimal-0.1.0/tests/unit/test_study.cpp +258 -0
  82. hoptimal-0.1.0/tests/unit/test_trial.cpp +226 -0
  83. hoptimal-0.1.0/vcpkg.json +9 -0
@@ -0,0 +1,26 @@
1
+ # Build artifacts — rebuilt inside the image
2
+ build/
3
+ **/__pycache__/
4
+ *.so
5
+ *.pyd
6
+ *.o
7
+ *.a
8
+
9
+ # Local logs / scratch captured during the Windows dev session
10
+ logs*.txt
11
+ test_results.txt
12
+
13
+ # Benchmark outputs (regenerated)
14
+ benchmarks/python/results/*.json
15
+
16
+ # VCS / editor
17
+ .git/
18
+ .gitignore
19
+ .vs/
20
+ .vscode/
21
+ .idea/
22
+
23
+ # Python packaging cruft
24
+ *.egg-info/
25
+ dist/
26
+ .pytest_cache/
@@ -0,0 +1,39 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+ workflow_dispatch: # allow manual runs
8
+ schedule:
9
+ - cron: "0 6 * * 1" # weekly Monday 06:00 UTC — runs the heavy DL job
10
+
11
+ jobs:
12
+ # ── Core + classic ML integrations ──────────────────────────────────────────
13
+ # Reuses the project Dockerfile so CI and local `docker build` are identical.
14
+ # The `integrations` stage builds the C++ core, runs all 130 tests, builds the
15
+ # pybind11 module, and runs the sklearn/xgboost/lightgbm/catboost smoke tests.
16
+ build-and-test:
17
+ name: build + test (core + integrations)
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Build and test via Docker (target=integrations)
23
+ run: docker build --target integrations -t hoptimal:ci .
24
+
25
+ # ── Deep-learning integrations (heavy; weekly + manual only) ─────────────────
26
+ # torch + tensorflow + jax are multi-GB, so this doesn't gate every push.
27
+ deep-learning:
28
+ name: deep-learning integrations (torch / jax / tensorflow)
29
+ runs-on: ubuntu-latest
30
+ if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+
34
+ - name: Free up disk space
35
+ run: |
36
+ sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android || true
37
+
38
+ - name: Build and test via Docker (target=dl)
39
+ run: docker build --target dl -t hoptimal:dl .
@@ -0,0 +1,86 @@
1
+ name: release
2
+
3
+ # Builds wheels for Linux/macOS/Windows + an sdist, then publishes to PyPI.
4
+ # Triggers when you publish a GitHub Release (recommended), or manually.
5
+ on:
6
+ release:
7
+ types: [published]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ # ── Build binary wheels on every platform ────────────────────────────────────
12
+ wheels:
13
+ name: wheels on ${{ matrix.os }}
14
+ runs-on: ${{ matrix.os }}
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ # macos-14 (Apple Silicon) cross-builds BOTH arm64 and x86_64 via
19
+ # CIBW_ARCHS_MACOS below, so a separate macos-13 (Intel) runner would
20
+ # only produce duplicate wheels — and those Intel runners are queue-
21
+ # constrained as GitHub winds them down. One macOS runner covers both.
22
+ os: [ubuntu-latest, windows-latest, macos-14]
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+
26
+ - name: Build wheels
27
+ uses: pypa/cibuildwheel@v2.21
28
+ env:
29
+ # Skip PyPy and musllinux to keep the matrix lean; add back if wanted.
30
+ CIBW_SKIP: "pp* *-musllinux_*"
31
+ # 64-bit only — the C++20 core has no reason to ship 32-bit wheels,
32
+ # and the 32-bit manylinux/Windows images use an older toolchain.
33
+ CIBW_ARCHS_LINUX: x86_64
34
+ CIBW_ARCHS_WINDOWS: AMD64
35
+ CIBW_ARCHS_MACOS: "x86_64 arm64"
36
+ # libc++ marks std::variant/std::visit "unavailable" below macOS 10.13,
37
+ # which this code uses. Raise the x86_64 deployment target (cibuildwheel
38
+ # clamps arm64 to its 11.0 minimum automatically).
39
+ CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=10.13
40
+ # C++20 needs a modern toolchain — manylinux2014's GCC 10 is too old
41
+ # for parts of the standard library, so build on the GCC 12 image.
42
+ CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
43
+ # Surface the real CMake/compiler error if a build fails.
44
+ CIBW_BUILD_VERBOSITY: "1"
45
+ # Smoke-test each built wheel actually imports + runs.
46
+ CIBW_TEST_REQUIRES: numpy
47
+ CIBW_TEST_COMMAND: >-
48
+ python -c "import hoptimal; s = hoptimal.create_study();
49
+ print('hoptimal', getattr(hoptimal, '__version__', 'ok'))"
50
+
51
+ - uses: actions/upload-artifact@v4
52
+ with:
53
+ name: wheels-${{ matrix.os }}
54
+ path: ./wheelhouse/*.whl
55
+
56
+ # ── Build the source distribution ────────────────────────────────────────────
57
+ sdist:
58
+ name: sdist
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+ - name: Build sdist
63
+ run: pipx run build --sdist
64
+ - uses: actions/upload-artifact@v4
65
+ with:
66
+ name: sdist
67
+ path: ./dist/*.tar.gz
68
+
69
+ # ── Publish to PyPI via Trusted Publishing (OIDC, no API tokens) ─────────────
70
+ publish:
71
+ name: publish to PyPI
72
+ needs: [wheels, sdist]
73
+ runs-on: ubuntu-latest
74
+ # Only publish for real releases, not manual dry-runs.
75
+ if: github.event_name == 'release'
76
+ environment:
77
+ name: pypi
78
+ url: https://pypi.org/p/hoptimal
79
+ permissions:
80
+ id-token: write # required for Trusted Publishing
81
+ steps:
82
+ - uses: actions/download-artifact@v4
83
+ with:
84
+ path: dist
85
+ merge-multiple: true
86
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,35 @@
1
+ # Build artifacts
2
+ build/
3
+ dist/
4
+ *.so
5
+ *.pyd
6
+ *.o
7
+ *.a
8
+ *.egg-info/
9
+
10
+ # Python
11
+ __pycache__/
12
+ *.pyc
13
+ .pytest_cache/
14
+ .venv/
15
+ venv/
16
+ .ipynb_checkpoints/
17
+
18
+ # Local logs / scratch from the dev session
19
+ logs*.txt
20
+ test_results.txt
21
+
22
+ # Benchmark run outputs (regenerated; commit curated results only)
23
+ benchmarks/python/results/*.json
24
+
25
+ # Planning / design docs kept outside the public repo.
26
+ PORTFOLIO_PLAN.md
27
+ hoptimal_architecture.md
28
+ docs/
29
+
30
+ # Editor / OS
31
+ .vs/
32
+ .vscode/
33
+ .idea/
34
+ .DS_Store
35
+ Thumbs.db
@@ -0,0 +1,121 @@
1
+ cmake_minimum_required(VERSION 3.20)
2
+ project(hoptimal VERSION 0.1.0 LANGUAGES CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 20)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+ set(CMAKE_CXX_EXTENSIONS OFF)
7
+
8
+ option(HOPTIMAL_BUILD_TESTS "Build C++ unit/integration tests" ON)
9
+ option(HOPTIMAL_BUILD_BENCHMARKS "Build C++ microbenchmarks" OFF)
10
+ option(HOPTIMAL_BUILD_PYTHON "Build pybind11 Python bindings" OFF)
11
+ option(HOPTIMAL_USE_SANITIZERS "Enable ASan + UBSan (non-MSVC)" OFF)
12
+
13
+ # ── Dependencies (try find_package first, fall back to FetchContent) ──────────
14
+ include(FetchContent)
15
+
16
+ # Eigen3 — header-only. Prefer a system/vcpkg install; otherwise fetch the
17
+ # source from git. We need only the headers, so we populate the source WITHOUT
18
+ # running Eigen's own CMake: SOURCE_SUBDIR points at a nonexistent directory so
19
+ # FetchContent_MakeAvailable downloads but skips add_subdirectory(). That avoids
20
+ # (a) GitLab archive-checksum drift (we clone a tag instead of pinning a tarball
21
+ # hash) and (b) a duplicate-target clash on Eigen3::Eigen that Eigen's own CMake
22
+ # would otherwise create.
23
+ find_package(Eigen3 3.4 QUIET)
24
+ if(NOT Eigen3_FOUND)
25
+ message(STATUS "Eigen3 not found — fetching 3.4.0 via FetchContent (needs internet)")
26
+ FetchContent_Declare(eigen3
27
+ GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
28
+ GIT_TAG 3.4.0
29
+ GIT_SHALLOW TRUE
30
+ SOURCE_SUBDIR cmake-do-not-configure
31
+ )
32
+ FetchContent_MakeAvailable(eigen3)
33
+ if(NOT TARGET Eigen3::Eigen)
34
+ add_library(Eigen3::Eigen INTERFACE IMPORTED)
35
+ target_include_directories(Eigen3::Eigen INTERFACE ${eigen3_SOURCE_DIR})
36
+ endif()
37
+ endif()
38
+
39
+ # GoogleTest (only when tests are requested)
40
+ if(HOPTIMAL_BUILD_TESTS)
41
+ find_package(GTest QUIET)
42
+ if(NOT GTest_FOUND)
43
+ message(STATUS "GTest not found — fetching via FetchContent")
44
+ FetchContent_Declare(googletest
45
+ URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
46
+ )
47
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
48
+ FetchContent_MakeAvailable(googletest)
49
+ endif()
50
+ endif()
51
+
52
+ # pybind11 (only when Python bindings are requested)
53
+ if(HOPTIMAL_BUILD_PYTHON)
54
+ find_package(pybind11 QUIET)
55
+ if(NOT pybind11_FOUND)
56
+ FetchContent_Declare(pybind11
57
+ URL https://github.com/pybind/pybind11/archive/refs/tags/v2.12.0.tar.gz
58
+ )
59
+ FetchContent_MakeAvailable(pybind11)
60
+ endif()
61
+ endif()
62
+
63
+ # ── hoptimal_core static library ──────────────────────────────────────────────────
64
+ add_library(hoptimal_core STATIC
65
+ # core
66
+ src/core/search_space.cpp
67
+ src/core/trial.cpp
68
+ src/core/study.cpp
69
+ src/storage/memory_storage.cpp
70
+ src/samplers/random_sampler.cpp
71
+ # Gaussian-process Bayesian optimization
72
+ src/utils/lbfgs.cpp
73
+ src/gp/kernel.cpp
74
+ src/gp/gaussian_process.cpp
75
+ src/gp/acquisition.cpp
76
+ src/samplers/gp_sampler.cpp
77
+ # pruners
78
+ src/pruners/median_pruner.cpp
79
+ src/pruners/hyperband_pruner.cpp
80
+ )
81
+
82
+ target_include_directories(hoptimal_core PUBLIC
83
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
84
+ $<INSTALL_INTERFACE:include>
85
+ )
86
+
87
+ target_link_libraries(hoptimal_core PUBLIC Eigen3::Eigen)
88
+
89
+ # Build with position-independent code so the static hoptimal_core library can be
90
+ # linked into the _hoptimal shared module (pybind11). On Linux, linking a non-PIC
91
+ # static lib into a .so fails ("relocation ... can not be used when making a
92
+ # shared object; recompile with -fPIC"). Harmless for the test executables.
93
+ set_target_properties(hoptimal_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
94
+
95
+ target_compile_options(hoptimal_core PRIVATE
96
+ $<$<CXX_COMPILER_ID:MSVC>:/W4 /wd4100 /wd4127>
97
+ $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -Wpedantic>
98
+ )
99
+
100
+ if(HOPTIMAL_USE_SANITIZERS AND NOT MSVC)
101
+ target_compile_options(hoptimal_core PRIVATE
102
+ -fsanitize=address,undefined -fno-omit-frame-pointer)
103
+ target_link_options(hoptimal_core PRIVATE
104
+ -fsanitize=address,undefined)
105
+ endif()
106
+
107
+ # ── Tests ─────────────────────────────────────────────────────────────────────
108
+ if(HOPTIMAL_BUILD_TESTS)
109
+ enable_testing()
110
+ add_subdirectory(tests/unit)
111
+ add_subdirectory(tests/integration)
112
+ endif()
113
+
114
+ # ── Python bindings ───────────────────────────────────────────────────────────
115
+ if(HOPTIMAL_BUILD_PYTHON)
116
+ pybind11_add_module(_hoptimal python/bindings/bindings.cpp)
117
+ target_link_libraries(_hoptimal PRIVATE hoptimal_core)
118
+ # scikit-build-core maps wheel.packages = ["python/hoptimal"] → the `hoptimal`
119
+ # package at the wheel root, so the compiled module installs into `hoptimal/`.
120
+ install(TARGETS _hoptimal DESTINATION hoptimal)
121
+ endif()
@@ -0,0 +1,48 @@
1
+ FROM python:3.11-slim AS core
2
+
3
+ RUN apt-get update && apt-get install -y --no-install-recommends \
4
+ build-essential \
5
+ cmake \
6
+ ninja-build \
7
+ git \
8
+ libeigen3-dev \
9
+ libgtest-dev \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ WORKDIR /hoptimal
13
+ COPY . .
14
+
15
+ RUN cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DHOPTIMAL_BUILD_TESTS=ON \
16
+ && cmake --build build -j"$(nproc)" \
17
+ && ctest --test-dir build --output-on-failure
18
+
19
+ RUN pip install --no-cache-dir . && pip install --no-cache-dir pytest
20
+
21
+ RUN python -c "import hoptimal; \
22
+ s=hoptimal.create_study('minimize'); \
23
+ s.optimize(lambda t:(t.suggest_float('x',-5,5)-2)**2, 30); \
24
+ print('core OK — best:', s.best_value, s.best_params)"
25
+
26
+ FROM core AS integrations
27
+
28
+ RUN pip install --no-cache-dir \
29
+ scikit-learn \
30
+ xgboost \
31
+ lightgbm \
32
+ catboost \
33
+ optuna \
34
+ scikit-optimize
35
+
36
+ RUN python examples/test_sklearn.py \
37
+ && python examples/test_xgboost.py \
38
+ && python examples/test_lightgbm.py \
39
+ && python examples/test_catboost.py
40
+
41
+ FROM integrations AS dl
42
+
43
+ RUN pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu
44
+ RUN pip install --no-cache-dir "jax[cpu]" flax tensorflow-cpu
45
+
46
+ RUN python examples/test_pytorch.py \
47
+ && python examples/test_jax.py \
48
+ && python examples/test_tensorflow.py
hoptimal-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel Dema
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,188 @@
1
+ Metadata-Version: 2.4
2
+ Name: hoptimal
3
+ Version: 0.1.0
4
+ Summary: High-performance hyperparameter optimisation — C++ core, Python bindings
5
+ Keywords: hyperparameter,optimization,bayesian-optimization,gaussian-process,tpe,cma-es,machine-learning,automl
6
+ Author-Email: Daniel Dema <danieldema42@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: C++
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Classifier: Operating System :: OS Independent
16
+ Project-URL: Homepage, https://github.com/danieldema/hoptimal
17
+ Project-URL: Repository, https://github.com/danieldema/hoptimal
18
+ Project-URL: Issues, https://github.com/danieldema/hoptimal/issues
19
+ Requires-Python: >=3.9
20
+ Requires-Dist: numpy>=1.24
21
+ Provides-Extra: sklearn
22
+ Requires-Dist: scikit-learn>=1.3; extra == "sklearn"
23
+ Provides-Extra: torch
24
+ Requires-Dist: torch>=2.0; extra == "torch"
25
+ Provides-Extra: tensorflow
26
+ Requires-Dist: tensorflow>=2.13; extra == "tensorflow"
27
+ Provides-Extra: jax
28
+ Requires-Dist: jax>=0.4; extra == "jax"
29
+ Requires-Dist: flax>=0.7; extra == "jax"
30
+ Provides-Extra: xgboost
31
+ Requires-Dist: xgboost>=2.0; extra == "xgboost"
32
+ Provides-Extra: lightgbm
33
+ Requires-Dist: lightgbm>=4.0; extra == "lightgbm"
34
+ Provides-Extra: catboost
35
+ Requires-Dist: catboost>=1.2; extra == "catboost"
36
+ Provides-Extra: benchmark
37
+ Requires-Dist: optuna; extra == "benchmark"
38
+ Requires-Dist: hyperopt; extra == "benchmark"
39
+ Requires-Dist: botorch; extra == "benchmark"
40
+ Requires-Dist: scikit-optimize; extra == "benchmark"
41
+ Requires-Dist: ray[tune]; extra == "benchmark"
42
+ Requires-Dist: flaml; extra == "benchmark"
43
+ Requires-Dist: nevergrad; extra == "benchmark"
44
+ Requires-Dist: plotly; extra == "benchmark"
45
+ Requires-Dist: pandas; extra == "benchmark"
46
+ Requires-Dist: scipy; extra == "benchmark"
47
+ Provides-Extra: all
48
+ Requires-Dist: hoptimal[benchmark,catboost,jax,lightgbm,sklearn,tensorflow,torch,xgboost]; extra == "all"
49
+ Description-Content-Type: text/markdown
50
+
51
+ # hoptimal
52
+
53
+ [![CI](https://github.com/danieldema/hoptimal/actions/workflows/ci.yml/badge.svg)](https://github.com/danieldema/hoptimal/actions/workflows/ci.yml)
54
+ ![C++20](https://img.shields.io/badge/C%2B%2B-20-blue)
55
+ ![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)
56
+ ![License: MIT](https://img.shields.io/badge/license-MIT-green)
57
+
58
+ **A from-scratch C++ Gaussian-Process Bayesian optimizer with Python bindings — competitive with Optuna and scikit-optimize on sample efficiency.**
59
+
60
+ hoptimal implements Bayesian optimization (a Gaussian-Process surrogate + acquisition
61
+ functions) in modern C++20, exposed to Python through pybind11. The GP, the
62
+ Cholesky-based inference, the kernel-hyperparameter fitting, and the acquisition
63
+ optimization are all hand-written — no GPyTorch, no BoTorch, no scikit-learn under
64
+ the hood.
65
+
66
+ ## Benchmark
67
+
68
+ Median regret (best-found − known optimum, lower is better) vs trial number on 8
69
+ standard optimization test functions, 8 seeds each — hoptimal against Optuna and
70
+ scikit-optimize:
71
+
72
+ ![regret curves](benchmarks/python/results/regret_curves.png)
73
+
74
+ hoptimal's GP methods are **best-in-class**: across the 8 functions they win 4
75
+ outright and place 2nd on the other 4, beating Optuna's TPE and CMA-ES and
76
+ trading wins with scikit-optimize's GP — especially strong on the harder
77
+ higher-dimensional problems (Hartmann-6, Ackley, Rosenbrock, Rastrigin).
78
+
79
+ | Function | hoptimal (best) | Optuna (best) | scikit-optimize |
80
+ |----------|------------:|--------------:|----------------:|
81
+ | branin | 0.0018 | 0.70 | **0.0011** |
82
+ | hartmann3 | 0.013 | 0.15 | **0.0002** |
83
+ | hartmann6 | **0.14** | 1.06 | 0.23 |
84
+ | ackley5 | **2.48** | 3.30 | 2.78 |
85
+ | rosenbrock4 | **5.29** | 10.4 | 9.28 |
86
+ | levy5 | 2.17 | **2.07** | 3.98 |
87
+ | rastrigin5 | **18.3** | 27.7 | 41.1 |
88
+ | styblinski5 | 48.8 | 55.5 | **27.7** |
89
+
90
+ Reproduce: `python benchmarks/python/competitors/bench_competitors.py && python benchmarks/python/visualize.py`
91
+
92
+ ## Quickstart
93
+
94
+ ```python
95
+ import hoptimal
96
+
97
+ study = hoptimal.create_study("minimize") # GP + Expected Improvement by default
98
+
99
+ def objective(trial):
100
+ x = trial.suggest_float("x", -5.0, 5.0)
101
+ y = trial.suggest_float("y", -5.0, 5.0)
102
+ return (x - 2.0) ** 2 + (y + 1.0) ** 2
103
+
104
+ study.optimize(objective, n_trials=50)
105
+ print(study.best_value, study.best_params)
106
+ ```
107
+
108
+ The `Trial` API mirrors Optuna's, so migration is mostly mechanical. For a
109
+ runnable tour (toy problem → Branin convergence plot → real sklearn model →
110
+ head-to-head vs Optuna) see [`examples/demo.ipynb`](examples/demo.ipynb).
111
+
112
+ ## Features
113
+
114
+ | Capability | Status |
115
+ |------------|--------|
116
+ | GP Bayesian optimization — **EI**, **UCB**, **PI** acquisitions | ✅ |
117
+ | RBF and Matérn-5/2 kernels, MLE hyperparameter fitting (L-BFGS) | ✅ |
118
+ | Float / int / log-scale / categorical parameters | ✅ |
119
+ | Multi-objective optimization (Pareto front) | ✅ |
120
+ | Median and Hyperband pruners (early stopping) | ✅ |
121
+ | Parallel trials (`n_jobs`) with constant-liar | ✅ |
122
+ | ML integrations: scikit-learn, XGBoost, LightGBM, CatBoost, PyTorch, JAX/Flax, TensorFlow/Keras | ✅ |
123
+
124
+ All integrations are validated on clean Linux in CI (see the Dockerfile).
125
+
126
+ ### scikit-learn example
127
+
128
+ ```python
129
+ from sklearn.svm import SVC
130
+ from sklearn.pipeline import Pipeline
131
+ from sklearn.preprocessing import StandardScaler
132
+ from hoptimal.integrations.sklearn import HoptimalSearchCV
133
+
134
+ pipe = Pipeline([("scaler", StandardScaler()), ("svc", SVC())])
135
+ search = HoptimalSearchCV(
136
+ pipe,
137
+ {"svc__C": ("float", 1e-3, 1e3, {"log": True}),
138
+ "svc__gamma": ("float", 1e-4, 1e0, {"log": True}),
139
+ "svc__kernel":("categorical", ["rbf", "sigmoid"])},
140
+ n_trials=40, cv=5, scoring="accuracy",
141
+ )
142
+ search.fit(X, y)
143
+ print(search.best_score_, search.best_params_)
144
+ ```
145
+
146
+ ## Build from source
147
+
148
+ **With Docker (recommended — builds + tests + validates integrations on clean Linux):**
149
+
150
+ ```bash
151
+ docker build --target core -t hoptimal . # C++ core + tests + bindings
152
+ docker build --target integrations -t hoptimal . # + sklearn/xgboost/lightgbm/catboost
153
+ docker build --target dl -t hoptimal . # + pytorch/jax/tensorflow (heavy)
154
+ ```
155
+
156
+ **Locally** (needs a C++20 compiler, CMake, Eigen3; GoogleTest/pybind11 are
157
+ fetched automatically if absent):
158
+
159
+ ```bash
160
+ # C++ library + tests
161
+ cmake -B build -DHOPTIMAL_BUILD_TESTS=ON
162
+ cmake --build build --parallel
163
+ ctest --test-dir build --output-on-failure
164
+
165
+ # Python package
166
+ pip install .
167
+ ```
168
+
169
+ ## How it works
170
+
171
+ Each trial, hoptimal fits a **Gaussian Process** to the observations so far, then
172
+ picks the next point by optimizing an **acquisition function** over the GP's
173
+ posterior. The implementation is hand-written C++:
174
+
175
+ - **GP regression** with RBF / Matérn-5/2 kernels; inference via a
176
+ **Cholesky factorization** of `K + σ²I` (with jitter for stability) rather
177
+ than an explicit inverse.
178
+ - **Kernel hyperparameters** (amplitude, length-scale) fitted by maximizing the
179
+ log marginal likelihood with L-BFGS and random restarts.
180
+ - **Acquisition** (EI / UCB / PI) optimized over the normalized `[0,1]ᵈ` space
181
+ via a quasi-random candidate set refined with L-BFGS.
182
+
183
+ The cost center — repeated Cholesky factorizations and acquisition
184
+ optimization — is exactly why the core is in C++.
185
+
186
+ ## License
187
+
188
+ MIT — see [LICENSE](LICENSE).