Hi Saul,
On 2014-01-23, Saul Schleimer <
sau...@gmail.com> wrote:
> It seems to me that this violates the principle of "least surprise": if I
> have a unit in a ring, and I invert it, I can reasonably expect answer to
> be a unit, in that ring...
Yes and no.
If you have an integral domain, you can reasonably expect the answer to be an
element of the fraction field: 1/1 naturally belongs to QQ, and it would be
very confusing if the type of 1/n would depend on n: Think of writing a program
that needs special cases all over the place.
But in your example, it is a matrix algebra, hence, no integral domain.
In this case, it might indeed be reasonable to expect the inverse of a
unit to stay in the same ring.
I think the discussion whether or not the algebraic structure (aka
"Parent",which means "object in a subcategory of the category of sets)
containing the result of arithmetic operations should depend
on the operands or *only* on the parents containing the operands took
place before I joined Sage. However, I can give some reasons for letting
the resulting parent only depend on the operand's parents:
- Sage's coercion system ("automatic conversion into a suitable parent
when doing arithmetic") relies on morphisms, which I think is the right
thing to do for providing a mathematical fundament to coercion (which goes
way beyond the "automatic type conversion" known from the C
programming language). Hence, an arithmetic operation such as *
involving parents R and S is modelled as a morphism (in an appropriate
category) RxS --> T, for another parent T (multiplication of elements
of R and S happens after mapping both elements to T). Of course, this
will not always be possible, there may only be a partial map or there
may be no canonical choice of a morphism. In that case, Sage would
normally refuse to do the multiplication (but I guess the user can
force it by doing explicit rather than implicit conversions).
Long paragraph in a nutshell: Sage's arithmetic system largely relies
on morphisms, and hence it would be against some of Sage's fundaments
to make the result of an arithmetic operation live in different parents,
depending on the operands.
- Imagine you have a huge number of arithemtic operations to do, with
operands that all belong to a fixed pair of parents. Now think what
happens if for *each* pair of operands you have to do (expensive)
tests before being able to choose the appropriate algorithm: It's a
waste of time! Instead, you do the expensive test *once* (namely only
for the fixed pair of parents), resulting in a single action, and
then you feed this single action with a zillion of operand pairs.
That's a lot more efficient than creation zillions of actions,
namely one for each operand pair!
Example for the second point:
sage: R = ZZ[x]
sage: S = QQ
sage: A = R.get_action(S, operator.mul)
sage: A
Right scalar multiplication by Rational Field on Univariate Polynomial
Ring in x over Integer Ring
sage: A.codomain()
Univariate Polynomial Ring in x over Rational Field
Hence, you have one action, taking a rational number and a polynomial
over the integers, and returning a polynomial over the rationals. And
this single action is in fact what Sage uses internally, for all
elements of R and S. So, when you do
sage: r = R.random_element(); r
x^2 - 8*x + 2
sage: s = S.random_element(); s
-1/2
sage: r*s
-1/2*x^2 + 4*x - 1
then internally Sage just looks up A (it is cached) and does
sage: A(r,s)
-1/2*x^2 + 4*x - 1
Best regards,
Simon