Thanks to visit codestin.com
Credit goes to github.com

Skip to content

BUG: cluster.hierarchy.fcluster: reject t < 1 for maxclust criteria - #26100

Open
HuzaifaChaudary wants to merge 1 commit into
scipy:mainfrom
HuzaifaChaudary:fix/fcluster-maxclust-t-below-one
Open

BUG: cluster.hierarchy.fcluster: reject t < 1 for maxclust criteria#26100
HuzaifaChaudary wants to merge 1 commit into
scipy:mainfrom
HuzaifaChaudary:fix/fcluster-maxclust-t-below-one

Conversation

@HuzaifaChaudary

Copy link
Copy Markdown

Reference issue

Closes gh-21206.

What does this implement/fix?

fcluster with criterion="maxclust" and t=0 gives a different answer depending on what
is in memory , instead of complaining .

cluster_maxclust_monocrit ends with MC[upper_idx] , but MC only holds n-1 values ,
so the last legal index is n-2 . upper_idx starts at n-1 and only comes down when a
threshold gives few enough clusters . testing i = n-2 always puts the whole tree into one
cluster , so that test only fails when max_nc < 1 . in that one case upper_idx is never
lowered and MC[n-1] is read one past the end of the array .

_hierarchy.pyx is compiled with boundscheck=False , so nothing catches it and the cutoff
is whatever happens to sit in that memory . with t=0 on six points the result is six
singleton clusters . passing an MC one slot longer with a known value in slot n-1 changes
the answer , which is what showed where it was reading from .

no t can ever produce fewer than one cluster , so the input is rejected instead . that
removes the only path that reaches the read rather than hiding it . t >= 1 is unchanged ,
and distance and inconsistent still take t=0 .

Additional information

t=0.5 is rejected too , it truncated to zero and reached the same line . t=1.5 still
works .

six new cases cover maxclust and maxclust_monocrit for t of 0 , -1 and 0.5 . they fail
on main with "DID NOT RAISE ValueError" . pytest scipy/cluster/ gives 225 passed , 6
skipped .

AI Generation Disclosure

i used claude code ( claude opus 5 ) to help look into the cause and to draft the patch and
the test . i went over the change myself , confirmed the out of bounds read , and ran the
tests locally .

cluster_maxclust_monocrit ends with MC[upper_idx], where MC has n-1 entries and
upper_idx starts at n-1. upper_idx only moves down when some threshold gives
nc <= max_nc, and testing i = n-2 always puts the whole tree in one cluster, so
that test only fails when max_nc < 1. in that one case upper_idx is never lowered
and MC[n-1] is read one past the end of the array.

the file is compiled with boundscheck=False, so nothing catches it and the cutoff
is whatever happens to sit in that memory. with t=0 on six points the result is
six singleton clusters, and feeding a longer MC with a known value in slot n-1
changes the answer, which is what showed where it was reading from.

no t can produce fewer than one cluster, so the input is rejected instead. this
removes the only path that reaches the read. t >= 1 is unchanged, and distance
and inconsistent still take t=0.
Copilot AI lite review requested due to automatic review settings September 4, 2026 22:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added scipy.cluster defect A clear bug or issue that prevents SciPy from being installed or used as expected labels Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

defect A clear bug or issue that prevents SciPy from being installed or used as expected scipy.cluster

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: cluster.hierarchy.fcluster: criterion="maxclust" with t=0 behaves inconsistently

2 participants