orivex 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 (46) hide show
  1. orivex-0.1.0/LICENSE.txt +21 -0
  2. orivex-0.1.0/PKG-INFO +152 -0
  3. orivex-0.1.0/README.md +89 -0
  4. orivex-0.1.0/pyproject.toml +118 -0
  5. orivex-0.1.0/setup.cfg +4 -0
  6. orivex-0.1.0/src/orivex/__init__.py +49 -0
  7. orivex-0.1.0/src/orivex/api.py +75 -0
  8. orivex-0.1.0/src/orivex/capabilities.py +42 -0
  9. orivex-0.1.0/src/orivex/engine.py +192 -0
  10. orivex-0.1.0/src/orivex/features/__init__.py +1 -0
  11. orivex-0.1.0/src/orivex/features/distribution.py +212 -0
  12. orivex-0.1.0/src/orivex/features/fitness_distance.py +244 -0
  13. orivex-0.1.0/src/orivex/features/information_content.py +442 -0
  14. orivex-0.1.0/src/orivex/features/meta_model.py +375 -0
  15. orivex-0.1.0/src/orivex/features/nearest_better.py +290 -0
  16. orivex-0.1.0/src/orivex/normalization.py +41 -0
  17. orivex-0.1.0/src/orivex/options.py +41 -0
  18. orivex-0.1.0/src/orivex/planner.py +89 -0
  19. orivex-0.1.0/src/orivex/py.typed +0 -0
  20. orivex-0.1.0/src/orivex/registry.py +57 -0
  21. orivex-0.1.0/src/orivex/result.py +96 -0
  22. orivex-0.1.0/src/orivex/sample.py +133 -0
  23. orivex-0.1.0/src/orivex/specs.py +144 -0
  24. orivex-0.1.0/src/orivex/torch/__init__.py +19 -0
  25. orivex-0.1.0/src/orivex/torch/api.py +120 -0
  26. orivex-0.1.0/src/orivex/torch/engine.py +162 -0
  27. orivex-0.1.0/src/orivex/torch/features/__init__.py +1 -0
  28. orivex-0.1.0/src/orivex/torch/features/distribution.py +148 -0
  29. orivex-0.1.0/src/orivex/torch/features/fitness_distance.py +129 -0
  30. orivex-0.1.0/src/orivex/torch/features/meta_model.py +287 -0
  31. orivex-0.1.0/src/orivex/torch/normalization.py +28 -0
  32. orivex-0.1.0/src/orivex/torch/sample.py +155 -0
  33. orivex-0.1.0/src/orivex.egg-info/PKG-INFO +152 -0
  34. orivex-0.1.0/src/orivex.egg-info/SOURCES.txt +44 -0
  35. orivex-0.1.0/src/orivex.egg-info/dependency_links.txt +1 -0
  36. orivex-0.1.0/src/orivex.egg-info/requires.txt +37 -0
  37. orivex-0.1.0/src/orivex.egg-info/top_level.txt +1 -0
  38. orivex-0.1.0/tests/test_bbob_correctness.py +279 -0
  39. orivex-0.1.0/tests/test_capabilities.py +43 -0
  40. orivex-0.1.0/tests/test_engine_isolation.py +141 -0
  41. orivex-0.1.0/tests/test_normalization.py +114 -0
  42. orivex-0.1.0/tests/test_options.py +69 -0
  43. orivex-0.1.0/tests/test_registry_planner.py +89 -0
  44. orivex-0.1.0/tests/test_result.py +49 -0
  45. orivex-0.1.0/tests/test_sample.py +77 -0
  46. orivex-0.1.0/tests/test_specs.py +94 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026, The orivex authors
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.
orivex-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.4
2
+ Name: orivex
3
+ Version: 0.1.0
4
+ Summary: A selective and fast exploratory landscape analysis engine.
5
+ Author-email: Wojciech Achtelik <wachtelik@gmail.com>
6
+ Maintainer-email: Wojciech Achtelik <wachtelik@gmail.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://helix-agh.github.io/orivex/
9
+ Project-URL: Documentation, https://helix-agh.github.io/orivex/
10
+ Project-URL: Repository, https://github.com/helix-agh/orivex
11
+ Project-URL: Issues, https://github.com/helix-agh/orivex/issues
12
+ Keywords: exploratory landscape analysis,ela,black-box optimization,benchmarking,bbob,feature extraction,numpy,pytorch
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Scientific/Engineering
25
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.10
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE.txt
30
+ Requires-Dist: numpy>=1.26
31
+ Requires-Dist: scipy>=1.11
32
+ Provides-Extra: docs
33
+ Requires-Dist: mkdocs<2,>=1.6.1; extra == "docs"
34
+ Requires-Dist: mkdocs-material<10,>=9.7; extra == "docs"
35
+ Requires-Dist: mkdocs-gen-files<0.6,>=0.5; extra == "docs"
36
+ Requires-Dist: mkdocstrings[python]<2,>=1.0; extra == "docs"
37
+ Requires-Dist: pymdown-extensions<11,>=10.15; extra == "docs"
38
+ Requires-Dist: ruff>=0.16.3; extra == "docs"
39
+ Provides-Extra: torch
40
+ Requires-Dist: torch>=2.3; extra == "torch"
41
+ Provides-Extra: test
42
+ Requires-Dist: hypothesis>=6.100; extra == "test"
43
+ Requires-Dist: pytest>=8; extra == "test"
44
+ Requires-Dist: pytest-cov>=5; extra == "test"
45
+ Provides-Extra: benchmark
46
+ Requires-Dist: ioh<0.4,>=0.3.14; extra == "benchmark"
47
+ Requires-Dist: matplotlib>=3.8; extra == "benchmark"
48
+ Requires-Dist: numdifftools>=0.9.41; extra == "benchmark"
49
+ Requires-Dist: pandas>=2.2; extra == "benchmark"
50
+ Requires-Dist: pyDOE<0.4,>=0.3.8; extra == "benchmark"
51
+ Requires-Dist: SALib<1.5,>=1.4.5; extra == "benchmark"
52
+ Requires-Dist: scikit-learn>=1.5; extra == "benchmark"
53
+ Requires-Dist: threadpoolctl>=3.6; extra == "benchmark"
54
+ Provides-Extra: dev
55
+ Requires-Dist: hypothesis>=6.100; extra == "dev"
56
+ Requires-Dist: pre-commit>=4.5; extra == "dev"
57
+ Requires-Dist: pytest>=8; extra == "dev"
58
+ Requires-Dist: pytest-cov>=5; extra == "dev"
59
+ Requires-Dist: ruff>=0.16.3; extra == "dev"
60
+ Requires-Dist: torch>=2.3; extra == "dev"
61
+ Requires-Dist: ty>=0.0.74; extra == "dev"
62
+ Dynamic: license-file
63
+
64
+ <p align="center">
65
+ <picture>
66
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/helix-agh/orivex/main/assets/orivex-lockup-dark.png">
67
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/helix-agh/orivex/main/assets/orivex-lockup-light.png">
68
+ <img alt="orivex" src="https://raw.githubusercontent.com/helix-agh/orivex/main/assets/orivex-lockup-light.png" width="440">
69
+ </picture>
70
+ </p>
71
+
72
+ <p align="center">
73
+ <strong>A selective and fast engine for exploratory landscape analysis.</strong>
74
+ </p>
75
+
76
+ <p align="center">
77
+ <a href="https://www.python.org/downloads/"><img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10+-blue.svg"></a>
78
+ <img alt="Status: pre-release" src="https://img.shields.io/badge/status-pre--release-orange.svg">
79
+ <img alt="Backends: NumPy and PyTorch" src="https://img.shields.io/badge/backends-NumPy%20%7C%20PyTorch-informational.svg">
80
+ </p>
81
+
82
+ <p align="center">
83
+ <a href="https://helix-agh.github.io/orivex/">Documentation</a> ·
84
+ <a href="https://helix-agh.github.io/orivex/getting-started/quickstart/">Quick start</a> ·
85
+ <a href="https://helix-agh.github.io/orivex/api/">API reference</a> ·
86
+ <a href="https://helix-agh.github.io/orivex/development/contributing/">Contributing</a>
87
+ </p>
88
+
89
+ **orivex** is a successor to [`pflacco`](https://github.com/Reiyan/pflacco)
90
+ for exploratory landscape analysis (ELA). Compute individually selected features from sampled
91
+ points and objective values, with shared intermediates, explicit costs, and versioned definitions.
92
+ A NumPy/SciPy core is complemented by an optional differentiable PyTorch backend.
93
+
94
+ ## Installation
95
+
96
+ Python 3.10 or newer is required. Install from PyPI:
97
+
98
+ ```bash
99
+ pip install orivex
100
+ ```
101
+
102
+ Add the optional differentiable PyTorch backend with `pip install "orivex[torch]"`.
103
+
104
+ To work from a checkout instead:
105
+
106
+ ```bash
107
+ git clone https://github.com/helix-agh/orivex.git
108
+ cd orivex
109
+ uv sync
110
+ ```
111
+
112
+ With pip, run `python -m pip install -e .` (add `".[torch]"` for the PyTorch backend).
113
+
114
+ ## Quick start
115
+
116
+ ```python
117
+ import numpy as np
118
+
119
+ from orivex import LandscapeSample, compute
120
+
121
+ rng = np.random.default_rng(42)
122
+ x = rng.uniform(-5.0, 5.0, size=(200, 2))
123
+ y = np.sum(x**2, axis=1)
124
+ sample = LandscapeSample(x, y, lower=[-5.0, -5.0], upper=[5.0, 5.0])
125
+
126
+ result = compute(sample, ["ela_distr.skewness", "nbc.nn_nb.mean_ratio"])
127
+ for name, item in result.values.items():
128
+ print(name, item.value, item.status.value)
129
+ ```
130
+
131
+ Objective values are min-max normalized by default. Pass `y_normalization=None` to use raw
132
+ canonical objectives. Undefined features return an `invalid` status with an explanation.
133
+
134
+ ## Documentation
135
+
136
+ Read the **[documentation](https://helix-agh.github.io/orivex/)** for installation, feature
137
+ selection, normalization, fitness-distance conventions, PyTorch support, and API reference.
138
+ The [feature overview](https://helix-agh.github.io/orivex/features/), [contributing guide](https://helix-agh.github.io/orivex/development/contributing/),
139
+ and [benchmark guide](https://helix-agh.github.io/orivex/development/benchmarks/) are also available.
140
+
141
+ Preview the documentation locally:
142
+
143
+ ```bash
144
+ uv sync --extra docs
145
+ uv run --no-sync mkdocs serve
146
+ ```
147
+
148
+ See [documentation development](https://helix-agh.github.io/orivex/development/documentation/) for strict builds and deployment.
149
+
150
+ ## License
151
+
152
+ orivex is licensed under the [MIT License](https://github.com/helix-agh/orivex/blob/main/LICENSE.txt).
orivex-0.1.0/README.md ADDED
@@ -0,0 +1,89 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/helix-agh/orivex/main/assets/orivex-lockup-dark.png">
4
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/helix-agh/orivex/main/assets/orivex-lockup-light.png">
5
+ <img alt="orivex" src="https://raw.githubusercontent.com/helix-agh/orivex/main/assets/orivex-lockup-light.png" width="440">
6
+ </picture>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <strong>A selective and fast engine for exploratory landscape analysis.</strong>
11
+ </p>
12
+
13
+ <p align="center">
14
+ <a href="https://www.python.org/downloads/"><img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10+-blue.svg"></a>
15
+ <img alt="Status: pre-release" src="https://img.shields.io/badge/status-pre--release-orange.svg">
16
+ <img alt="Backends: NumPy and PyTorch" src="https://img.shields.io/badge/backends-NumPy%20%7C%20PyTorch-informational.svg">
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://helix-agh.github.io/orivex/">Documentation</a> ·
21
+ <a href="https://helix-agh.github.io/orivex/getting-started/quickstart/">Quick start</a> ·
22
+ <a href="https://helix-agh.github.io/orivex/api/">API reference</a> ·
23
+ <a href="https://helix-agh.github.io/orivex/development/contributing/">Contributing</a>
24
+ </p>
25
+
26
+ **orivex** is a successor to [`pflacco`](https://github.com/Reiyan/pflacco)
27
+ for exploratory landscape analysis (ELA). Compute individually selected features from sampled
28
+ points and objective values, with shared intermediates, explicit costs, and versioned definitions.
29
+ A NumPy/SciPy core is complemented by an optional differentiable PyTorch backend.
30
+
31
+ ## Installation
32
+
33
+ Python 3.10 or newer is required. Install from PyPI:
34
+
35
+ ```bash
36
+ pip install orivex
37
+ ```
38
+
39
+ Add the optional differentiable PyTorch backend with `pip install "orivex[torch]"`.
40
+
41
+ To work from a checkout instead:
42
+
43
+ ```bash
44
+ git clone https://github.com/helix-agh/orivex.git
45
+ cd orivex
46
+ uv sync
47
+ ```
48
+
49
+ With pip, run `python -m pip install -e .` (add `".[torch]"` for the PyTorch backend).
50
+
51
+ ## Quick start
52
+
53
+ ```python
54
+ import numpy as np
55
+
56
+ from orivex import LandscapeSample, compute
57
+
58
+ rng = np.random.default_rng(42)
59
+ x = rng.uniform(-5.0, 5.0, size=(200, 2))
60
+ y = np.sum(x**2, axis=1)
61
+ sample = LandscapeSample(x, y, lower=[-5.0, -5.0], upper=[5.0, 5.0])
62
+
63
+ result = compute(sample, ["ela_distr.skewness", "nbc.nn_nb.mean_ratio"])
64
+ for name, item in result.values.items():
65
+ print(name, item.value, item.status.value)
66
+ ```
67
+
68
+ Objective values are min-max normalized by default. Pass `y_normalization=None` to use raw
69
+ canonical objectives. Undefined features return an `invalid` status with an explanation.
70
+
71
+ ## Documentation
72
+
73
+ Read the **[documentation](https://helix-agh.github.io/orivex/)** for installation, feature
74
+ selection, normalization, fitness-distance conventions, PyTorch support, and API reference.
75
+ The [feature overview](https://helix-agh.github.io/orivex/features/), [contributing guide](https://helix-agh.github.io/orivex/development/contributing/),
76
+ and [benchmark guide](https://helix-agh.github.io/orivex/development/benchmarks/) are also available.
77
+
78
+ Preview the documentation locally:
79
+
80
+ ```bash
81
+ uv sync --extra docs
82
+ uv run --no-sync mkdocs serve
83
+ ```
84
+
85
+ See [documentation development](https://helix-agh.github.io/orivex/development/documentation/) for strict builds and deployment.
86
+
87
+ ## License
88
+
89
+ orivex is licensed under the [MIT License](https://github.com/helix-agh/orivex/blob/main/LICENSE.txt).
@@ -0,0 +1,118 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "orivex"
7
+ version = "0.1.0"
8
+ description = "A selective and fast exploratory landscape analysis engine."
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.10"
12
+ authors = [{name = "Wojciech Achtelik", email = "wachtelik@gmail.com"}]
13
+ maintainers = [{name = "Wojciech Achtelik", email = "wachtelik@gmail.com"}]
14
+ keywords = [
15
+ "exploratory landscape analysis",
16
+ "ela",
17
+ "black-box optimization",
18
+ "benchmarking",
19
+ "bbob",
20
+ "feature extraction",
21
+ "numpy",
22
+ "pytorch",
23
+ ]
24
+ classifiers = [
25
+ "Development Status :: 4 - Beta",
26
+ "Intended Audience :: Science/Research",
27
+ "Intended Audience :: Developers",
28
+ "License :: OSI Approved :: MIT License",
29
+ "Operating System :: OS Independent",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3.10",
32
+ "Programming Language :: Python :: 3.11",
33
+ "Programming Language :: Python :: 3.12",
34
+ "Programming Language :: Python :: 3.13",
35
+ "Programming Language :: Python :: 3.14",
36
+ "Topic :: Scientific/Engineering",
37
+ "Topic :: Scientific/Engineering :: Mathematics",
38
+ "Typing :: Typed",
39
+ ]
40
+ dependencies = [
41
+ "numpy>=1.26",
42
+ "scipy>=1.11",
43
+ ]
44
+
45
+ [project.optional-dependencies]
46
+ docs = [
47
+ "mkdocs>=1.6.1,<2",
48
+ "mkdocs-material>=9.7,<10",
49
+ "mkdocs-gen-files>=0.5,<0.6",
50
+ "mkdocstrings[python]>=1.0,<2",
51
+ "pymdown-extensions>=10.15,<11",
52
+ "ruff>=0.16.3",
53
+ ]
54
+ torch = [
55
+ "torch>=2.3",
56
+ ]
57
+ test = [
58
+ "hypothesis>=6.100",
59
+ "pytest>=8",
60
+ "pytest-cov>=5",
61
+ ]
62
+ benchmark = [
63
+ "ioh>=0.3.14,<0.4",
64
+ "matplotlib>=3.8",
65
+ "numdifftools>=0.9.41",
66
+ "pandas>=2.2",
67
+ "pyDOE>=0.3.8,<0.4",
68
+ "SALib>=1.4.5,<1.5",
69
+ "scikit-learn>=1.5",
70
+ "threadpoolctl>=3.6",
71
+ ]
72
+ dev = [
73
+ "hypothesis>=6.100",
74
+ "pre-commit>=4.5",
75
+ "pytest>=8",
76
+ "pytest-cov>=5",
77
+ "ruff>=0.16.3",
78
+ "torch>=2.3",
79
+ "ty>=0.0.74",
80
+ ]
81
+
82
+ [project.urls]
83
+ Homepage = "https://helix-agh.github.io/orivex/"
84
+ Documentation = "https://helix-agh.github.io/orivex/"
85
+ Repository = "https://github.com/helix-agh/orivex"
86
+ Issues = "https://github.com/helix-agh/orivex/issues"
87
+
88
+ [tool.setuptools.packages.find]
89
+ where = ["src"]
90
+
91
+ [tool.setuptools.package-data]
92
+ orivex = ["py.typed"]
93
+
94
+ [tool.pytest.ini_options]
95
+ addopts = "-ra --strict-config --strict-markers"
96
+ pythonpath = ["src", "tests", "benchmarks"]
97
+ testpaths = ["tests"]
98
+
99
+ [tool.ruff]
100
+ line-length = 100
101
+ target-version = "py310"
102
+
103
+ [tool.ruff.lint]
104
+ select = ["E", "W", "F", "I", "B", "C4", "UP", "ARG", "SIM", "PTH", "RUF"]
105
+
106
+ [tool.ruff.lint.isort]
107
+ known-first-party = ["orivex"]
108
+
109
+ [tool.ruff.lint.per-file-ignores]
110
+ "tests/**" = ["ARG"]
111
+ "tests/torch/**" = ["E402"]
112
+
113
+ [tool.ty.environment]
114
+ python-version = "3.10"
115
+ root = ["./src"]
116
+
117
+ [tool.ty.src]
118
+ include = ["src"]
orivex-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,49 @@
1
+ """Better FLACCO: selective and verified exploratory landscape analysis."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ from orivex.api import compute, list_features
6
+ from orivex.capabilities import AutogradSupport, FeatureCapability
7
+ from orivex.normalization import YNormalization
8
+ from orivex.result import BackendName, DeviceType, FloatingDType
9
+ from orivex.sample import LandscapeSample, ObjectiveSense, ObjectiveSenseName
10
+ from orivex.specs import (
11
+ CostModel,
12
+ CostTier,
13
+ FeatureSpec,
14
+ InputRequirement,
15
+ InvarianceBehavior,
16
+ InvarianceClaim,
17
+ MetricKind,
18
+ Reference,
19
+ Transformation,
20
+ )
21
+
22
+ try:
23
+ __version__ = version("orivex")
24
+ except PackageNotFoundError: # Running directly from a source checkout.
25
+ __version__ = "0.0.0"
26
+
27
+ __all__ = [
28
+ "AutogradSupport",
29
+ "BackendName",
30
+ "CostModel",
31
+ "CostTier",
32
+ "DeviceType",
33
+ "FeatureCapability",
34
+ "FeatureSpec",
35
+ "FloatingDType",
36
+ "InputRequirement",
37
+ "InvarianceBehavior",
38
+ "InvarianceClaim",
39
+ "LandscapeSample",
40
+ "MetricKind",
41
+ "ObjectiveSense",
42
+ "ObjectiveSenseName",
43
+ "Reference",
44
+ "Transformation",
45
+ "YNormalization",
46
+ "__version__",
47
+ "compute",
48
+ "list_features",
49
+ ]
@@ -0,0 +1,75 @@
1
+ """Public convenience API backed by the built-in feature engine."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy as np
6
+
7
+ from orivex.engine import Engine
8
+ from orivex.features.distribution import FEATURES as DISTRIBUTION_FEATURES
9
+ from orivex.features.distribution import INTERMEDIATES as DISTRIBUTION_INTERMEDIATES
10
+ from orivex.features.fitness_distance import FEATURES as FITNESS_DISTANCE_FEATURES
11
+ from orivex.features.fitness_distance import INTERMEDIATES as FITNESS_DISTANCE_INTERMEDIATES
12
+ from orivex.features.information_content import FEATURES as INFORMATION_CONTENT_FEATURES
13
+ from orivex.features.information_content import INTERMEDIATES as INFORMATION_CONTENT_INTERMEDIATES
14
+ from orivex.features.meta_model import FEATURES as META_MODEL_FEATURES
15
+ from orivex.features.meta_model import INTERMEDIATES as META_MODEL_INTERMEDIATES
16
+ from orivex.features.nearest_better import FEATURES as NEAREST_BETTER_FEATURES
17
+ from orivex.features.nearest_better import INTERMEDIATES as NEAREST_BETTER_INTERMEDIATES
18
+ from orivex.normalization import YNormalization
19
+ from orivex.options import FeatureOptions
20
+ from orivex.result import ComputationResult
21
+ from orivex.sample import LandscapeSample
22
+ from orivex.specs import FeatureSpec
23
+
24
+ DEFAULT_ENGINE = Engine(
25
+ DISTRIBUTION_FEATURES
26
+ + META_MODEL_FEATURES
27
+ + INFORMATION_CONTENT_FEATURES
28
+ + NEAREST_BETTER_FEATURES
29
+ + FITNESS_DISTANCE_FEATURES,
30
+ DISTRIBUTION_INTERMEDIATES
31
+ + META_MODEL_INTERMEDIATES
32
+ + INFORMATION_CONTENT_INTERMEDIATES
33
+ + NEAREST_BETTER_INTERMEDIATES
34
+ + FITNESS_DISTANCE_INTERMEDIATES,
35
+ )
36
+
37
+
38
+ def compute(
39
+ sample: LandscapeSample,
40
+ features: str | tuple[str, ...] | list[str],
41
+ *,
42
+ rng: np.random.Generator | None = None,
43
+ workers: int = 1,
44
+ y_normalization: YNormalization = "minmax",
45
+ options: FeatureOptions | None = None,
46
+ ) -> ComputationResult:
47
+ """Compute features from canonical objectives, min-max normalized by default.
48
+
49
+ ``y_normalization`` is ``"minmax"`` (observed range) or ``None`` (raw canonical
50
+ objectives). Normalized constant objectives map to zero. The original sample is
51
+ preserved; preprocessing is recorded
52
+ separately from mathematical feature definitions in result metadata.
53
+
54
+ ``options`` is a nested mapping keyed by feature group, for example
55
+ ``{"fitness_distance": {"proportion_of_best": 0.25}}``. Omit it to use defaults.
56
+ Unknown groups and option names are rejected. Fitness-distance features always use
57
+ Euclidean distances to the best selected observation. Effective options are recorded
58
+ in ``result.metadata.options`` as an immutable snapshot.
59
+
60
+ ``workers=1`` is the predictable default. Pass ``-1`` to let supporting kernels use all
61
+ available CPUs, or a positive integer to set an upper worker count. Kernels that do not
62
+ support parallel execution ignore this setting.
63
+ """
64
+ return DEFAULT_ENGINE.compute(
65
+ sample,
66
+ features,
67
+ rng=rng,
68
+ workers=workers,
69
+ y_normalization=y_normalization,
70
+ options=options,
71
+ )
72
+
73
+
74
+ def list_features() -> tuple[FeatureSpec, ...]:
75
+ return tuple(DEFAULT_ENGINE.registry.get(name) for name in DEFAULT_ENGINE.registry.names())
@@ -0,0 +1,42 @@
1
+ """Backend-specific feature implementation capabilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Literal, TypeAlias
7
+
8
+ from orivex.result import BackendName, DeviceType, FloatingDType
9
+
10
+ AutogradSupport: TypeAlias = Literal["smooth", "piecewise", "none"]
11
+
12
+
13
+ @dataclass(frozen=True, slots=True)
14
+ class FeatureCapability:
15
+ """Execution properties that belong to an implementation, not its mathematics."""
16
+
17
+ feature_name: str
18
+ backend: BackendName
19
+ autograd: AutogradSupport
20
+ devices: tuple[DeviceType, ...]
21
+ dtypes: tuple[FloatingDType, ...]
22
+ notes: tuple[str, ...] = ()
23
+
24
+ def __post_init__(self) -> None:
25
+ if not self.feature_name:
26
+ raise ValueError("feature name must not be empty")
27
+ if self.backend not in ("numpy", "torch"):
28
+ raise ValueError(f"unsupported backend: {self.backend!r}")
29
+ if self.autograd not in ("smooth", "piecewise", "none"):
30
+ raise ValueError(f"unsupported autograd support: {self.autograd!r}")
31
+ if not self.devices:
32
+ raise ValueError("at least one device type is required")
33
+ if not self.dtypes:
34
+ raise ValueError("at least one floating dtype is required")
35
+ if any(device not in ("cpu", "cuda", "mps") for device in self.devices):
36
+ raise ValueError(f"unsupported device types: {self.devices!r}")
37
+ if any(dtype not in ("float32", "float64") for dtype in self.dtypes):
38
+ raise ValueError(f"unsupported floating dtypes: {self.dtypes!r}")
39
+ if len(set(self.devices)) != len(self.devices):
40
+ raise ValueError("device types must be unique")
41
+ if len(set(self.dtypes)) != len(self.dtypes):
42
+ raise ValueError("floating dtypes must be unique")