-
Notifications
You must be signed in to change notification settings - Fork 165
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
IsAssociativeElement
: Documentation wrong? Bug?
#2776
Comments
I agree that But let's look at the technical reasons for this, and what we might be able to do about it. You give two examples, but in The problem is how we compute types of lists (and hence whether they are in a given filter or not). Clearly it is desirable to have this fast. For proper objects, this is no problem, as the type is stored. But for lists, the type has to be recomputed each time we ask for it. So to make it fast, for homogenous lists, we essentially only take the families of the elements in to account. Consider this snippet:
Now, the type of the list of course inherits all filters implied by its family. But it has more: namely any filters that come from implications. For the example at hand, the following declarations and implications are relevant: DeclareSynonym( "IsAdditiveElementWithInverseTable",
IsAdditiveElementWithInverseCollColl and IsTable );
DeclareSynonym( "IsRingElementTable",
IsAdditiveElementWithInverseTable
and IsMultiplicativeElementTable );
DeclareSynonym( "IsMatrix", IsRingElementTable );
InstallTrueMethod( IsOrdinaryMatrix, IsMatrix and IsInternalRep );
InstallTrueMethod( IsAssociativeElement, IsOrdinaryMatrix and IsAssociativeElementCollColl ); The family object of But crucially, the In order to get the type right here, GAP would have to iterate over all list elements, compute their types, then "intersect" the filters/flags they imply, and use that. That's a lot more expensive for a homogenous list than to just consider the type of a single element in the list. Now, truth be told, in the above example, we actually are iterating over all elements -- because those lists (and lists of lists, and so on) all are mutable, so their types are not fully stored, and thus have to be recomputed every. single. time. we interact with these lists (which is a nightmare of its own, and we discussed this plenty before). In theory, we could add a special case to the kernel here: for homogenous lists, inspect the type of one elements, and check for certain filters; if set, add the corresponding But that's still a rather nasty hack (and I am not even sure it actually would work the way I think it might). I have doubts whether it'd be really worth it. Which is of course one of the many reasons why we want "real" matrix and vector objects. Which gets us back to my original remark: Why does The reasons for this really are: no fully function MatrixObj and VectorObj types are available yet; indeed there are still lots of details to be fleshed out; existing implementations are slow or incomplete; and also, anything we put out "officially" risks becoming a hard depdenency we can never get rid of again. Moreover, in long discussions on whether ...
it was finally determined that option 2 was most beneficial, and this has now been implemented in the library. But to be honest, I can't fully get the argument back together, gotta look at notes when I have had slept (and perhaps @ThomasBreuer can chime in). Part of it certainly was to make a gradual transition of existing code possible. However, now that I am writing this, I am once again wondering about it... ah well... Anyway, from a pragmatic point of view, what we need is a highly optimized and complete "generic" MatrixObj implementation that works over arbitrary base domains, to replace uses of lists-of-lists (and the same for vectors, of course). Then, we need matrix/vector implementations for various specialized domains. For small finite fields, we of course have our compressed matrices; but there are various bottlenecks in them that should be addressed (and for compatibility reasons, we might instead want to add a new type, and leave the existing compressed matrix code for legacy support only... I could explain more of why I think that might be best, but I am already digressing too far). Anyway, regarding performance: We could make
If this was stored in a single GAP object, it'd need about 56 bytes of storage (24 for GAP meta data, 8 for a pointer to a type object, 4+4 for row/column length, 13 for the actual data, 3 for padding); perhaps some more in the end if we need to store some more meta data. So a factor of 10 in storage, and also many advantage in performance. This is part of the reasons why I think we need to overhaul our compressed matrix type, or implement yet another one: it's better to store the matrix more compactly (also for memory locality), and use proxy objects to fake support for To give an idea about the performance of
and over the integers:
This could be greatly improved if those |
PS: I just spent a few minutes on optimizing
I'll try to make a PR out of this, and perhaps we can switch UPDATE: used slightly different timings; those from my first run were looking overly good by chance; these numbers fluctuate quite a bit, gotta dig out my benchmarking code for better numbers when fine tuning this. |
Oh, and of course for highest performance (beating that of plists) in the generic case, one could implement a |
Disregard my comment about I do think that there is some sense in a matrix being an |
Since I was mentioned in some of the comments, just a few remarks.
|
There are two underlying problems here: (1) a matrix with mutable rows cannot remember anything which might be changed if one of the rows is mutated (in particular, in this case, if its length changes) (2) for some lists, even immutable ones, such as enumerators of FP groups, determining the length maybe arbitrarily expensive, so working out if a list of such things is rectangular would be a problem. I suspect what this really means is that IsRectangularTable should not be a Category. |
@ThomasBreuer I agree that most of what I wrote above got quite off tangent; gotta make sure to add a link to it "somewhere" where MatrixObj design is discussed, and/or copy it there (but where is such a place? @stevelinton the second issue doesn't seem relevant here at all; the second is correct, but IMHO also not quite at the core of the issue -- after all, even an immutable plist cannot store a type, as |
Documentation
GAP
master
and also
The text was updated successfully, but these errors were encountered: