Change the default base_ring for matrices from ZZ to QQ

閲覧: 6 回
最初の未読メッセージにスキップ

Jason Grout

未読、
2008/05/15 10:20:562008/05/15
To: sage-...@googlegroups.com
Based on some conversations with linear algebra people and classroom
demonstrations in a linear algebra class, people are confused that when
they create a matrix with matrix(3, range(9)), for example, that the
echelon_form is not the rref output that they get from most any other
program they have ever used, and certainly not what is taught in an
undergrad linear algebra class. There is additional confusion if the
entries specified have a fraction in them; then the matrix defaults to
being over QQ, and the echelon_form functino gives the expected naive
rref! The problem, of course, lies in the matrix defaulting to having
base_ring == ZZ (i.e., non-field).


What do people think about making the default ring for matrices QQ?
Additionally, if the ring R is determined from the elements provided,
then the matrix would be over R.fraction_field(). Of course, the
documentation for matrix() would clearly indicate what is happening if
the ring is not specified.


With this change:

matrix(3, range(9)) would yield a matrix over QQ because the elements
live in ZZ, and then we call ZZ.fraction_field() to get the base ring of
the matrix.

matrix(3,3) would yield a matrix over QQ because QQ would be the default
ring if no entries are specified.

matrix(R,...) would yield a ring over R, since R was explicitly specified.

Thanks,

Jason

mhampton

未読、
2008/05/15 10:33:022008/05/15
To: sage-devel
I think this is a good idea.

-M. Hampton

Jason Grout

未読、
2008/05/15 10:48:262008/05/15
To: sage-...@googlegroups.com
Jason Grout wrote:
> Based on some conversations with linear algebra people and classroom
> demonstrations in a linear algebra class, people are confused that when
> they create a matrix with matrix(3, range(9)), for example, that the
> echelon_form is not the rref output that they get from most any other
> program they have ever used, and certainly not what is taught in an
> undergrad linear algebra class. There is additional confusion if the
> entries specified have a fraction in them; then the matrix defaults to
> being over QQ, and the echelon_form functino gives the expected naive
> rref! The problem, of course, lies in the matrix defaulting to having
> base_ring == ZZ (i.e., non-field).
>
>
> What do people think about making the default ring for matrices QQ?
> Additionally, if the ring R is determined from the elements provided,
> then the matrix would be over R.fraction_field(). Of course, the
> documentation for matrix() would clearly indicate what is happening if
> the ring is not specified.
>


More concisely, this proposal could be worded:

What do people think of making matrix() return a matrix over a field by
default, unless a ring is explicitly specified. The default field would
either be the fraction field of the ring containing the specified
elements, or would be QQ if no elements are specified. This logic would
*only* be applied if a ring is not specified. The documentation of
matrix() would also be changed accordingly.

William Stein

未読、
2008/05/15 10:55:282008/05/15
To: sage-...@googlegroups.com

+1

I suggested this idea. I would never do this is Sage were "just for me",
but Sage isn't. Please keep that in mind when reading the above proposal...

-- William

Harald Schilly

未読、
2008/05/15 11:10:472008/05/15
To: sage-devel
On May 15, 4:20 pm, Jason Grout <jason-s...@creativetrax.com> wrote:
> matrix(3, range(9)) would yield a matrix over QQ

+1

many just use integers as cheap examples but in fact use them over QQ

h

didier deshommes

未読、
2008/05/15 11:15:142008/05/15
To: sage-...@googlegroups.com
On Thu, May 15, 2008 at 10:48 AM, Jason Grout
<jason...@creativetrax.com> wrote:
> More concisely, this proposal could be worded:
>
> What do people think of making matrix() return a matrix over a field by
> default, unless a ring is explicitly specified. The default field would
> either be the fraction field of the ring containing the specified
> elements, or would be QQ if no elements are specified. This logic would
> *only* be applied if a ring is not specified. The documentation of
> matrix() would also be changed accordingly.

Just to make sure I get it:
matrix(1,1,[1]) and matrix(1,2,[Mod(23,4),23]) will be over QQ

