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

Improve approximate order on getitem calls #35265

Merged

Conversation

mantepse
Copy link
Contributor

@mantepse mantepse commented Mar 11, 2023

πŸ“š Description

Calling Stream_inexact.__getitem__(n) for n == self._approximate_order, we can update self._true_order and self._approximate_order as follows:

  • if the result is non-zero, we now know that n is the true order
  • otherwise, we know that n+1 is a lower bound for the order.

This fixes #35261, but it may not be the best fix, because it potentially makes __getitem__ slower.

Fixes #34556, which was the original issue.

πŸ“ Checklist

  • I have made sure that the title is self-explanatory and the description concisely explains the PR.
  • I have linked an issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation accordingly.

βŒ› Dependencies

@codecov-commenter
Copy link

codecov-commenter commented Mar 11, 2023

Codecov Report

Patch coverage: 93.61% and no project coverage change.

Comparison is base (5330147) 88.61% compared to head (0938ff5) 88.61%.

❗ Current head 0938ff5 differs from pull request most recent head e978a9c. Consider uploading reports for the commit e978a9c to get more accurate results

Additional details and impacted files
@@           Coverage Diff            @@
##           develop   #35265   +/-   ##
========================================
  Coverage    88.61%   88.61%           
========================================
  Files         2148     2148           
  Lines       398855   398841   -14     
========================================
+ Hits        353438   353439    +1     
+ Misses       45417    45402   -15     
Impacted Files Coverage Ξ”
src/sage/rings/lazy_series.py 92.43% <ΓΈ> (ΓΈ)
src/sage/rings/lazy_series_ring.py 89.77% <ΓΈ> (ΓΈ)
src/sage/data_structures/stream.py 97.60% <93.61%> (+0.12%) ⬆️

... and 23 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

β˜” View full report in Codecov by Sentry.
πŸ“’ Do you have feedback about the report comment? Let us know in this issue.

Copy link
Collaborator

@tscrim tscrim left a comment

Choose a reason for hiding this comment

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

While this might slow things down a little bit, it should make the code more robust. My proposed change is to try and simplify the logic a bit (at least to my eyes).

src/sage/data_structures/stream.py Outdated Show resolved Hide resolved
@mantepse mantepse marked this pull request as draft March 16, 2023 12:13
@mantepse
Copy link
Contributor Author

I think that this should also simplify the computation of Stream_inexact.order.

@mantepse
Copy link
Contributor Author

dense case is missing, working on it

@mantepse mantepse marked this pull request as ready for review March 16, 2023 14:18
src/sage/data_structures/stream.py Outdated Show resolved Hide resolved
src/sage/data_structures/stream.py Show resolved Hide resolved
Comment on lines 404 to 420
# Dense implementation
i = n - self._offset
if i >= len(self._cache):
a = len(self._cache) + self._offset
if self._true_order:
# It is important to extend by generator:
# self._iter might recurse, and thereby extend the
# cache itself, too.
self._cache.extend(next(self._iter) for _ in range(a, n+1))
c = self._cache[i]
else:
for _ in range(a, n+1):
c = next(self._iter)
self._cache.append(c)
if c:
self._true_order = True
else:
self._approximate_order += 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 don't see how to make inline review suggestions that span such changes like this. It would be nice if things worked much more uniformly than they do...

Suggested change
# Dense implementation
i = n - self._offset
if i >= len(self._cache):
a = len(self._cache) + self._offset
if self._true_order:
# It is important to extend by generator:
# self._iter might recurse, and thereby extend the
# cache itself, too.
self._cache.extend(next(self._iter) for _ in range(a, n+1))
c = self._cache[i]
else:
for _ in range(a, n+1):
c = next(self._iter)
self._cache.append(c)
if c:
self._true_order = True
else:
self._approximate_order += 1
# Dense implementation
i = n - self._offset
if i >= len(self._cache):
a = len(self._cache) + self._offset
if not self._true_order:
for _ in range(a, n+1):
c = next(self._iter)
if c:
self._true_order = True
break
a = len(self._cache) + self._offset
self._approximate_order = a
if self._true_order:
# It is important to extend by generator:
# self._iter might recurse, and thereby extend the
# cache itself, too.
self._cache.extend(next(self._iter) for _ in range(a, n+1))

It is slightly more complicated logic, but it reduces some duplication and should be faster. Basically, it works by updating until it finds the true order then proceeds by a direct extension. If it doesn't find the true order but reaches n, then it falls through with a large enough cache.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like the idea, however, as coded it does not work for me. One reason is that we have to put c into the cache. However, this still breaks _offset. I am working on it.

tscrim added a commit to tscrim/sage that referenced this pull request Mar 20, 2023
@mantepse
Copy link
Contributor Author

Your comment sparkled quite a simplification, please have a look. The idea is to get rid of _offset by insisting that the cache in the dense case starts with the first non-zero term.

I noticed, that some (or, at least one) of the (in)equality checks could be improved, I have not done this yet.

There is one minor (?) optimisation that is possible in the sparse case: if we compute self[self._approximate_order], and this turns out to be zero, it is not necessary to put it into the cache. Of course, this will help only if the coefficients are computed in order. On the other hand, keeping the cache small is probably a good idea.

