Opened 11 years ago
Closed 11 years ago
#10772 closed defect (fixed)
0**0 = 1 for number fields, matrices, and more
Reported by: | mstreng | Owned by: | AlexGhitza |
---|---|---|---|
Priority: | major | Milestone: | sage-4.7 |
Component: | basic arithmetic | Keywords: | 0, power, pow, number field, matrix, convention, python |
Cc: | Merged in: | sage-4.7.alpha2 | |
Authors: | Marco Streng | Reviewers: | Robert Bradshaw |
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description
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 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.
Attachments (1)
Change History (6)
Changed 11 years ago by
comment:1 Changed 11 years ago by
- Status changed from new to needs_review
comment:2 Changed 11 years ago by
- Status changed from needs_review to positive_review
comment:3 Changed 11 years ago by
- Milestone set to sage-4.7
comment:4 Changed 11 years ago by
- Reviewers set to Robert Bradshaw
comment:5 Changed 11 years ago by
- Merged in set to sage-4.7.alpha2
- Resolution set to fixed
- Status changed from positive_review to closed