To me it looks like the *only* change from the current beahavior will
be that the matrices above will be over QQ, instead of over ZZ or a
generic ring. What other cases am I missing?

didier

kcrisman

未読、
2008/05/15 11:16:492008/05/15
To: sage-devel
I was just discussing this very issue with my chair yesterday. He had
created some wrappers to make using the elementary operations a little
easier for linear algebra students (though I think ended up sticking
with Octave for this semester for unrelated reasons), and then noticed
this with scaling rows under his first implementation.

What happens if you start with something like matrix(3, range(9)), but
then want to turn it into a complex matrix and scale a row by (say) i/
2? Under the current scaling code, this happens:

sage: N.rescale_col(2,i/2)
---------------------------------------------------------------------------
<type 'exceptions.TypeError'> Traceback (most recent call
last)
<snip>
<type 'exceptions.TypeError'>: unable to convert I/2 to a rational

I certainly have no problem with matrices starting off as rational
ones - a great idea! But it doesn't directly affect this sort of
issue - one could still start with a matrix over ZZ and then want to
multiply it later on by 1/2 without using change_ring().

What I am wondering is whether throwing an exception of TypeError
under the current code should be replaced by a try statement first
attempting N.changering(??) . The problem is I have no idea what to
use for ??, because unfortunately i/2 lives in Symbolic Ring, not in
CC, so I can't just put in ??=parent(i/2). It would sort of be beside
of the point of making Sage easier to use in the linear algebra
classroom if we had to explicitly type CC(i/2) everytime we wanted to
use i/2.

In any case, what "should" happen in the scaling context when scaling
by something mathematically legitimate, but not in the ring the matrix
is defined over in Sage?

- kcrisman

