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

[Discussion] Separating labels and integers #4

Open
lkdvos opened this issue Dec 12, 2024 · 2 comments
Open

[Discussion] Separating labels and integers #4

lkdvos opened this issue Dec 12, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@lkdvos
Copy link
Contributor

lkdvos commented Dec 12, 2024

The current design for labelled numbers incurs a rather large number of method ambiguities and can possibly lead to invalidations, since defining new integer types etc is a big source of that.
Of course, this should not be an argument to never define new number types, but just to carefully consider the benefits.

Here, (correct me if I'm wrong), the main purpose is to have labels attached to GradedUnitRange objects, such that these can easily/automatically be carried along.
One alternative could be to separate the labels and the integers again, and manually handle that kind of logic in GradedUnitRange. The benefit is that this does not suffer from ambiguities and invalidations, but of course requires a bit more manual work.

Just to add this information here, as @mtfishman mentioned, one nice feature that we probably should preserve in any case is that indexing into a gradedrange outputs something that contains both the label as well as the range information:

what I like about the current design is that when you index into a GradedUnitRange, i.e. g[2], it outputs the range value along with information about the sector. That is consistent with the fact that we want slices like g[Block.(2:3)], g[2:5], g[Block(2)], etc. to preserve the sector information.

(linking #3)

After thinking about this a bit more, it seems to me that - at least for slicing operations - this should not be a real problem to support in any case, since indexing into a gradedrange object returns another gradedrange, which thus retains that information. The harder case to figure out is what "scalar indexing" should do, similar to how scalar indexing into BlockArrays becomes a bit more involved. The normal Julia array behavior is to drop scalar dimensions, reducing the total number of dimensions as you index. This is slightly annoying to deal with for ranges/axes that want to hold on to more information, since there you really don't want to drop these dimensions, because that would also discard the label/grading information.
Effectively, I would probably advocate that for these kinds of arrays, indexing should either be "fully scalar", and if not, considered as a slicing operation.

a[1,2,3] # scalar
a[1:3, 2:4, 2:3] # slicing: Array{T,3} as result
a[1, :, :] # slicing: Matrix as result -- should really just stay Array{T,3}!!

To achieve this, effectively you would have that a[i, ...] would become a[i:i, ...] whenever not all indices are "scalar". This would also solve the issue that indexing with a scalar into a gradedrange loses the label information, as now g[i:i] would still output a range.

@lkdvos lkdvos added the enhancement New feature or request label Dec 12, 2024
@mtfishman
Copy link
Member

mtfishman commented Dec 12, 2024

So, I remembered the feature I like the most about the current design, which is that code like this:

r = blockedrange([2, 3])
# Or:
r = gradedrange([U1(0) => 2, U1(1) => 3])

# Outputs either blocked range or graded range
# depending on `r`
blockedrange(blocklengths(r))

"just works". That is helpful for making code generic between graded unit ranges and plain blocked unit ranges. Right now that is made possible because blocklengths(::AbstractGradedUnitRange) outputs a list of labelled integers, but maybe we can get that behavior (and similar behavior where we want the sector information preserved in generic code) in other ways, such as the suggestion in ITensor/SymmetrySectors.jl#4 (comment) to have blocklengths(::AbstractGradedUnitRange) output an iterator object.

@lkdvos
Copy link
Contributor Author

lkdvos commented Dec 12, 2024

Maybe a different way to formulate the question could be if we can get away with not making LabelledInteger a subtype of Integer, which would also solve these issues.
In some sense, I would indeed expect blocklengths to return information about the different sectors and their corresponding lengths.
I think it might be intuitive to think about this as follows: you need to blocklengths needs to return two pieces of information: the "order" of the blocks and their sizes.

  • standard blockaxes have blocklengths that are just ordered according to linear ordering: blocklengths(r)[i] yields the length of block i::Int. Ie, this behaves like vectors of blocklengths.
  • graded blockaxes have blocklengths that are ordered according to their label: blocklengths(r)[c] yields the length of the block with label c. Ie, this behaves somewhat like a dictionary.

Clearly, whether this is a vector or a dictionary should just be an implementation detail

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

No branches or pull requests

2 participants