@mantepse
Copy link
Contributor Author

I think improving the (in)equality checks could be done in a separate ticket.

@mantepse
Copy link
Contributor Author

Sorry, there is still a bug - I tried to make the logic clean, but I still tripped over a case. If n == self._approximate_order and c we also should set true_order.

@tscrim
Copy link
Collaborator

tscrim commented Mar 21, 2023

Doing that for the dense case was something I remember us considering and then rejecting for some reason (which I don't remember). It might have been something relevant to the implementation at the time.

I also think for the sparse case not putting things into the cache is the right way to go. The smaller the cache, the less we have to copy/manipulate/store-in-memory/etc.

@mantepse
Copy link
Contributor Author

This should be OK now. It is not the most beautiful piece of code I've ever written, but I don't see how to make it much better.

I also tried it locally with #35293, which works after resolving a trivial merge conflict. Stream_truncate._offset should be removed of course.

It is not clear to me whether in which circumstances I should update to develop. Feel free to click on "update branch" (or tell me to do it in case you do not have permission).

@mantepse
Copy link
Contributor Author

Oh, and Stream_truncate.order is also outdated now, of course.

Copy link
Collaborator

@tscrim tscrim left a comment

Choose a reason for hiding this comment

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

Thank you. I think this is a good improvement. Let's get this in. If we find anything else, we can do a followup PR. I will also update #35293 accordingly.

tscrim added a commit to tscrim/sage that referenced this pull request Mar 22, 2023
@mantepse mantepse added this to the sage-10.0 milestone Mar 22, 2023
@github-actions
Copy link

Documentation preview for this PR is ready! πŸŽ‰
Built with commit: 0938ff5

@vbraun
Copy link
Member

vbraun commented Mar 26, 2023

Merge conflict

@vbraun vbraun merged commit 3142be9 into sagemath:develop Apr 1, 2023
5 of 6 checks passed
vbraun pushed a commit that referenced this pull request Apr 1, 2023
    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes #1234" use "Introduce new method to
calculate 1+1"
-->
### πŸ“š Description

This address the arity problem noted in #35261. It also removes a `TODO`
in a `revert()` implementation by making the behavior the same across
different implementations. Warnings are added for the user for the
assumptions made by the code.

### πŸ“ Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->

- [x] I have made sure that the title is self-explanatory and the
description concisely explains the PR.
- [x] I have linked an issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation accordingly.

### βŒ› Dependencies
<!-- List all open pull requests that this PR logically depends on -->

- #35127 Avoiding a long test.
- #35254 Avoiding merge conflicts.
- #35291 Making sure these changes work together.
- #35265 For some slight simplification of the new stream's
`__getitem__`.
    
URL: #35293
Reported by: Travis Scrimshaw
Reviewer(s): Martin Rubey, Travis Scrimshaw
@mantepse mantepse deleted the improve_approximate_order_on__getitem__calls branch April 1, 2023 17:41
vbraun pushed a commit to vbraun/sage that referenced this pull request Sep 14, 2023
    
<!-- Please provide a concise, informative and self-explanatory title.
-->
<!-- Don't put issue numbers in the title. Put it in the Description
below. -->
<!-- For example, instead of "Fixes sagemath#12345", use "Add a new method to
multiply two integers" -->

We allow lazy series to compute infinite sums `\sum_{i \in I} p_i` and
products `\prod_{i \in I} (1 + p_i)` over arbitrary (enumerated) index
sets `I` subject to a somewhat mild technical constraint that the order
of each input `p_i` is weakly increasing wrt the iteration order and the
preimage of each order is finite.

### πŸ“ Checklist

<!-- Put an `x` in all the boxes that apply. It should be `[x]` not `[x
]`. -->

- [x] The title is concise, informative, and self-explanatory.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation accordingly.

### βŒ› Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

- sagemath#35265

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#35362
Reported by: Travis Scrimshaw
Reviewer(s): Martin Rubey, Travis Scrimshaw
vbraun pushed a commit to vbraun/sage that referenced this pull request Sep 16, 2023
    
<!-- Please provide a concise, informative and self-explanatory title.
-->
<!-- Don't put issue numbers in the title. Put it in the Description
below. -->
<!-- For example, instead of "Fixes sagemath#12345", use "Add a new method to
multiply two integers" -->

We allow lazy series to compute infinite sums `\sum_{i \in I} p_i` and
products `\prod_{i \in I} (1 + p_i)` over arbitrary (enumerated) index
sets `I` subject to a somewhat mild technical constraint that the order
of each input `p_i` is weakly increasing wrt the iteration order and the
preimage of each order is finite.

### πŸ“ Checklist

<!-- Put an `x` in all the boxes that apply. It should be `[x]` not `[x
]`. -->

- [x] The title is concise, informative, and self-explanatory.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation accordingly.

### βŒ› Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

- sagemath#35265

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#35362
Reported by: Travis Scrimshaw
Reviewer(s): Martin Rubey, Travis Scrimshaw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug in revert method for lazy power series improve approximate order on __getitem__ calls
5 participants