Initializing a matrix using the entries keyword, but with a partial function

12 views
Skip to first unread message

Peleg Michaeli

unread,
Dec 21, 2016, 7:30:33 AM12/21/16
to sage-support
The matrix (or Matrix) documentation reads:

   INPUT:

   
* "ring" -- the base ring for the entries of the matrix.

   
* "nrows" -- the number of rows in the matrix.

   
* "ncols" -- the number of columns in the matrix.

   
* "sparse" -- create a sparse matrix. This defaults to "True"
     
when the entries are given as a dictionary, otherwise defaults to
     
"False".

   
* "entries" -- see examples below.


However, the examples below do not give any example of using "entries" as a keyword argument. And, indeed, passing `entries=...` in the call of Matrix raises TypeError.

I can overcome this using positional arguments only.  Here is a working example:

sage: def f(i, j):
....:     return i+j
....:
sage
: matrix(QQ, 3, 3, f)

[0 1 2]
[1 2 3]
[2 3 4]

But if I am passing a partial function, this does not work any more:

sage: def f(i, j, x):
....:     return (i + j) * x
....:
sage
: import functools
sage
: def f(i, j, x):
....:     return (i + j) * x
....:
sage
: g = functools.partial(f, x=7)
sage
: g(0, 1)
7
sage
: matrix(QQ, 3, 3, g)
Traceback (most recent call last):
 
File "<ipython-input-131-5bd380f06a54>", line 1, in <module>
    matrix
(QQ, Integer(3), Integer(3), g)
 
File "sage/matrix/constructor.pyx", line 794, in sage.matrix.constructor.MatrixFactory.__call__ (build/cythonized/sage/matrix/constructor.c:7154)
   
return MatrixSpace(ring, nrows, ncols, sparse=sparse)(entries)
 
File "/home/peleg/sage/local/lib/python2.7/site-packages/sage/matrix/matrix_space.py", line 531, in __call__
   
return self.matrix(entries, coerce, copy)
 
File "/home/peleg/sage/local/lib/python2.7/site-packages/sage/matrix/matrix_space.py", line 1488, in matrix
   
return MC(self, x, copy=copy, coerce=coerce)
 
File "sage/matrix/matrix_rational_dense.pyx", line 199, in sage.matrix.matrix_rational_dense.Matrix_rational_dense.__init__ (build/cythonized/sage/matrix/matrix_rational_dense.c:4734)
   
raise TypeError("entries must be coercible to a list or integer")
TypeError: entries must be coercible to a list or integer


How can I make this work?

Vincent Delecroix

unread,
Dec 21, 2016, 7:42:00 AM12/21/16
to sage-s...@googlegroups.com
Hi Peleg,

It would be better if matrix would do a type check for partial function.
Currently it does not, the relevant line is

{{{
if isinstance(arg, (types.FunctionType, types.LambdaType,
types.MethodType)):
}}}

in sage/matrix/constructor.pyx the function MatrixFactory.

Concerning a direct solution, you can cheat with

sage: matrix(QQ, 3, 3, lambda i,j: g(i,j))

Or even more directly with

sage: matrix(QQ, 3, 3, lambda i,j: f(i,j,7))

Vincent

Le 21/12/2016 à 13:29, Peleg Michaeli a écrit :
> The matrix (or Matrix) documentation reads:
>
> INPUT:
>
> * "ring" -- the base ring for the entries of the matrix.
>
> * "nrows" -- the number of rows in the matrix.
>
> * "ncols" -- the number of columns in the matrix.
>
> * "sparse" -- create a sparse matrix. This defaults to "True"
> when the entries are given as a dictionary, otherwise defaults to
> "False".
>
> * "entries" -- see examples below.
>
>
> However, the examples below do not give any example of using "entries" as a *keyword
> argument*. And, indeed, passing `entries=...` in the call of Matrix raises
> TypeError.
>
> I can overcome this using positional arguments only. Here is a working
> example:
>
> sage: def f(i, j):
> ....: return i+j
> ....:
> sage: matrix(QQ, 3, 3, f)
>
> [0 1 2]
> [1 2 3]
> [2 3 4]
>
> But if I am passing a *partial function*, this does not work any more:

Peleg Michaeli

unread,
Dec 21, 2016, 7:57:38 AM12/21/16
to sage-support
Hi Vincent,

Great, thanks!
I'd say that the docstring should be amended as well, don't you think? (As the keyword argument `entries` does not exist)


Peleg.

Vincent Delecroix

unread,
Dec 21, 2016, 8:05:28 AM12/21/16
to sage-s...@googlegroups.com
True, there is no such keyword in the (relatively complicated) signature

def __call__(self, *Args, ring=None, nrows=None, ncols=None, sparse=None):

However, it is the kind of argument you really want to input to the
function! Note the equivalence of the output of

sage: matrix(QQ, 3, 3, entries)

sage: matrix(entries, ring=QQ, nrows=3, ncols=3)

In the documentation, you complain about the INPUT section. It is
intended to describe the order of the arguments (and not necessarily
their names). If you feel like we should have a named argument entries
it can easily be added.

Vincent
Reply all
Reply to author
Forward
0 new messages