Skip to content

Commit 509ee9c

Browse files
MNT add py39 support (#196)
1 parent fac6872 commit 509ee9c

File tree

8 files changed

+9679
-5766
lines changed

8 files changed

+9679
-5766
lines changed

.github/workflows/asv.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
run: |
2828
git branch main origin/main
2929
30-
- uses: prefix-dev/[email protected].0
30+
- uses: prefix-dev/[email protected].3
3131
with:
3232
environments: dev
3333
cache: true
@@ -93,7 +93,7 @@ jobs:
9393
cp -r "$d"/* "asv_benchmarks/results/"
9494
done
9595
96-
- uses: prefix-dev/[email protected].0
96+
- uses: prefix-dev/[email protected].3
9797
with:
9898
environments: dev
9999
cache: true

.github/workflows/static.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99

1010
steps:
1111
- uses: actions/checkout@v5
12-
- uses: prefix-dev/[email protected].0
12+
- uses: prefix-dev/[email protected].3
1313
with:
1414
environments: static
1515
cache: true

.github/workflows/test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,26 @@ jobs:
1616

1717
steps:
1818
- uses: actions/checkout@v5
19-
- uses: prefix-dev/[email protected].0
19+
- uses: prefix-dev/[email protected].3
2020
with:
2121
environments: >-
2222
dev
2323
docs
2424
nogil
25+
py39
2526
cache: true
2627

2728
- name: Re-install local
2829
run: |
2930
pixi reinstall -e dev --frozen fastcan
3031
pixi reinstall -e docs --frozen fastcan
3132
pixi reinstall -e nogil --frozen fastcan
33+
pixi reinstall -e py39 --frozen fastcan
3234
3335
- name: Test with pytest
3436
run: |
3537
pixi run -e dev test
38+
pixi run -e py39 test
3639
- name: Test with doctest
3740
if: matrix.os == 'ubuntu-latest'
3841
run: |

.github/workflows/wheel.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
runs-on: ubuntu-latest
99
steps:
1010
- uses: actions/checkout@v5
11-
- uses: prefix-dev/[email protected].0
11+
- uses: prefix-dev/[email protected].3
1212
with:
1313
environments: dev
1414
cache: true
@@ -36,7 +36,7 @@ jobs:
3636
uses: pypa/[email protected]
3737
env:
3838
CIBW_SKIP: "*_i686 *_ppc64le *_s390x *_universal2 *-musllinux_* cp314t*"
39-
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.10"
39+
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9"
4040
CIBW_ARCHS_LINUX: auto
4141
CIBW_ARCHS_MACOS: x86_64 arm64
4242
CIBW_ARCHS_WINDOWS: AMD64

fastcan/_beam.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def _beam_search(
1313
X, V, n_features_to_select, beam_width, indices_include, mask_exclude, tol, verbose
1414
):
1515
"""
16-
Perform beam search to find the best subset of features.
16+
Beam search with SSC.
1717
1818
Parameters:
1919
X : np.ndarray
@@ -48,12 +48,16 @@ def _beam_search(
4848
X_support, X_selected = _prepare_candidates(
4949
X, mask_exclude, indices_include
5050
)
51+
if X_selected.shape[1] == 0:
52+
beams_scores = np.sum((X.T @ V) ** 2, axis=1)
53+
beams_scores[~X_support] = 0
54+
else:
55+
W_selected = orth(X_selected)
56+
selected_score = np.sum((W_selected.T @ V) ** 2)
57+
beams_scores = _gram_schmidt(
58+
X, X_support, X_selected, selected_score, V, tol
59+
)
5160
beams_selected_ids = [indices_include for _ in range(beam_width)]
52-
W_selected = orth(X_selected)
53-
selected_score = np.sum((W_selected.T @ V) ** 2)
54-
beams_scores = _gram_schmidt(
55-
X, X_support, X_selected, selected_score, V, tol
56-
)
5761
beams_selected_ids, top_k_scores = _select_top_k(
5862
beams_scores[None, :],
5963
beams_selected_ids,
@@ -123,11 +127,9 @@ def _select_top_k(
123127
return new_ids_selected, top_k_scores
124128

125129

126-
def _gram_schmidt(X, X_support, X_selected, selected_score, V, tol, modified=True):
130+
def _gram_schmidt(X, X_support, X_selected, selected_score, V, tol):
127131
X = np.copy(X)
128-
if modified:
129-
# Change to Modified Gram-Schmidt
130-
W_selected = orth(X_selected)
132+
W_selected = orth(X_selected) # Change to Modified Gram-Schmidt
131133
scores = np.zeros(X.shape[1])
132134
for i, support in enumerate(X_support):
133135
if not support:

pixi.lock

Lines changed: 9634 additions & 5741 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pixi.toml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ channels = ["conda-forge"]
33
platforms = ["win-64", "linux-64", "osx-64", "osx-arm64", "linux-aarch64"]
44

55
[dependencies]
6-
python = ">=3.10"
7-
scikit-learn = ">=1.7.0,!=1.7.1"
8-
cython = ">=3.1.0" # build dependencies
9-
meson-python = ">=0.18.0" # build dependencies
6+
python = ">=3.9"
7+
scikit-learn = ">=1.6.0"
8+
cython = ">=3.0.10" # build dependencies
9+
meson-python = ">=0.16.0" # build dependencies
1010

1111
[target.osx-64.dependencies]
1212
compilers = "*" # build dependencies
@@ -74,12 +74,13 @@ python-build = "*"
7474
pip = "*"
7575

7676
[feature.nogil.dependencies]
77+
python = "<3.14"
7778
python-freethreading = "*"
7879
cython = ">=3.1.0" # build dependencies
7980
meson-python = ">=0.18.0" # build dependencies
8081

8182
[feature.nogil.pypi-dependencies]
82-
scikit-learn = ">=1.7.0,!=1.7.1"
83+
scikit-learn = ">=1.6.0"
8384
fastcan = { path = ".", editable = true }
8485

8586
[tasks]
@@ -138,9 +139,16 @@ pyodide-build-recipe = { cmd = "rm -rf dist && bash -c 'source emsdk/emsdk_env.s
138139
pyodide-download = '''bash -c "[ -d pyodide ] || (LATEST_TAG=$(curl -s https://api.github.com/repos/pyodide/pyodide/releases/latest | grep \"tag_name\" | cut -d \" -f4) && curl -L https://github.com/pyodide/pyodide/releases/download/${LATEST_TAG}/pyodide-${LATEST_TAG}.tar.bz2 | tar -xjf -)"'''
139140
pyodide-test-recipe = { cmd = "mv ../dist/* . && python -m http.server --directory .", cwd = "pyodide", depends-on = ["pyodide-download", "pyodide-build-recipe"] }
140141

142+
[feature.py39.dependencies]
143+
python = "==3.9.0"
144+
scikit-learn = "==1.6.0"
145+
meson-python = "==0.16.0"
146+
cython = "==3.0.10"
147+
141148
[environments]
142149
dev = ["test", "build", "jupyter", "asv"]
143150
docs = ["docs"]
144151
static = { features = ["static"], no-default-feature = true }
145152
nogil = { features = ["nogil"], no-default-feature = true }
146-
wasm = { features = ["wasm"], no-default-feature = true }
153+
wasm = { features = ["wasm"], no-default-feature = true }
154+
py39 = { features = ["py39", "test"] }

pyproject.toml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ description = "A fast canonical-correlation-based greedy search algorithm"
55
authors = [
66
{ name = "Matthew Sikai Zhang", email = "[email protected]" },
77
]
8-
requires-python = ">=3.10"
8+
requires-python = ">=3.9"
99
readme = "README.rst"
1010
license = { file = "LICENSE" }
1111

12-
dependencies = ["scikit-learn>=1.7.0,!=1.7.1"]
12+
dependencies = ["scikit-learn>=1.6.0"]
1313

1414
classifiers = [
1515
"Development Status :: 4 - Beta",
@@ -19,6 +19,7 @@ classifiers = [
1919
"Operating System :: Unix",
2020
"Operating System :: MacOS",
2121
"Programming Language :: Python :: 3",
22+
"Programming Language :: Python :: 3.9",
2223
"Programming Language :: Python :: 3.10",
2324
"Programming Language :: Python :: 3.11",
2425
"Programming Language :: Python :: 3.12",
@@ -33,7 +34,13 @@ download = "https://pypi.org/project/fastcan/#files"
3334
tracker = "https://github.com/scikit-learn-contrib/fastcan/issues"
3435

3536
[build-system]
36-
requires = ["meson-python>=0.18.0", "Cython>=3.1.0", "scikit-learn>=1.7.0"]
37+
requires = [
38+
"scikit-learn>=1.6.0",
39+
"meson-python>=0.18.0; python_version > '3.9'",
40+
"Cython>=3.1.0; python_version > '3.9'",
41+
"meson-python==0.16.0; python_version == '3.9'",
42+
"Cython==3.0.10; python_version == '3.9'",
43+
]
3744
build-backend = "mesonpy"
3845

3946
# Needed on Windows CI to compile with Visual Studio compiler

0 commit comments

Comments
 (0)