Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,28 @@ concurrency:
cancel-in-progress: true

jobs:
type-check:
timeout-minutes: 10
if: "! contains(github.event.head_commit.message, '[skip ci]')"
name: Type check
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- name: Set up Python 3.10
uses: actions/setup-python@v6
with:
python-version: '3.10'
cache: 'pip'

- name: Install tox
run: python3 -m pip install tox

- name: Run ty
run: tox -e type
working-directory: python

run-tests:
timeout-minutes: 15
if: "! contains(github.event.head_commit.message, '[skip ci]')"
Expand Down Expand Up @@ -78,7 +100,7 @@ jobs:

build_sdist:
timeout-minutes: 10
needs: run-tests
needs: [run-tests, type-check]
if: "! contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ${{ matrix.os }}
strategy:
Expand Down
10 changes: 9 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
ci:
skip: [roxygenize] # Produces renv errors.
# roxygenize produces renv errors. ty needs network access while running,
# which is unavailable in pre-commit.ci; it runs in GitHub Actions instead.
skip: [roxygenize, ty]
autofix_prs: true
autofix_commit_msg: |
[pre-commit.ci] auto fixes from pre-commit.com hooks
Expand Down Expand Up @@ -51,6 +53,12 @@ repos:
types_or: [ python, pyi, jupyter ]
require_serial: true

- repo: https://github.com/astral-sh/ty-pre-commit
rev: v0.0.89
hooks:
- id: ty
args: [--project=python, --isolated]

- repo: https://github.com/sphinx-contrib/sphinx-lint
rev: v1.0.2
hooks:
Expand Down
2 changes: 2 additions & 0 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ collapse_tables = [ "project.authors" ]

[tool.ty.rules]
invalid-assignment = "ignore"
[tool.ty.src]
include = [ "src" ]

[tool.pytest.ini_options]
faulthandler_timeout = 10
Expand Down
6 changes: 4 additions & 2 deletions python/src/moocore/_docsubstitute.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from typing import Any
from typing import Any, TypeVar
from collections.abc import Callable

from string import Template
import inspect

_CallableT = TypeVar("_CallableT", bound=Callable[..., Any])

COMMON_PARAMS = {
"points": """2D array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.""",
Expand Down Expand Up @@ -32,7 +34,7 @@ class DocSubstitute:
def __init__(self) -> None:
self.params = COMMON_PARAMS

def __call__(self, func: Callable[..., Any]) -> Callable[..., Any]:
def __call__(self, func: _CallableT) -> _CallableT:
if func.__doc__:
try:
func.__doc__ = Template(
Expand Down
26 changes: 16 additions & 10 deletions python/src/moocore/_generate.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import cast

import numpy as np

# FIXME: Implement also WFG hard type described here:
Expand Down Expand Up @@ -172,15 +174,17 @@ def generate_ndset(
[0.16824287, 0.4448603 , 0.35613488, 0.17723839, 0.5565858 ]])
"""
if seed is None or is_integer_value(seed):
seed = np.random.default_rng(seed)
rng = np.random.default_rng(seed)
else:
rng = cast(np.random.Generator, seed)

def _sample_simplex(n: int, d: int) -> np.ndarray:
x = seed.exponential(size=(n, d))
x = rng.exponential(size=(n, d))
x /= x.sum(axis=1, keepdims=True)
return x

def _sample_sphere(n: int, d: int) -> np.ndarray:
x = np.abs(seed.normal(size=(n, d)))
x = np.abs(rng.normal(size=(n, d)))
x /= np.linalg.norm(x, axis=1, keepdims=True)
return x

Expand All @@ -190,7 +194,7 @@ def _sample_convex_sphere(n: int, d: int) -> np.ndarray:
def _sample_cliff_concave(n: int, d: int) -> np.ndarray:
x = np.empty((n, d))
x[:, :2] = _sample_sphere(n, 2)
x[:, 2:] = seed.uniform(0, 1, size=(n, d - 2))
x[:, 2:] = rng.uniform(0, 1, size=(n, d - 2))
return x

def _sample_cliff_convex(n: int, d: int) -> np.ndarray:
Expand Down Expand Up @@ -563,23 +567,25 @@ def generate_sequence(

"""
if seed is None or is_integer_value(seed):
seed = np.random.default_rng(seed)
rng = np.random.default_rng(seed)
else:
rng = cast(np.random.Generator, seed)

match method:
case "cube":
sample = _generate_within_hypercube(n, d, seed)
sample = _generate_within_hypercube(n, d, rng)
case "sphere":
sample = _generate_within_hypersphere(n, d, seed, r_min=r_min)
sample = _generate_within_hypersphere(n, d, rng, r_min=r_min)
case "each-dominates-previous":
sample = _generate_total_dominance_chain(
n, d, rng=seed, dominates_previous=True
n, d, rng=rng, dominates_previous=True
)
case "each-dominates-next":
sample = _generate_total_dominance_chain(
n, d, rng=seed, dominates_previous=False
n, d, rng=rng, dominates_previous=False
)
case "glas2017":
sample = _generate_glas2017_sequence(n, d, seed, c_value=c_value)
sample = _generate_glas2017_sequence(n, d, rng, c_value=c_value)
case _:
raise ValueError(f"unknown method={method}")

Expand Down
Loading
Loading