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

Syntax extension: allow mat{idxlist1, idxlist2} as alternative for mat{idxlist1}{idxlist2} (OR allow mat[idxlist1, idxlist2]) #4356

Open
fingolfin opened this issue Mar 29, 2021 · 1 comment

Comments

@fingolfin
Copy link
Member

fingolfin commented Mar 29, 2021

The proposal

In GAP, one can reference a sublist or "slice" of a list via the syntax list{idx} where idx is a list of indices. For example:

gap> list := [10, 20, 30, 40];;
gap> list{[3,1,2,2]};
[ 30, 10, 20, 20 ]

This can also be nested to reference a submatrix:

gap> mat := [ [ 0, 0, 4 ], [ 1, 0, -2 ], [ 0, 1, 1 ] ];;
gap> mat{[1,3]}{[2,3]};
[ [ 0, 4 ], [ 1, 1 ] ]

This can even be extended to higher types of "tensors", and combined with the [idx] syntax to do additional interesting things. E.g. extract a column (but as a "row vector"):

gap> mat{[1..3]}[2];
[ 0, 0, 1 ]
# contrast that with this:
gap> mat{[1..3]}{[2]};
[ [ 0 ], [ 0 ], [ 1 ] ]

Note that while I only discuss extracting submatrices, of course everything also applies to the assignment counterpart:

gap> mat{[1..2]}{[1..2]} := [[1,2],[3,4]];
[ [ 1, 2 ], [ 3, 4 ] ]
gap> mat;
[ [ 1, 2, 4 ], [ 3, 4, -2 ], [ 0, 1, 1 ] ]

The drawback of mat{idx1}{idx2} is that that it works by first extracting the rows of mat corresponding to idx1, and then from each row extracts the entries with indices in idx2. This is sensible and fine if all matrices are "lists of row vectors". But for matrix objects which e.g. store their entries "flat", using this syntax is either not possible, or requires using relatively expensive "proxy row objects".

For access of single entries, we already introduced the syntax m[i,j] as alternative to m[i][j]. I suggest we do something quite similar for the {...} syntax:

gap> mat := [ [ 0, 0, 4 ], [ 1, 0, -2 ], [ 0, 1, 1 ] ];;
gap> mat{[1,3],[2,3]};
[ [ 0, 4 ], [ 1, 1 ] ]

This could even be further extended to emulate mat{idxlist}[idx] and mat[idx]{idxlist}, by allowing one of idx1 and idx2 to be

gap> mat{[1..3], 2};
[ 0, 0, 1 ]
# contrast that with this:
gap> mat{[1..3], [2]};
[ [ 0 ], [ 0 ], [ 1 ] ]

Alternatives

For some years now, GAP also supported passing arbitrary elements as "index" to \[\] methods. Initially we used this for a[[i,j]] as a simple alternative to a[i,j]. However, I don't think much code ever used this.

We could therefore use this feature to implement the above feature with [] instead of {}. Indeed, it just requires a few methods to work for basic lists-of-lists

gap> mat := [ [ 0, 0, 4 ], [ 1, 0, -2 ], [ 0, 1, 1 ] ];;
gap> InstallOtherMethod(\[\,\],[ IsMatrixObj,IsList,IsList], {m,i,j}->m{i}{j});
gap> InstallOtherMethod(\[\,\],[ IsMatrixObj,IsList,IsInt], {m,i,j}->m{i}[j]);
gap> InstallOtherMethod(\[\,\],[ IsMatrixObj,IsInt,IsList], {m,i,j}->m[i]{j});
gap> mat[[1,3],[2,3]];
[ [ 0, 4 ], [ 1, 1 ] ]
gap> mat[[1..3], 2];
[ 0, 0, 1 ]
gap> mat[[1..3], [2]];
[ [ 0 ], [ 0 ], [ 1 ] ]

So this is much simpler to do. However, I am concerned that it might cause problems for people who are e.g. still using the mat[[i,j]] trick.

Th

Implementation

For the mat[idxlist1, idxlist2] variant, I already sketched a basic pure GAP implementation above; of course one would want to install specialized methods for e.g. compressed matrices later on (but that same also holds for the mat{idxlist1, idxlist2} variant).

For the mat{idxlist1, idxlist2} variant, I could sketch how this could be implemented with not that much work required. However, let's first settle which variant we'd prefer, if any at all.

@fingolfin fingolfin changed the title Syntax extension: allow mat{idxlist1, idxist2} as alternative for mat{idx1}{idx2} (OR allow `mat[idx1, Syntax extension: allow mat{idxlist1, idxlist2} as alternative for mat{idx1}{idx2} (OR allow mat[idxlist1, idxlist2]) Mar 29, 2021
@fingolfin fingolfin changed the title Syntax extension: allow mat{idxlist1, idxlist2} as alternative for mat{idx1}{idx2} (OR allow mat[idxlist1, idxlist2]) Syntax extension: allow mat{idxlist1, idxlist2} as alternative for mat{idxlist1}{idxlist2} (OR allow mat[idxlist1, idxlist2]) Mar 29, 2021
@wucas
Copy link
Contributor

wucas commented Jun 2, 2021

I quite like this idea. Tbh I didn't know that this existed until now. I wouldn't use the alternative though as it would be more consistent to have curly brackets. I am curious though, why is is necessary to have list{[x,y]} instead of just list{x,y} why the additional brackets? For matrices this of course would make sense to distinguish row and column indices...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Status: No status
Development

No branches or pull requests

2 participants