Skip to content

ENH: Implement Kendall discordance - #110

Open
fbourgey wants to merge 3 commits into
scipy:mainfrom
fbourgey:kendall_dis
Open

ENH: Implement Kendall discordance#110
fbourgey wants to merge 3 commits into
scipy:mainfrom
fbourgey:kendall_dis

Conversation

@fbourgey

Copy link
Copy Markdown
Member

Reference issue

Toward #98

What does this implement/fix?

Implement Kendall discordance from _kendall_dis

Comment thread tests/xsf_tests/test_kendall_dis.cpp Outdated

@mdhaber mdhaber left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks like a faithful translation, and the tests are OK with my if they're ok with @steppi.

The tests are a little light, so I would suggest a few larger, non-trivial examples (probably randomly generated), and also checking behavior when there are tied elements. Maybe run kendalltau with randomly generated x and y (with and without the possibilities of ties in x, ties in y, and both) up until you get to dis = _kendall_dis(x, y) # discordant pairs to see what sort of input _kendall_dis can receive.

Thank you!

@steppi if we use this in SciPy, can it automatically be vectorized to work along the last axis?

@fbourgey

Copy link
Copy Markdown
Member Author

This looks like a faithful translation, and the tests are OK with my if they're ok with @steppi.

The tests are a little light, so I would suggest a few larger, non-trivial examples (probably randomly generated), and also checking behavior when there are tied elements. Maybe run kendalltau with randomly generated x and y (with and without the possibilities of ties in x, ties in y, and both) up until you get to dis = _kendall_dis(x, y) # discordant pairs to see what sort of input _kendall_dis can receive.

Thank you!

@steppi if we use this in SciPy, can it automatically be vectorized to work along the last axis?

Thanks @mdhaber, I'll improve the tests.

@fbourgey fbourgey changed the title ENH: Implement Kendall discordance kendall_dis ENH: Implement Kendall discordance Mar 19, 2026
@fbourgey

Copy link
Copy Markdown
Member Author

@mdhaber I have improved the tests with randomly-generated and tie/no-tie scenarios for x and y.

Can you detail exactly what you meant with

[...] up until you get to dis = _kendall_dis(x, y) # discordant pairs to see what sort of input _kendall_dis can receive.

@mdhaber

mdhaber commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

Can you detail exactly what you meant with...

It's probably not very important. I just couldn't remember exactly what could happen with the input to _kendall_dis - I think both x and y are ranks, but I couldn't remember whether there could be tied ranks within x, tied ranks within y, and tied ranks between the two. A little bit of thinking / reading code could help remind me, but the option I was suggesting was generating random input (with ties) to scipy.stats.kendalltau and seeing what data gets passed to _kendall_dis.

@fbourgey

fbourgey commented Apr 3, 2026

Copy link
Copy Markdown
Member Author

Can you detail exactly what you meant with...

It's probably not very important. I just couldn't remember exactly what could happen with the input to _kendall_dis - I think both x and y are ranks, but I couldn't remember whether there could be tied ranks within x, tied ranks within y, and tied ranks between the two. A little bit of thinking / reading code could help remind me, but the option I was suggesting was generating random input (with ties) to scipy.stats.kendalltau and seeing what data gets passed to _kendall_dis.

@mdhaber OK, thanks. Do you think the current test is sufficient? Happy to expand on it if needed.

@fbourgey fbourgey added the Enhancement New feature or request label Apr 15, 2026
@fbourgey

Copy link
Copy Markdown
Member Author

@dschmitz89 when you get the chance, can you please review that one?

Comment thread include/xsf/stats.h

inline double gdtrc(double a, double b, double x) { return cephes::gdtrc(a, b, x); }

inline int64_t kendall_dis(const std::vector<intptr_t> &x, const std::vector<intptr_t> &y) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this need to be CuPy compatible in future? then std::vector is a no go from what I understood.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right, and I have cupy/cupy#9959 working now, so it's something we can actually try out now off of that branch.

@steppi steppi May 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should take three mdspan views, for x and y, but also for the scratch buffer space arr. No allocations inside of kernels. The SciPy gufunc should use the stateful functor pattern from https://github.com/steppi/scipy/blob/759ab1c458d56404dc8938a6074ebec8d290b449/scipy/special/mathieu.h to reuse the scratch buffer over the course of a single gufunc call. The CuPy gufunc will pre-allocate the scratch buffer space in Python wrapper.

@dschmitz89

Copy link
Copy Markdown
Contributor

This LGTM, only question left is the CuPy compatibility.

Comment thread include/xsf/stats.h
inline double gdtrc(double a, double b, double x) { return cephes::gdtrc(a, b, x); }

inline int64_t kendall_dis(const std::vector<intptr_t> &x, const std::vector<intptr_t> &y) {
intptr_t sup = 1 + *std::max_element(y.begin(), y.end());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wait, I missed that the size of the scratch buffer depends on the values of y. I think the way this is done needs to be rethought. I'll look into it.

@steppi steppi May 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seems possible to use a different algorithm (Knight's merge-sort based algorithm) that won't require a buffer with size depending on the values of y. I'll take this one from here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants