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

MatrixObj semantics: how to handle dimension mismatch in matrix and vector arithmetics #3561

Open
fingolfin opened this issue Jul 12, 2019 · 4 comments
Assignees
Labels
kind: discussion discussions, questions, requests for comments, and so on

Comments

@fingolfin
Copy link
Member

While working on PR #2973, I noticed that most arithmetics there did not perform any checks on the dimensions of the involved input matrices. Likewise for vectors. (And actually, also no basedomain checks; but to keep things simpler, I'd like to focus on the dimensions in this issue; we can discuss basedomain checks separately; so for this issue, let's assume that all matrices and vectors have identical basedomain).

We should decide what we demand from resp. allow MatrixObj implementations to do when dimensions don't match. To simplify the discussion further, let's start by focusing on a single example:

What should happen two matrices are added whose dimensions differ?

If they are lists-of-lists, GAP will happily proceed; but the output may not be a matrix anymore:

gap> [[1,2]] + [[3],[4]];
[ [ 4, 2 ], [ 4 ] ]

Similarly, one can add lists of differing lengths; the missing entries in the shorter list are essentially treated as being zero.

So, here are some options I can think of:

  1. We forbid this, and require that conformant MatrixObj implementations must check the dimensions, and must produce an error if the dimensions do not match

  2. We document the behavior explicitly undefined. MatrixObj implementations may check the dimensions, and may produce an error if the dimensions do not match; but they can also produce bogus results

  3. We explicitly allow this, and define what the resulting matrix should be (likely: taking the maximum of the number of rows, and the maximum of the number of columns, and create a matrix of that size; fill the result up with zeros as needed).

  4. ... other possibilities... ?

To me option 3 is the least interesting, as I see no applications of this rather artificial behavior. The drawback of option 1 is that it has a performance penalty, albeit probably a rather small one (this is a different once one considers the BaseDomain, though!).

I think I kind of prefer option 2 for this reason, although it has the drawback of letting buggy code slip through. But if we add checks inside of Assert statements in as many places as possible, one could simply set the assertion level up to get slower code that however immediately points out any such bugs.

This example of course has many variants, for addition, subtraction, multiplication; and also for vectors, and as I mentioned, for the basedomain. We should resolve all of those eventually.

@fingolfin fingolfin added the kind: discussion discussions, questions, requests for comments, and so on label Jul 12, 2019
@ThomasBreuer
Copy link
Contributor

I would also prefer option 2.

As for option 1, the very general arithmetic behaviour of nested lists was chosen deliberately and should not be restricted. And since a plain list of lists is regarded as a MatrixObj, one could force checks as prescribed by option 1 only for implementations other than plain lists of lists.

Option 3 looks like forcing each implementation of a new kind of MatrixObj to provide extra code for situations which are not intended.

@stevelinton
Copy link
Contributor

Is there any merit in a category something like IsStrictMatrixObj which guarantees that arithmetic on objects in it will produce an error if the dimensions don't match.

Incidentally, one fundamental concept behind the behaviour of nested lists was to allow unbound entries to regarded as zeros, which people wanted for various things. There were (a lot of) other considerations.

@fingolfin
Copy link
Member Author

The beauty of MatrixObj is that one can still represent zero entries by unbounded entries internally, this just would be hidden from the user. Of course one also will want ways to make the sparsity "visible", so it can be exploited, but I don't think forcing client code to inspect each entry for being bound/unbound would be helpful or relevant for that.

@DominikBernhardt
Copy link
Contributor

I am not entirely happy with option 2 as this may produce wrong results and the working mathematician might not notice this at first. Could we maybe provide wrapper functions with checks for dimension that then dispatch to a NC version of the function that can still be used internally?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: discussion discussions, questions, requests for comments, and so on
Projects
No open projects
Status: No status
Development

No branches or pull requests

4 participants