(By the way, the wrapper code is nice and well-documented, at
https://sage.math.gordon.edu/home/pub/1/)

Bjake Hammersholt Roune

未読、
2008/05/15 11:21:112008/05/15
To: sage-devel
> [...] people are confused that when
> they create a matrix with matrix(3, range(9)), for example, that the
> echelon_form is not the rref output that they get from most any other
> program they have ever used [...]
> What do people think about making the default ring for matrices QQ?
>
I have no objections to making QQ the defailt ring for matrices.
However, I don't think this resolves the problem entirely.

A part of the confusion stems from echelon_form doing entirely
different things based on the type of argument it gets. I would prefer
echelon_form to always use fractions, and have some other function
avoid the fractions. Another solution I could get behind is for
echelon_form to have a parameter for whether to use fractions, and
have the default be to use them.

Cheers
Bjarke

Jason Grout

未読、
2008/05/15 11:55:262008/05/15
To: sage-...@googlegroups.com
didier deshommes wrote:
> On Thu, May 15, 2008 at 10:48 AM, Jason Grout
> <jason...@creativetrax.com> wrote:
>> More concisely, this proposal could be worded:
>>
>> What do people think of making matrix() return a matrix over a field by
>> default, unless a ring is explicitly specified. The default field would
>> either be the fraction field of the ring containing the specified
>> elements, or would be QQ if no elements are specified. This logic would
>> *only* be applied if a ring is not specified. The documentation of
>> matrix() would also be changed accordingly.
>
> Just to make sure I get it:
> matrix(1,1,[1]) and matrix(1,2,[Mod(23,4),23]) will be over QQ


Currently, your first example yields a matrix over ZZ and the second a
matrix over Ring of integers mod 4.

After the change, your first example would yield a matrix over QQ. The
second would still yield a matrix over Ring of integers mod 4 because
calling fraction_field throws an exception (the ring is not an integral
domain).


>
> To me it looks like the *only* change from the current beahavior will
> be that the matrices above will be over QQ, instead of over ZZ or a
> generic ring. What other cases am I missing?

A matrix over a polynomial ring, for example.

sage: x=polygen(QQ)
sage: matrix([x]).base_ring()
Univariate Polynomial Ring in x over Rational Field

After the change it would be:

sage: x=polygen(QQ)
sage: matrix([x]).base_ring()
Fraction Field of Univariate Polynomial Ring in x over Rational Field


Jason

William Stein

未読、
2008/05/15 11:56:182008/05/15
To: sage-...@googlegroups.com
On Thu, May 15, 2008 at 8:15 AM, didier deshommes <dfde...@gmail.com> wrote:
>
> On Thu, May 15, 2008 at 10:48 AM, Jason Grout
> <jason...@creativetrax.com> wrote:
>> More concisely, this proposal could be worded:
>>
>> What do people think of making matrix() return a matrix over a field by
>> default, unless a ring is explicitly specified. The default field would
>> either be the fraction field of the ring containing the specified
>> elements, or would be QQ if no elements are specified. This logic would
>> *only* be applied if a ring is not specified. The documentation of
>> matrix() would also be changed accordingly.
>
> Just to make sure I get it:
> matrix(1,1,[1]) and

Yes.

> matrix(1,2,[Mod(23,4),23]) will be over QQ

Absolutely not! The behavior of matrix(1,2,[Mod(23,4),23]) will be exactly
like it is now, since Integers(4).fraction_field() doesn't contain Integers(4).

sage: matrix(1,2,[Mod(23,4),23])
[3 3]
sage: parent(matrix(1,2,[Mod(23,4),23]))
Full MatrixSpace of 1 by 2 dense matrices over Ring of integers modulo 4

> To me it looks like the *only* change from the current beahavior will
> be that the matrices above will be over QQ, instead of over ZZ or a
> generic ring. What other cases am I missing?

I don't know. Why would you think that matrix(1,2,[Mod(23,4),23]) would
suddenly be over QQ? That would be very weird.

>
> didier
>
> >
>

--
William Stein
Associate Professor of Mathematics
University of Washington
http://wstein.org

William Stein

未読、
2008/05/15 11:59:322008/05/15
To: sage-...@googlegroups.com

That would work fine. What you're really asking about is making
the function rescale row on an *integer* or rational matrix automatically
change the base ring to complex. I think that is very reasonable and
would be fine with that. It is somewhat orthogonal to Jason's proposal
though.

> Under the current scaling code, this happens:
>
> sage: N.rescale_col(2,i/2)
> ---------------------------------------------------------------------------
> <type 'exceptions.TypeError'> Traceback (most recent call
> last)
> <snip>
> <type 'exceptions.TypeError'>: unable to convert I/2 to a rational
>
> I certainly have no problem with matrices starting off as rational
> ones - a great idea! But it doesn't directly affect this sort of
> issue - one could still start with a matrix over ZZ and then want to
> multiply it later on by 1/2 without using change_ring().

Yep, this is orthogonal. You're just suggesting that scale_row
be improved.

>
> What I am wondering is whether throwing an exception of TypeError
> under the current code should be replaced by a try statement first
> attempting N.changering(??) . The problem is I have no idea what to
> use for ??, because unfortunately i/2 lives in Symbolic Ring, not in
> CC, so I can't just put in ??=parent(i/2).

The Sequence constructor is the canonical answer to this question.
Given any list v of Sage object it will find a canonical place to put
them all:

sage: v = [3, I/2]
sage: w = Sequence(v)
sage: w
[3, I/2]
sage: w.universe()
Symbolic Ring

William Stein

未読、
2008/05/15 12:01:442008/05/15
To: sage-...@googlegroups.com
On Thu, May 15, 2008 at 8:21 AM, Bjake Hammersholt Roune
<bjarke...@gmail.com> wrote:
>
>> [...] people are confused that when
>> they create a matrix with matrix(3, range(9)), for example, that the
>> echelon_form is not the rref output that they get from most any other
>> program they have ever used [...]
>> What do people think about making the default ring for matrices QQ?
>>
> I have no objections to making QQ the defailt ring for matrices.

I do. That's definitely *not* the proposal. The proposal is to make the
base ring the fraction field of the canonical ring in which the list of
entries live, if that fraction field is defined. QQ was just an example.

> However, I don't think this resolves the problem entirely.
>
> A part of the confusion stems from echelon_form doing entirely
> different things based on the type of argument it gets. I would prefer
> echelon_form to always use fractions, and have some other function
> avoid the fractions. Another solution I could get behind is for
> echelon_form to have a parameter for whether to use fractions, and
> have the default be to use them.

Echelon form over a field is just a natural special case of a more
general notion of echelon forms over rings. So from an algebraist's
point of view echelon form does *exactly* the same thing over ZZ
or QQ, relative to the ring over which we are working.

-- William

Jason Grout

未読、
2008/05/15 12:02:582008/05/15
To: sage-...@googlegroups.com


I'm not sure I understand the problem. Here is an example session in
Sage 3.0.1. Can you change this to illustrate what you mean?

sage: m=matrix(3,3,range(9))
sage: n = m*(i/2)
sage: n.parent()
Full MatrixSpace of 3 by 3 dense matrices over Symbolic Ring
sage: n

[ 0 I/2 I]
[3*I/2 2*I 5*I/2]
[ 3*I 7*I/2 4*I]
sage: m2 = m/i
sage: m2.parent()
Full MatrixSpace of 3 by 3 dense matrices over Symbolic Ring
sage: m2

[ 0 -1*I -2*I]
[-3*I -4*I -5*I]
[-6*I -7*I -8*I]


Thanks,

Jason

Nick Alexander

未読、
2008/05/15 12:04:572008/05/15
To: sage-...@googlegroups.com
> What do people think about making the default ring for matrices QQ?

I'm not certain why I dislike this so much, but I vote -1. I think
it's because I understand the Sage coercion model well and since I
know what to expect, I appreciate my data starting at the "lowest
level of the model".

I would prefer changing echelon_form over an integral domain to work
over the fraction field and reserve hermite_normal_form for PIDs.

Nick

William Stein

未読、
2008/05/15 12:09:062008/05/15
To: sage-...@googlegroups.com

We could do this. It would

1. Require rewriting code in modules/*.py to
call different functions depending on whether the base ring
is a field or not.

2. Break compatibility with Magma where EchelonForm is the
same as in Sage over ZZ (not a priori bad.)

3. Probably other things would break, but I'm not sure where.
It's likely doctest would uncover what, hopefully. Code
would also have to be changed in matrix_integer_dense,
obviously...

-- William

Jason Grout

未読、
2008/05/15 12:06:192008/05/15
To: sage-...@googlegroups.com

I think the fundamental problem among the people I have talked with was
that they never thought of a "matrix over ZZ". Instead they always
really thought of a "matrix over RR" with entries in ZZ. So I think the
proposal addresses the problem well. Those people that don't want to
worry about matrices over non-fields don't have to deal with them, while
those people that do work with matrices over non-fields can get them easily.

Thanks,

Jason

Jason Grout

未読、
2008/05/15 12:10:302008/05/15
To: sage-...@googlegroups.com
William Stein wrote:
> On Thu, May 15, 2008 at 8:21 AM, Bjake Hammersholt Roune
> <bjarke...@gmail.com> wrote:
>>> [...] people are confused that when
>>> they create a matrix with matrix(3, range(9)), for example, that the
>>> echelon_form is not the rref output that they get from most any other
>>> program they have ever used [...]
>>> What do people think about making the default ring for matrices QQ?
>>>
>> I have no objections to making QQ the defailt ring for matrices.
>
> I do. That's definitely *not* the proposal. The proposal is to make the
> base ring the fraction field of the canonical ring in which the list of
> entries live, if that fraction field is defined. QQ was just an example.


The other part of the proposal is making it so that a matrix without a
ring specified and without entries specified would default to being over
QQ, i.e., we would have:

sage: matrix(3,3).parent()
Rational Field

Currently this returns a matrix over ZZ.

In that sense, the default ring for matrices would be QQ instead of ZZ
after the change.

Thanks,

Jason

kcrisman

未読、
2008/05/15 12:32:272008/05/15
To: sage-devel

> I'm not sure I understand the problem.  Here is an example session in
> Sage 3.0.1.  Can you change this to illustrate what you mean?
>

Sorry, Jason, the example was sort of buried in my post. Here is a
concise version.

sage: A=matrix(QQ,3,range(9))
sage: A

[0 1 2]
[3 4 5]
[6 7 8]
sage: A.rescale_row(2,i/2)
---------------------------------------------------------------------------
<type 'exceptions.TypeError'> Traceback (most recent call
last)
<snip>
<type 'exceptions.TypeError'>: unable to convert I/2 to a rational

William is right about it being (nearly) orthogonal - the common
projection is to use in pedagogical circumstances.

This is now http://trac.sagemath.org/sage_trac/ticket/3212.

Nils Bruin

未読、
2008/05/15 14:48:482008/05/15
To: sage-devel
-1. While I agree that defaulting to matrices over QQ rather than over
ZZ would lead to more expected behaviour for most users, I don't see
how the rule for changing the base ring can be made both consistent
and cheap.

Imagine R1 = QQ[x,y]/(x^2+y^2-1). Then FieldOfFractions(R1) is well-
defined, so one would expect that
matrix([x]) would be over the field of fractions.

If R2=Q[x,y]/( x^2-y^2), FieldOfFractions(R2) does not exist. Deciding
whether FieldOfFractions(Ri) exists is a fairly expensive operation in
these cases.

I think special-casing matrix([ZZ(1)]) etc. is a bad idea. You would
need a method R.has_an_obvious_field_of_fractions() on rings to both
deal with ZZ and avoid expensive operations for R1 and R2 above.

David Roe

未読、
2008/05/15 15:40:492008/05/15
To: sage-...@googlegroups.com
I agree with Nick here. If we want to change the default behavior of
some functions so that they work the same as over the fraction field,
that's fine. But don't add a call to fraction field to the
constructor. ZZ is the initial object in the category of rings.
That's a good reason for it to be the default base ring.
David

Jason Grout

未読、
2008/05/15 15:49:202008/05/15
To: sage-...@googlegroups.com
Nils Bruin wrote:
> -1. While I agree that defaulting to matrices over QQ rather than over
> ZZ would lead to more expected behaviour for most users, I don't see
> how the rule for changing the base ring can be made both consistent
> and cheap.
>
> Imagine R1 = QQ[x,y]/(x^2+y^2-1). Then FieldOfFractions(R1) is well-
> defined, so one would expect that
> matrix([x]) would be over the field of fractions.
>
> If R2=Q[x,y]/( x^2-y^2), FieldOfFractions(R2) does not exist. Deciding
> whether FieldOfFractions(Ri) exists is a fairly expensive operation in
> these cases.


Good points. In the current case, I don't think the speed issues affect
us because apparently sage can't create the field of fractions of the
first case, unless I'm doing this wrong:


sage: R.<x,y>=QQ['x','y']
sage: Frac(R.quo(x^2+y^2-1))
---------------------------------------------------------------------------
<type 'exceptions.NotImplementedError'> Traceback (most recent call last)

/home/grout/<ipython console> in <module>()

/home/grout/sage/local/lib/python2.5/site-packages/sage/rings/fraction_field.py
in FractionField(R, names)
104 if not ring.is_Ring(R):
105 raise TypeError, "R must be a ring"
--> 106 if not R.is_integral_domain():
107 raise TypeError, "R must be an integral domain."
108 return R.fraction_field()

/home/grout/sage/local/lib/python2.5/site-packages/sage/rings/quotient_ring.py
in is_integral_domain(self)
351
352 """
--> 353 return self.defining_ideal().is_prime()
354
355 def cover_ring(self):

/home/grout/sage/local/lib/python2.5/site-packages/sage/rings/ideal.py
in is_prime(self)
402 NotImplementedError
403 """
--> 404 raise NotImplementedError
405
406 def is_principal(self):

<type 'exceptions.NotImplementedError'>:
sage: Frac(R.quo(x^2-y^2))
---------------------------------------------------------------------------
<type 'exceptions.NotImplementedError'> Traceback (most recent call last)

/home/grout/<ipython console> in <module>()

/home/grout/sage/local/lib/python2.5/site-packages/sage/rings/fraction_field.py
in FractionField(R, names)
104 if not ring.is_Ring(R):
105 raise TypeError, "R must be a ring"
--> 106 if not R.is_integral_domain():
107 raise TypeError, "R must be an integral domain."
108 return R.fraction_field()

/home/grout/sage/local/lib/python2.5/site-packages/sage/rings/quotient_ring.py
in is_integral_domain(self)
351
352 """
--> 353 return self.defining_ideal().is_prime()
354
355 def cover_ring(self):

/home/grout/sage/local/lib/python2.5/site-packages/sage/rings/ideal.py
in is_prime(self)
402 NotImplementedError
403 """
--> 404 raise NotImplementedError
405
406 def is_principal(self):

<type 'exceptions.NotImplementedError'>:

Of course, we shouldn't rely on Sage not having functionality
(especially if we point it out the lack of said functionality, as it is
quite likely to be fixed soon!).

If it is too expensive in general, then maybe we can just special-case
the ZZ->QQ conversion. My guess is that this would take care of most
common scenarios.

Is that special case what you are referring to below?


>
> I think special-casing matrix([ZZ(1)]) etc. is a bad idea. You would
> need a method R.has_an_obvious_field_of_fractions() on rings to both
> deal with ZZ and avoid expensive operations for R1 and R2 above.

> --~--~---------~--~----~------------~-------~--~----~


Thanks,

Jason

Bjake Hammersholt Roune

未読、
2008/05/15 17:46:232008/05/15
To: sage-devel
> >> What do people think about making the default ring for matrices QQ?
>
> > I have no objections to making QQ the defailt ring for matrices.
>
> I do. That's definitely *not* the proposal. The proposal is to make the
> base ring the fraction field of the canonical ring in which the list of
> entries live, if that fraction field is defined. QQ was just an example.
>
Yes, we already agree, QQ is just an example. ;)

> > A part of the confusion stems from echelon_form doing entirely
> > different things based on the type of argument it gets. I would prefer
> > echelon_form to always use fractions, and have some other function
> > avoid the fractions. Another solution I could get behind is for
> > echelon_form to have a parameter for whether to use fractions, and
> > have the default be to use them.
>
> Echelon form over a field is just a natural special case of a more
> general notion of echelon forms over rings. So from an algebraist's
> point of view echelon form does *exactly* the same thing over ZZ
> or QQ, relative to the ring over which we are working.
>
Yes - the confusing part is the dependence on the ring. My guess is
that echelon_form will more often be used by people expecting to get
fractions than not, and the people who know the difference will be in
a better position to figure out what is happening.

Cheers
Bjarke

Robert Bradshaw

未読、
2008/05/15 19:04:242008/05/15
To: sage-...@googlegroups.com

I would second this idea, I like it much better than matrix(3,range
(9) being over Q. I think that's the way it used to be. It seems odd
to make matrices by default over their fraction fields (if they
exist)--other than echelon form is there any other case that one
wants this. This could slow things down a lot too--matrices over QQ
have some overhead (only O(n^2)) over matrices over ZZ, but there is
a huge difference in performance for Z[x] and Frac(Z[x]). Also, then

sage: matrix(3, range(9).charpoly('x')

would return a polynomial over QQ rather than ZZ which I think is odd
and less efficient.

- Robert

William Stein

未読、
2008/05/15 19:13:002008/05/15
To: sage-...@googlegroups.com

I think based on this whole discussion:

(1) matrix(3, range(9)) returning a matrix over QQ is *definitely* out.
If there is a trac ticket it should be marked invalid.

(2) The echelon_form command should be changed to always return
a result over the fraction field, thus making a break with Magma.

(3) Rewrite all the rest of code in Sage that depends on the current
behavior of echelon_form. This code will have to call hermite_form
instead. E.g., code in modules/free_module.py will have to change.
Code in a.kernel() will have to change, etc.

Doing (1), (2) is almost trivial. Do (3) will be a little more difficult, and
could introduce bugs.

I'm very much against
a.echelon_form(...)
being over ZZ or QQ depending on arguments to echelon_form.
If for no other reason than even if one does that then it will
still be necessary to do all of (3) above.

I've cc'd David Kohel on this email, since he is 100% responsible
for the current state of affairs regarding echelon form, and I want
to give him a chance to speak up before we do (1)-(3) above.

-- William

全員に返信
投稿者に返信
転送
新着メール 0 件