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

New indexing and iteration for ProductSector #141

Merged
merged 2 commits into from
Aug 4, 2024
Merged

Conversation

Jutho
Copy link
Owner

@Jutho Jutho commented Aug 3, 2024

ProductSector can be indexed and will iterate using an order that is based on running through slices of constant Manhattan distance. This enables indexing and meaningful iteration if infinite sectors are included in the product sector.

Copy link

codecov bot commented Aug 3, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 79.94%. Comparing base (ca4853a) to head (72c76f8).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #141   +/-   ##
=======================================
  Coverage   79.94%   79.94%           
=======================================
  Files          42       42           
  Lines        4962     4962           
=======================================
  Hits         3967     3967           
  Misses        995      995           

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

Copy link
Collaborator

@lkdvos lkdvos left a comment

Choose a reason for hiding this comment

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

I just added some of my thoughts as a reply to the "can we make this faster" comment, but I am not sure if this really matters, and presumably that really is over-engineering things.
At the very least, I would say to merge as-is, and if necessary optimize later

function Base.isless(p1::ProductSector{T}, p2::ProductSector{T}) where {T}
return isless(reverse(p1.sectors), reverse(p2.sectors))
function Base.isless(p1::P, p2::P) where {P<:ProductSector}
return isless(findindex(values(P), p1), findindex(values(P), p2))
Copy link
Collaborator

@lkdvos lkdvos Aug 4, 2024

Choose a reason for hiding this comment

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

I think here it is possible to try to avoid computing the manhattan index if we really want:

  • first compute the manhattan distance and compare
  • if equal, only the localoffset should be compared

I would even guess that this second point can be determined without even computing the offset, by comparing the cartesianindices?

@@ -13,3 +13,78 @@ function _kron(A, B)
end
return C
end

# Manhattan based distance enumeration: I is supposed to be one-based index
# TODO: is there any way to make this faster?
Copy link
Collaborator

Choose a reason for hiding this comment

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

There's definitely some number theory stuff that could come in handy here, if I am not mistaken, the relevant terms are triangular numbers, tetrahedral numbers, and their generalizations.
There are general formulas for this:

$$\sum_{n_{k-1} = 1}^{n_k} \sum_{n_{k-2} = 1}^{n_{k-1}} \cdots \sum_{n_1 = 1}^{n_2} n_1 = \begin{pmatrix} n_k + k - 1 \\ k \end{pmatrix}$$

This is however for infinite grids, but I feel like it should be possible to split the grid into regions that are either hyperrectangular, or "hypertriangular", both of which have "volume formulas"?

https://en.wikipedia.org/wiki/Tetrahedral_number

Copy link
Owner Author

Choose a reason for hiding this comment

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

The binomial formula is what I started with, but that indeed only works if there are no upper bounds, i.e. if all the sectors involved are infinite.


function Base.iterate(P::SectorValues{ProductSector{T}}, i=1) where {T<:SectorTuple}
Base.IteratorSize(P) != Base.IsInfinite() && i > length(P) && return nothing
return getindex(P, i), i + 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess here is the biggest possible speed trap, it feels like it could be possible to iterate through these without having to map to linear indices, similar to how cartesianindices can be iterated without the integer divisions.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Given that iteration over all possible sector values is not really used in the code, except for making tests, I don't care too much about the speed of this :-)

@Jutho
Copy link
Owner Author

Jutho commented Aug 4, 2024

Ok, I think I will merge as is. I have ran the tests locally, but currently the TensorKitSectors tests are not running in CI. While analysing CI, also noticed something weird. The MacOS tests are all slightly quicker then on Ubuntu (for the tensor tests, they do not have all the sector choices in common, but those that do were always a bit faster on Mac), up to the point of AD. The AD tests seem anyway to take very long compared to the rest of the tests on both platforms, but on Mac they become really excessive. The AD tests for Rep[U1] take 14 minutes on Ubuntu and 87 minutes (!) on Mac. Not sure what is going on there; maybe excessive memory leading to caching or something?

@lkdvos
Copy link
Collaborator

lkdvos commented Aug 4, 2024

It could also be the RNG, I think the AD tests are really fully random (including spaces/arrows etc) now, making it quite hard to control the weight of the tests...

@Jutho Jutho merged commit fc34907 into master Aug 4, 2024
14 checks passed
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