On Jan 18, 2008 2:53 PM, David R. Kohel <[EMAIL PROTECTED]> wrote: > Hi William, > > > > I don't like the coercion into Mat(QQ,2); I think this will give serious > > > problems in any general system: > > > > > > sage: type(A.inverse()) > > > <type 'sage.matrix.matrix_rational_dense.Matrix_rational_dense'> > > > sage: type(A) > > > <type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'> > > > > Why exactly is that a serious problem? > > I'm afraid that some innocuous call to the inverse of an element will > propagate with + and * of elements to yield unexpected, mathematically > incorrect results or a crash at some point which is far from the initial > point, which will make buggy code. > > Note that this definition of x.inverse() is also not consistent with > the SAGE conventions for other rings (e.g. integers or polynomials).
A quick note here: currently no matrices are ring elements in Sage. Actually, though how is it not consistent? If x is a polynomial or an integer, then x^(-1) yields something that may be in another ring with the property that x*x^(-1) = 1: sage: x = polygen(QQ,'x') sage: (1+x)^(-1) 1/(x + 1) > > > Certainly (like in Magma) 1/x could be defined to create the field of > > > fractions > > > or a larger field, but I would assert that x^-1, and certainly > > > x.inverse() should > > > not create a structure which doesn't already exist. > > Magma is not at all consistent. Since Allan is not an algebraist, he > often puts in place whatever he thinks should be in place for a given > ring. This looks like a convention: > > > PS<q> := PowerSeriesRing(QQ); > > Parent(1/q); > Laurent series field in $.1 over Rational Field > > Parent(q/(q + q^2)); > Laurent series field in $.1 over Rational Field > > q^-1; > > >> q^-1; > ^ > Runtime error in '^': Argument 2 is not invertible for negative power > > But then for "convenience of users", division by a unit is carried out > in the same ring: > > > Parent(1/(1+q)); > Power series ring in q over Rational Field > > In writing code, it becomes necessary to test the invertibility of the > denominator in order to know what the output type will be. > > Moreover, the conventions for power series ring are not the same for > p-adic rings, so writing generic code becomes difficult. > > I strongly suggest that some fixed convention exists for all rings, > before things become too muddled. I prefer: > > 1/x = constructor for the ring of fractions Yes. > x^-1 = x.inverse() the inverse in the ring (error for non-units) I'm not so sure. > If you think SAGE should be more lenient with the notation x^-1, then I do. Not allowing 3^(-1) seems too mean to me. > 1/x = x^-1 constructor for the ring of fractions > x.inverse() the inverse in the ring > But x.inverse() should not return an inverse if one does not exist; > this should be reserved for the operation on units in the ring or > give an error. I really want to be able to do: I would be OK with this, but I think the name should be more explicit, e.g., x.inverse_in_parent() > > try: > y = x.inverse() > except ValueError ... > > On further thought, I would use this example to argue that x^-1 should > be x.inverse() and not 1/x: > > sage: x = 2 > sage: for i in range(-3,3): > ....: type(x^i) > ....: > <type 'sage.rings.rational.Rational'> > <type 'sage.rings.rational.Rational'> > <type 'sage.rings.rational.Rational'> > <type 'sage.rings.integer.Integer'> > <type 'sage.rings.integer.Integer'> > <type 'sage.rings.integer.Integer'> > > Again, to ensure in generic code that one doesn't leave the closed > operations in a ring, one would need to code for special cases where > i < 0 and i non-negative. > > In general I am opposed to functions returning values of different > types depending on the values of the arguments, unless there is some > overriding reason and convention in place for doing otherwise. Same here. And in the case of exponentiation I think there is such an overriding reason and convention in place for doing otherwise. > Let me also point out another useful constructor, which Magma gets > wrong. At Michael Stoll's request, an ExactDivision function was > created to solve the problem that x/y is (supposed to be) a > constructor for the field of fractions but one often wants the > result, if it exists, division exists in a ring (say an integral > domain). Thus there exists this completely general intrinsic: > > > ExactQuotient; > Intrinsic 'ExactQuotient' > > Signatures: > > (<RngElt> x, <RngElt> y) -> BoolElt, RngElt > > Return the quotient x div y, assuming y divides x exactly. > Is that supposed to raise an error if y does not divide x? Or does it return False and undefined in that case. What an unpleasant function. > Unfortunately, it was never fully implemented, so if you try to apply > it to anything but, say, integers or polynomials, you find it doesn't > exist: > > > ExactQuotient(q,q+q^2); > > >> ExactQuotient(q,q+q^2); > ^ > Runtime error in 'ExactQuotient': Operation not available for this ring > > Here q is the power series generator defined above. Note that it does > seem to have been fixed up for general fields: > > > PS<t> := LaurentSeriesRing(QQ); > > ExactQuotient(t,t+t^2); > 1 - t + t^2 - t^3 + t^4 - t^5 + t^6 - t^7 + t^8 - t^9 + t^10 - t^11 + t^12 - > t^13 + t^14 - t^15 + t^16 - t^17 + t^18 - t^19 + O(t^20) > > ExactQuotient(1/2,1/3); > 3/2 > > PS<t> := LaurentSeriesRing(QQ); > > ExactQuotient(t,t+t^2); > 1 - t + t^2 - t^3 + t^4 - t^5 + t^6 - t^7 + t^8 - t^9 + t^10 - t^11 + t^12 - > t^13 + t^14 - t^15 + t^16 - t^17 + t^18 - t^19 + O(t^20) > > ExactQuotient(1/2,1/3); > 3/2 > > But one needs to have ExactQuotient defined for all rings, or you can't > use it in generic code. > > Even if the denominator is a unit, x/y is often more efficient than > doing x * 1/y. Thus, I would add to the list of generic ring functions > (at least for integral domains), a member function > > x.exact_division(y) > > to those which should be defined for ring (or integral domain) elements. This seems much more like a case where one should use a divisibility test function that also returns the quotient in the case when divisibility holds and None otherwise, e.g., t, quo = x.divides(y, with_quotient=True) Alternatively, I could see doing x.exactly_divided_by(y) and have it raises a ValueError if the division fails. I think x.exact_division(y) is a poor choice of name readability wise, since it is unclear if it is x/y or y/x. > Note that even though a field of fractions exists, there may not be > an injective image of the ring. Take for example Z/26Z with elements > x = 7 and y = 2. Then x/y is well-defined in Z/26Z \otimes Z[1/2], > which is canonically isomorphic to Z/13Z. In fact there are two fields > of fractions -- both of which are noninjective homomorphic images. When things are not well-defined don't define them. That's been a general philosophy all over in Sage. > Even if the field of fractions is mathematically unique, it might not > be computationally unique. Then you make a choice and document it, and make sure there is a canical map in one direction only. Anyways, are there any mathematical objects that are "computationally unique"? > A few years back Claus Fieker introduced > in Magma a field of fractions of an order. It's of course isomorphic > to the number field, but arithmetic is with respect to a basis of > the order rather than a power basis of the number field. > > Another example is the field of fractions of ZZ[x]. Magma has both > function fields over ZZ and over QQ, and in many applications that > over ZZ is faster. > > In short, I think 1/x and x/y are useful as constructors and all users > should be aware that they are constructors for a field of fractions > (equal to the field itself if the parent of x or y is already one), > which may involve some choice. The "/" symbol is already special in > Python, so users already have to be aware (or beware) of its special > definition. > > However, this special convention shouldn't be carried too far and > confused with or replace a well-defined inverse operator on units. > > Whatever the conventions, SAGE has a unique opportunity to get it right > by learning from the mistakes of other systems, and defining and > enforcing uniform standards that can be relied upon across the system. > > There were many instances where Magma changed the rules for automatic > coercion for convenience of users, to the point of overstepping the > bounds of rigor, and had to pull back when users or system code would > break. Magma's rules for automatic coercions, etc., are -- at least in all my memory of writing for the system -- almost completely ad hoc, at least from the programming point of view -- my impression is that they get enforced by people in Sydney deciding on things and pushing those decisions tediously through millions of lines of code. Python's rules for coercion are really really stupid from a math point of view (basically coerce to the left operand type), but they are fine for most programming tasks and easy to explain. Sage's rules are most certainly not ad hoc, since they are enforced by the generic code in the file coerce.pyx. We had some clear simple rules that I could explain in a few sentences that I came up with a year ago, and those were enforced down through the system. Unfortunately, it turned out that actually _using_ sage under those coercion rules -- though enough for me -- drove a lot of people totally nuts -- it was just too painful. So a huge amount of brainstorming and prototypes went into that problem and now we have the current coercion system. And I can't even explain easily how it works or what the rules are, which actually really annoying. But it does work very well in practice. > The problem is to maintain logically consistent rules which > balance rigor and ease of use. True. But the balance *must* be much more on ease of use, even more than it already has been, or very few people would use Sage and Sage would be irrelevant, which might be fine for some people but not for me since I appreciate the value of having a lot of Sage users. But this is really a perhaps boring digression from the real discussion. -- William Stein Associate Professor of Mathematics University of Washington http://wstein.org --~--~---------~--~----~------------~-------~--~----~ To post to this group, send email to sage-devel@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sage-devel URLs: http://www.sagemath.org -~----------~----~----~----~------~----~------~--~---