Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Fix Outer for SparseArray #940
Fix Outer for SparseArray #940
Changes from 20 commits
c4b6752
45149f3
983049d
e171e0c
e7b68a3
0789bd6
4159b69
58dbb8b
9583f38
f799576
f09b340
6dddce8
12917a1
bbfc74c
9be0ca7
bb133b1
60611b4
8a0057f
e235c04
3af6f9a
4db5ea0
792d218
312eaff
088cbed
daf7d6d
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
Maybe this code deserves to be moved to a
mathics.eval
module.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.
Could you tell me more about how the codes are organized in Mathics3? So that I can determine which code should be moved to
mathics.eval
or other locations in future updates.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.
This aspect is described in https://mathics-development-guide.readthedocs.io/en/latest/extending/code-overview/python-modules.html and
mathics.eval
specifically in https://mathics-development-guide.readthedocs.io/en/latest/extending/code-overview/python-modules.htmlThere 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.
Thanks for the references. But I still have some specific questions left to figure out
mathics.eval
be as general as possible, or is it just a place foreval()
of functions inmathics.builtin
?rec()
andrec_sparse()
. So ifrec_sparse()
should be moved tomathics.eval.tensor
, I'd prefer to treatrec()
(inOuter
and inInner
) the same way.rec()
is moved tomathics.eval.tensor
, it will require as many as 6 parameters(item, rest_lists, current, f, head, evaluation)
, which seems a bit weird to me.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.
The question as is leads me to believe that I might not have have conveyed the motivation. So let me start with that and wind up with some guidelines which I hope you can then decide on how to organize.
Currently Mathics3 evaluates expressions by walking a tree (which is specifically a kind of M-expression)
If Mathics3 is to be sped up, we need to turn the tree evaluation into a sequence of instructions. The functions that start
eval_
you can think of as the instructions. They are top-level functions like Add, Subtract, Factor, etc. but with parameter checking done and objects like Integers and Strings turned into possibly lower, level objects. Basically there would be at least one for every Wolfram Alpha builtin function.Of course, to support these high-level built in functions, we need other functions. Those will not start with
eval_
.With respect to
rec()
andrec_sparse()
specifically, if you do not feel any essential difference between them, then, sure, they both can be moved somewhere under the themathics.eval
module. Please, can we we come up with a more descriptive name thanrec()
andrec_sparse()
and add docstrings to these functions to as well?So finally, I have to describe or apologize for the crappiness of this code, since we are trying to encourage people not to follow the bad habits of what came before.
Originally, this was one huge monolith and we have not come close to digging ourselves out of the mess that is there. In the hierarchical OO monolith, there were a number of nested private functions such as
rec()
(or is it "wreck") that had to duplicated in that organization and because they were or are, well, private functions which probably should not have been private but instead put in a common module where the function can be used both places.Finally as for the number of parameters. It probably means that there is a structure, object, concept or organization that we are missing that exists that encapsulates those parts into a more comprehensive whole.
However since I don't understand what this
rec
thing does, clearly I can't offer a suggestion. If you have an idea here and want to go with that, please suggest something or make that change.Otherwise for the first cut, I would not worry about this initially. We can come back to that. What I have found is that there is so much of a mess, we just can't fix everything all at once. And whatever the ultimate better solution is, having splitting off the common
rec
thing into a separate module will only help things.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.
I looked at the situation with the
rec()
andrec_sparse()
in more detail. Some of the things I said were a bit misleading, or just wrong (because I did not understand the true situation).So let me clarify the situation here and correct some things I wrote.
First, yes indeed, this code goes back to the earliest times and that means the coding style is not good; names are misleading and there are neither docstrings nor documentation describing the code.
I suppose "rec" relates to the recursive implementation. The only way one could make this more vague would to use
f()
orfn()
. But thankfully, at least the wrong term has not be used which was sometimes done.In good programming practice, function names reflect what a function does more than how it is implemented. And here the name is vague too.
As a result, you find a number of internal functions called
rec()
in different Builtin classes that are really not related to one another. But the two functions we are interested in here which are similar arerec()
andrec_sparse()
from BuiltinOuter
.A better name for these two functions would be
create_outer_piece()
andcreate_outer_piece_sparse()
. If it is useful to mention these work recursively, that would be done in the docstring or description of the function. For example:It might also be nice to add type annotations. (This code was written in Python 2.7 when type annotations did not exist. But there comments, docstrings and good programming practice did exist in Python 2.7.)
Here is a suggestion for reorganization...
Create a function called
eval_Outer()
inmathics.eval.tensors
, and move the Python code in current method inOuter
calledeval()
to that renaming and improving therec()
andrec_sparse()
methods. They can still be an internal function as it is here.eval()
then just callseval_Outer
.Later, if we want reorganized things further we are in a better position to do that.
I suspect that you like most people were expecting you'd just make this little change and to get the code to understand sparse arrays and be done with it. I know if I were contributing here, that's what I expect.
The reality is there is a big mess that we picked up that we are still trying to dig ourselves out of. In the past, a great deal of our effort has been just clean up work of the kind mentioned here.
It has been a big mistake to just keep coding in the style and organization that came before. That's what led to this being a big mess rather than just a mess.
To the extent you can help us dig out of this, this is greatly appreciated.
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.
I have to say, my main concern was about having a more or less complicated implementation of the
eval_
methods inside themathics.builtin.tensor
module, not about the private, nested functions. Of course, it is better if these functions are properly named and documented, but at this stage, it would be enough for me to move the implementation tomathics.eval.tensor
, something likeand
In mathics.builtin.tensor
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.
Sounds like the C/C++ style header-source separation?
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.
Yes, I guess so. I suppose this would be a good way to describe it in the developer documentation.
And like C/C++ header-source separation it is not strictly mandatory to make code work, just accepted practice.
As @mmatera says, this is good. We can merge this as is, or do you want to do the other stuff in addition. That can be done in another PR if you prefer.
Let us know.
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.
I believe that (at least in tensor-related evaluations) there are only two cases where recursion is needed, namely tensor contraction (i.e.
Inner, TensorContract, etc.
) and direct product (i.e.Outer, TensorProduct, etc.
). So when I have time I'll try to combinerec()
andrec_sparse()
into a single public function calledcreate_outer_piece()
or something else, and do the same thing forInner
(obviouslyInner
shares the same bug asOuter
).However, that is a completely different thing than fixing
Outer
. So I would prefer this PR to be merged as is, then I will do the above things in another PR.