-
-
Notifications
You must be signed in to change notification settings - Fork 655
Optimize AdditiveMonoids sum() method #39726
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
Conversation
Documentation preview for this PR (built with commit accd7cd; changes) is ready! 🎉 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo one doc tweak.
Also, perhaps as a followup, the |
Co-authored-by: Travis Scrimshaw <clfrngrown@aol.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. LGTM.
I think this one is already using
We may also want to optimize this thing though.
Using weights may make it a bit faster, but I don't think it is too useful in practice and requires extra API guarantee of subclasses. (In fact the binary splitting already guarantee |
I don’t think it will be easy to optimize the symbolic sum (the sumbolic?) since it needs to do a lot of preprocessing/delegation. (That being said, +1 if you’re able to do it.) Ah, right. I was thinking more of the |
Looking at the source code of that… cpdef dict sum(dict_iter):
r"""
Return the pointwise addition of dictionaries with coefficients.
INPUT:
- ``dict_iter`` -- iterator of dictionaries whose values are in
a common ring and all values are nonzero
OUTPUT:
- a dictionary containing all keys of the dictionaries in ``dict_list``
with values being the sum of the values in the different dictionaries
(keys with zero value are omitted)
EXAMPLES::
sage: import sage.data_structures.blas_dict as blas
sage: D = {0: 1, 1: 1}; D
{0: 1, 1: 1}
sage: blas.sum(D for x in range(5))
{0: 5, 1: 5}
sage: D1 = {0: 1, 1: 1}; D2 = {0: -1, 1: 1}
sage: blas.sum([D1, D2])
{1: 2}
sage: blas.sum([{}, {}, D1, D2, {}])
{1: 2}
"""
cdef dict result = {}
cdef D
for D in dict_iter:
if result:
iaxpy(1, D, result, remove_zeros=False)
elif D:
result = D.copy()
return remove_zeros(result)
cpdef dict linear_combination(dict_factor_iter, bint factor_on_left=True):
r"""
Return the pointwise addition of dictionaries with coefficients.
INPUT:
- ``dict_factor_iter`` -- iterator of pairs ``D``, ``coeff``, where
* the ``D``'s are dictionaries with values in a common ring
* the ``coeff``'s are coefficients in this ring
- ``factor_on_left`` -- boolean (default: ``True``); if ``True``,
the coefficients are multiplied on the left, otherwise they are
multiplied on the right
OUTPUT:
- a dictionary containing all keys of dictionaries in ``dict_list``
with values being the sum of the values in the different
dictionaries and each one first multiplied by the given factor
(keys with zero value are omitted)
EXAMPLES::
sage: import sage.data_structures.blas_dict as blas
sage: D = { 0:1, 1:1 }; D
{0: 1, 1: 1}
sage: blas.linear_combination( (D,i) for i in range(5) )
{0: 10, 1: 10}
sage: blas.linear_combination( [(D,1), (D,-1)] )
{}
"""
cdef dict result = {}
cdef dict D
for D, a in dict_factor_iter:
if not a: # We multiply by 0, so nothing to do
continue
if not result and a == 1:
result = D.copy()
else:
iaxpy(a, D, result, remove_zeros=False)
return remove_zeros(result) So in the most common case where operations on the base ring takes constant time, this is already the best we can do. It probably won't show up too much in practice. (meanwhile looking at the code I notice #40127) |
Here, since it is implement sparsely as a |
No? The current implementation is such that:
You cannot do better than this for generic values, right? |
I'm not quite convinced. I feel like the same argument could be made for this PR, where is clearly is having an effect. For dense vectors, then I agree it would likely have no discernible effect. If we had a clairvoyant daemon that could do the sums using as few overlapping supports as possible, then it would be faster as we simply need to update the Additionally we can also simply take the larger For the linear combinations, we could group things with the same coefficient to minimize the number of multiplications in the base ring, which could be relatively expensive. This is likely a speedup asymptotically, but not sure if it is worthwhile to implement. |
No, in this PR then:
If however |
Assume hash/dictionary lookup etc. is slow it would backfire though. Whether it's an asymptotic improvement… maybe, I'll need to think about it. |
sagemathgh-39726: Optimize AdditiveMonoids sum() method Previously the example shown takes way too long. Now it takes 0.5s. It is probably possible to optimize further by specialize it using Singular. Opinion: how should the iterator multiplication be implemented * as is (disadvantage: slightly misleading method name), * copy paste the code logic of `iterator_prod` and make a new method `iterator_sum` (disadvantage: code duplication), * make an internal method `_iterator_combine` that takes `bint multiply`, then make `iterator_prod` and `iterator_sum` call it (disadvantage: potential slower branching each operation, but should be negligible) ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [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 and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#39726 Reported by: user202729 Reviewer(s): Travis Scrimshaw, user202729
sagemathgh-40126: Simplify QuiverRep_generic.linear_combination_of_basis method Shorten the code. This might become faster after sagemath#39726 (or might not, I haven't benchmarked) ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#40126 Reported by: user202729 Reviewer(s): Travis Scrimshaw
sagemathgh-39726: Optimize AdditiveMonoids sum() method Previously the example shown takes way too long. Now it takes 0.5s. It is probably possible to optimize further by specialize it using Singular. Opinion: how should the iterator multiplication be implemented * as is (disadvantage: slightly misleading method name), * copy paste the code logic of `iterator_prod` and make a new method `iterator_sum` (disadvantage: code duplication), * make an internal method `_iterator_combine` that takes `bint multiply`, then make `iterator_prod` and `iterator_sum` call it (disadvantage: potential slower branching each operation, but should be negligible) ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [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 and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#39726 Reported by: user202729 Reviewer(s): Travis Scrimshaw, user202729
sagemathgh-40126: Simplify QuiverRep_generic.linear_combination_of_basis method Shorten the code. This might become faster after sagemath#39726 (or might not, I haven't benchmarked) ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#40126 Reported by: user202729 Reviewer(s): Travis Scrimshaw
sagemathgh-39726: Optimize AdditiveMonoids sum() method Previously the example shown takes way too long. Now it takes 0.5s. It is probably possible to optimize further by specialize it using Singular. Opinion: how should the iterator multiplication be implemented * as is (disadvantage: slightly misleading method name), * copy paste the code logic of `iterator_prod` and make a new method `iterator_sum` (disadvantage: code duplication), * make an internal method `_iterator_combine` that takes `bint multiply`, then make `iterator_prod` and `iterator_sum` call it (disadvantage: potential slower branching each operation, but should be negligible) ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [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 and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#39726 Reported by: user202729 Reviewer(s): Travis Scrimshaw, user202729
sagemathgh-40126: Simplify QuiverRep_generic.linear_combination_of_basis method Shorten the code. This might become faster after sagemath#39726 (or might not, I haven't benchmarked) ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#40126 Reported by: user202729 Reviewer(s): Travis Scrimshaw
sagemathgh-40126: Simplify QuiverRep_generic.linear_combination_of_basis method Shorten the code. This might become faster after sagemath#39726 (or might not, I haven't benchmarked) ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#40126 Reported by: user202729 Reviewer(s): Travis Scrimshaw
Previously the example shown takes way too long. Now it takes 0.5s.
It is probably possible to optimize further by specialize it using Singular.
Opinion: how should the iterator multiplication be implemented
iterator_prod
and make a new methoditerator_sum
(disadvantage: code duplication),_iterator_combine
that takesbint multiply
, then makeiterator_prod
anditerator_sum
call it (disadvantage: potential slower branching each operation, but should be negligible)📝 Checklist
⌛ Dependencies