#10772: 0**0 = 1 for number fields, matrices, and more
--------------------------------+-------------------------------------------
   Reporter:  mstreng           |       Owner:  AlexGhitza                      
                       
       Type:  defect            |      Status:  new                             
                       
   Priority:  major             |   Milestone:                                  
                       
  Component:  basic arithmetic  |    Keywords:  0, power, pow, number field, 
matrix, convention, python
     Author:  Marco Streng      |    Upstream:  N/A                             
                       
   Reviewer:                    |      Merged:                                  
                       
Work_issues:                    |  
--------------------------------+-------------------------------------------
 Python has the convention {{{x**0 = 1}}} even for {{{x=0}}}. Sage follows
 this convention in some cases, but raises an error in others. This patch
 generalizes Python's convention to
 {{{sage.structure.element.generic_power_c}}}, which includes number field
 elements and matrices. This fixes inconsistent behaviour for matrices and
 a bug for number fields (see examples below). See also
 [http://groups.google.com/group/sage-
 nt/browse_thread/thread/67e53f8e5d5061d2 this discussion].

 Example 1:
 {{{
 sage: K.<a> = NumberField(x^4+x+1)
 sage: r = [ZZ,QQ,RR,CC,int,float,K]
 sage: N = len(r)^2; N
 49
 sage: for a in r:
 ....:     for b in r:
 ....:         try:
 ....:             if a(0)^b(0) != 1:
 ....:                 (a,b,a(0)^b(0))
 ....:                 N = N - 1
 ....:         except (ArithmeticError, TypeError, AttributeError,
 RuntimeError) as e:
 ....:             (a,b,e)
 ....:             N = N - 1
 ....:
 (Integer Ring, Complex Field with 53 bits of precision, NaN - NaN*I)
 (Integer Ring, Number Field in a with defining polynomial x^4 + x + 1,
 ArithmeticError('0^0 is undefined.',))
 (Rational Field, Complex Field with 53 bits of precision, NaN - NaN*I)
 (Rational Field, Number Field in a with defining polynomial x^4 + x + 1,
 ArithmeticError('0^0 is undefined.',))
 Exception RuntimeError: 'maximum recursion depth exceeded in
 __subclasscheck__' in <type 'exceptions.TypeError'> ignored
 Exception RuntimeError: 'maximum recursion depth exceeded in
 __subclasscheck__' in <type 'exceptions.TypeError'> ignored
 Exception RuntimeError: 'maximum recursion depth exceeded while calling a
 Python object' in <type 'exceptions.GeneratorExit'> ignored
 Exception RuntimeError: 'maximum recursion depth exceeded while calling a
 Python object' in <type 'exceptions.GeneratorExit'> ignored
 Exception GeneratorExit in <generator object <genexpr> at 0x6d2e1e0>
 ignored
 (Real Field with 53 bits of precision, Number Field in a with defining
 polynomial x^4 + x + 1, RuntimeError('maximum recursion depth exceeded
 while calling a Python object',))
 (Complex Field with 53 bits of precision, Integer Ring,
 ArithmeticError('0^0 is undefined.',))
 (Complex Field with 53 bits of precision, Rational Field, NaN - NaN*I)
 (Complex Field with 53 bits of precision, Real Field with 53 bits of
 precision, NaN - NaN*I)
 (Complex Field with 53 bits of precision, Complex Field with 53 bits of
 precision, NaN - NaN*I)
 (Complex Field with 53 bits of precision, <type 'int'>,
 ArithmeticError('0^0 is undefined.',))
 (Complex Field with 53 bits of precision, <type 'float'>, NaN - NaN*I)
 (Complex Field with 53 bits of precision, Number Field in a with defining
 polynomial x^4 + x + 1, TypeError(<type
 'sage.rings.complex_number.ComplexNumber'>,))
 (<type 'int'>, Real Field with 53 bits of precision,
 TypeError("unsupported operand type(s) for ** or pow(): 'int' and
 'sage.rings.real_mpfr.RealNumber'",))
 (<type 'int'>, Complex Field with 53 bits of precision,
 AttributeError("'int' object has no attribute 'log'",))
 (<type 'int'>, Number Field in a with defining polynomial x^4 + x + 1,
 TypeError('An embedding into RR or CC must be specified.',))
 (<type 'float'>, Complex Field with 53 bits of precision,
 AttributeError("'float' object has no attribute 'log'",))
 (<type 'float'>, Number Field in a with defining polynomial x^4 + x + 1,
 TypeError('An embedding into RR or CC must be specified.',))
 (Number Field in a with defining polynomial x^4 + x + 1, Integer Ring,
 ArithmeticError('0^0 is undefined.',))
 (Number Field in a with defining polynomial x^4 + x + 1, Rational Field,
 ArithmeticError('0^0 is undefined.',))
 (Number Field in a with defining polynomial x^4 + x + 1, Real Field with
 53 bits of precision, ArithmeticError('0^0 is undefined.',))
 (Number Field in a with defining polynomial x^4 + x + 1, Complex Field
 with 53 bits of precision, TypeError('An embedding into RR or CC must be
 specified.',))
 (Number Field in a with defining polynomial x^4 + x + 1, <type 'int'>,
 ArithmeticError('0^0 is undefined.',))
 (Number Field in a with defining polynomial x^4 + x + 1, <type 'float'>,
 ArithmeticError('0^0 is undefined.',))
 (Number Field in a with defining polynomial x^4 + x + 1, Number Field in a
 with defining polynomial x^4 + x + 1, ArithmeticError('0^0 is
 undefined.',))
 sage: N
 25
 }}}
 So in about half of these cases (25/49) we follow Python's convention
 {{{0^0=1}}} and the other half of the time we get an assortment of errors
 and {{{NaN}}}. This patch removes the 10 occurrences of
 {{{ArithmeticError}}} from the list. Other tickets can deal with the other
 cases.

 Example 2:
 {{{
 sage: a = Matrix([[1,0],[0,0]]); a
 [1 0]
 [0 0]
 b = Matrix([[0,0],[0,0]]); b
 [0 0]
 [0 0]
 sage: a^0
 [1 0]
 [0 1]
 sage: b^0
 ArithmeticError: 0^0 is undefined.
 }}}
 Here Sage finds {{{a!=0}}}, and concludes {{{a^0 = a.parent()(1)}}}. Note
 that the lower right entry of {{{a^0}}} should be {{{0^0}}}, and is
 {{{1}}}.
 Next, Sage finds {{{b==0}}}, and concludes that {{{b^0}}} is illegal. Both
 the upper left and lower right entry of {{{b}}} are the same as the lower
 right entry of {{{a}}}, so the behaviour of {{{a^0}}} and {{{b^0}}} in
 Sage is inconsistent: either both should yield an {{{ArithmeticError}}} or
 neither should.
 The patch adopts Python's convention so that the output of {{{b^0}}} is
 the 2x2 identity matrix and this example becomes consistent.

 Example 3:
 {{{
 sage: K.<a> = NumberField(x^3+x+1)
 sage: K.relativize(1, 'c')
 Number Field in c0 with defining polynomial x^3 + x + 1 over its base
 field
 sage: K.relativize(0, 'c')
 ArithmeticError: 0^0 is undefined.
 }}}
 This is explained by
 {{{
 sage: NumberField(x-1, 'a').power_basis()
 [1]
 sage: NumberField(x, 'a').power_basis()
 ArithmeticError: 0^0 is undefined.
 }}}
 And it gets worse: a number field with defining polynomial {{{x}}} is part
 of the output of {{{K.subfields()}}}
 {{{
 sage: s = K.subfields()
 sage: for i in [1,0]:
 ....:     K.relativize(s[i][1], 'c')
 ....:
 Number Field in c0 with defining polynomial x - a1 over its base field
 ArithmeticError: 0^0 is undefined.
 }}}
 This last example is clearly a bug. An automatic consequence of
 generalizing Python's convention {{{0^0=1}}} is that this bug vanishes.

 Interestingly, the patch adds no code.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/10772>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to