Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added array_permutations (attempt 2) #1014

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

ronnodas
Copy link
Contributor

Most of the changes are to create a common abstraction that works for permutations and {array_,}combinations, much of it by @phimuemue. Completes a variant of #1001.

Copy link

codecov bot commented Jan 13, 2025

Codecov Report

Attention: Patch coverage is 94.17476% with 6 lines in your changes missing coverage. Please review.

Project coverage is 94.38%. Comparing base (6814180) to head (1348785).
Report is 134 commits behind head on master.

Files with missing lines Patch % Lines
src/lazy_buffer.rs 89.47% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1014      +/-   ##
==========================================
- Coverage   94.38%   94.38%   -0.01%     
==========================================
  Files          48       50       +2     
  Lines        6665     6930     +265     
==========================================
+ Hits         6291     6541     +250     
- Misses        374      389      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@phimuemue phimuemue left a comment

Choose a reason for hiding this comment

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

  • Importing things: Do we use use something as _ in our codebase? If not, please go with use something;.
  • Is ArrayOrVecHelper for Vec<usize> even needed after all this? Shouldn't combinations also run via Box<[usize]>?

src/combinations.rs Outdated Show resolved Hide resolved
use std::fmt;
use std::iter::FusedIterator;

use super::lazy_buffer::LazyBuffer;
use super::lazy_buffer::{LazyBuffer, PoolIndex};
Copy link
Member

@phimuemue phimuemue Jan 13, 2025

Choose a reason for hiding this comment

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

I think PoolIndex is not really tied to LazyBuffer (it should be compatible with anything you can usize-index into), so it should probably have an own module.

cycles: Box<[usize]>, // TODO Should be Idx::Item<usize>
k: Idx::Length, // TODO Should be inferred from cycles
},
Loaded { indices: Box<[usize]>, cycles: Idx },
Copy link
Member

Choose a reason for hiding this comment

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

Is cycles really an Idx or should it actually be Idx::Item<usize>? I know that these are the same types, but don't the semantics differ? I.e. isn't Idx always meant to index into a slice, whereas Idx::Item<usize> is an array or a Vec containing usizes?

If we'd like to avoid answering this question, we could keep Loaded::k: Idx::Length.

Copy link
Contributor Author

@ronnodas ronnodas Jan 13, 2025

Choose a reason for hiding this comment

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

cycles is really neither an Idx nor an Idx::Item<usize>, since Idx::Item should be what is obtained by indexing something of type Idx into the buffer, but I don't feel strongly about this. Maybe it makes sense to keep cycles of type Box<[usize]> and switch back to the name PoolIndex so that that trait has clearer semantics.

src/permutations.rs Outdated Show resolved Hide resolved
cycles,
k: *k,
};
let item = Idx::item_from_fn(k, |i| vals[indices[i]].clone());
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this indices.extract_item(vals)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, for the same reason as in the PermutationState::Loaded case, indices is now of length n.

@@ -173,22 +165,26 @@ impl<Idx: ArrayOrVecHelper> PermutationState<Idx> {
let total = (n - k.value() + 1..=n).try_fold(1usize, |acc, i| acc.checked_mul(i));
(total.unwrap_or(usize::MAX), total)
};
match *self {
match self {
Copy link
Member

Choose a reason for hiding this comment

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

Why did this change from *self to self? Is this really realted to this commit?

We can take this, but I prefer not to mix it into these commits, if possible.

Copy link
Contributor Author

@ronnodas ronnodas Jan 13, 2025

Choose a reason for hiding this comment

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

It is related: Buffered.indices is no longer Copy, we could add a ref there instead.

Or alternatively also remove the refs in the Loaded case.

src/combinations.rs Outdated Show resolved Hide resolved
@@ -57,7 +57,7 @@ where
debug_fmt_fields!(Combinations, indices, pool, first);
}

impl<I: Iterator, Idx: PoolIndex> CombinationsGeneric<I, Idx> {
impl<I: Iterator, Idx: ArrayOrVecHelper> CombinationsGeneric<I, Idx> {
Copy link
Member

Choose a reason for hiding this comment

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

Is Idx still a good name if the trait is ArrayOrVecHelper?

@ronnodas
Copy link
Contributor Author

Is ArrayOrVecHelper for Vec even needed after all this? Shouldn't combinations also run via Box<[usize]>?

This is needed to allow Combinations::reset, which is (only) used by powerset.

@phimuemue
Copy link
Member

phimuemue commented Jan 15, 2025

@jswrenn I'd like to bump to Rust 1.65, because it allows generic associated types.

We currently have trait PoolIndex<T>, but what we actually want is trait ContiguousSequence { type Type<T>: BorrowMut<[T]>; } which could then be impld for Vecs and arrays. Then, we could use ContiguousSequence::Type with different Ts (nice, because the indices/cycles use ContiguousSequence::Type<usize> and e.g. Permutations::Item = ContiguousSequence::Type<UnderlyingIterator::Item>).

I tried staying in Rust 1.63, but we'd have to bend over backwards to achieve something similar.

Please let me know if I can do this, then I'll prepare a PR changing PoolIndex<T> to ContiguousSequence, paving the way for array_permutations.

@ronnodas I'll keep you in the loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants