#7580: bugs in infinite polynomial ring
-----------------------+----------------------------------------------------
Reporter: was | Owner: SimonKing
Type: defect | Status: needs_review
Priority: major | Milestone: sage-4.3
Component: algebra | Keywords: infinite polynomial ring coercion
Work_issues: | Author: Simon King
Upstream: N/A | Reviewer:
Merged: |
-----------------------+----------------------------------------------------
Changes (by newvalueoldvalue):
* cc: nthiery (added)
* keywords: => infinite polynomial ring coercion
* status: needs_work => needs_review
* author: => Simon King
Comment:
Hi!
Cc to Nicolas, since it partially concerns categories/functors.
We proudly present a major revision of Infinite Polynomial Rings; the
patch bomb is relative to sage-4.3.alpha1.
First of all, it fixes the bugs that William stated in the ticket
description.
Second, it is now possible to use ''any'' commutative base ring; the
restriction of using fields is now moved to the {{{groebner_basis()}}}
method.
Third, and that's the biggest change: It now uses the strength of Sage's
coercion machinery in pushout.py. I hope I did not overdo my use of it...
'''__Bug fixes__'''
Answer to William's failing examples:
1.
{{{
sage: X.<x,y> = InfinitePolynomialRing(QQ)
sage: x[2^31]
---------------------------------------------------------------------------
IndexError Traceback (most recent call
last)
...
IndexError: Variable index is too big - consider using the sparse
implementation
}}}
I think that error message is clearer, and it gives a good advice...
{{{
sage: x[100]
x_100
}}}
So, that bug is gone.
2.
{{{
sage: X.<a,b> = InfinitePolynomialRing(QQ)
sage: a[100]
a_100
sage: a[2/3]
---------------------------------------------------------------------------
ValueError Traceback (most recent call
last)
...
ValueError: The index (= 2/3) must be an integer
sage: a[Mod(2,3)]
a_2
sage: X.<a,b> = InfinitePolynomialRing(QQ)
sage: a[0]
a_0
sage: a['0+5']
---------------------------------------------------------------------------
ValueError Traceback (most recent call
last)
...
ValueError: invalid literal for int() with base 10: '0+5'
}}}
'''__Extensions__'''
1.
The variable names can be any alphanumeric string. The base ring can be
any commutative ring. Note the rhyme...
{{{
sage: A.<t> = ZZ[]
sage: X.<alpha,beta>= InfinitePolynomialRing(A)
sage: X
Infinite polynomial ring in alpha, beta over Univariate Polynomial Ring in
t over Integer Ring
sage: 1/2*alpha[2]*t^3+alpha[1]*beta[4]^2
1/2*t^3*alpha_2 + alpha_1*beta_4^2
sage: latex(_)
(\frac{1}{2} t^{3}) \alpha_{2} + \alpha_{1}\beta_{4}^{2}
}}}
1.1.
Some words on the implementation for arbitrary base rings: Working on it,
I discovered some bugs in {{{MPolynomialRing_polydict}}}, as I reported on
[http://groups.google.com/group/sage-
devel/browse_thread/thread/b69ba8e631bd3bf7/bc6ee7bdccf26ee1?lnk=gst&q=FakeRing#bc6ee7bdccf26ee1
sage-devel]. However, there was no answer (so, apparently no interest).
Therefore I decided to just work around these bugs. One issue is to
evaluate a string 'x_2*t', if 'x_2' is a variable in an infinite
polynomial ring and 't' is a variable in the base ring. gens_dict() would
at most know about 'x_2' --- but with the additional complication that
there is no fixed finite list of variables for the infinite polynomial
ring.
__Solution__
I introduced a dictionary-like class {{{InfiniteGenDict}}}, that returns a
variable of an infinite polynomial ring, given its name.
And I introduced a class {{{GenDictWithBasering}}} that returns a variable
of the ring or its base-ring or the base-ring of its base-ring or... The
first answer wins.
I think that this class might be of general use, e.g., for fixing issues
in {{{MPolynomialRing_polydict}}}.
Examples:
{{{
sage: R.<a,b> = InfinitePolynomialRing(QQ['t'])
sage: R('a_0*t')
t*a_0
sage: _.parent()
Infinite polynomial ring in a, b over Univariate Polynomial Ring in t over
Rational Field
sage: R._P
Multivariate Polynomial Ring in a_1, a_0, b_1, b_0 over Univariate
Polynomial Ring in t over Rational Field
sage: type(_)
<class
'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_domain'>
sage: R._P('a_0*t')
---------------------------------------------------------------------------
TypeError Traceback (most recent call
last)
...
TypeError: unable to convert string
}}}
This is what I mean by "bug in {{{MPolynomialRing_polydict}}}"! And this
is why I use string evaluation as a last resort, since this works much
better:
{{{
sage: R.gens_dict()
GenDict of Infinite polynomial ring in a, b over Univariate Polynomial
Ring in t over Rational Field
sage: _._D
[InfiniteGenDict defined by ['a', 'b'], {'t': t}, {'1': 1}]
sage: sage_eval('a_0*t',R.gens_dict())
t*a_0
sage: R.gens_dict()['t'].parent()
Univariate Polynomial Ring in t over Rational Field
sage: R.gens_dict()['a_4'].parent()
Infinite polynomial ring in a, b over Univariate Polynomial Ring in t over
Rational Field
}}}
I think that {{{GenDictWithBasering}}} can provide a solution for the
trouble with {{{MPolynomialRing_polydict}}}. As I showed, direct string
conversion was flawed. But the following works:
{{{
sage: from sage.rings.polynomial.infinite_polynomial_ring import
GenDictWithBasering
sage: D = GenDictWithBasering(R._P, R._P.gens_dict())
sage: sage_eval('a_0*t',D)
t*a_0
sage: _.parent()
Multivariate Polynomial Ring in a_1, a_0, b_1, b_0 over Univariate
Polynomial Ring in t over Rational Field
}}}
2.
It is now possible to construct quotient rings of infinite polynomial
rings by symmetric ideals. Here, of course, it is required to have a field
as base ring (for Groebner bases)
{{{
sage: R.<x> = InfinitePolynomialRing(QQ)
sage: I = R.ideal([x[1]*x[2] + x[3]])
}}}
Note that ``I`` is not a symmetric Groebner basis (the symmetric Groebner
basis of a principal symmetric ideal is generally not formed by a single
polynomial!):
{{{
sage: G = R*I.groebner_basis()
sage: G
Symmetric Ideal (x_1^2 + x_1, x_2 - x_1) of Infinite polynomial ring in x
over Rational Field
sage: Q = R.quotient(G)
sage: p = x[3]*x[1]+x[2]^2+3
sage: Q(p)
-2*x_1 + 3
}}}
By the second generator of G, variable x_n is equal to x_1 for any
positive integer n.
By the first generator of G, x_1^3^ is equal to x_1 in Q. Indeed, we have
{{{
sage: Q(p)*x[2] == Q(p)*x[1]*x[3]*x[5]
True
}}}
Note that the one doc test in {{{quotient_ring.py}}} has a doc test
involving symmetric ideals. I don't know who wrote it, but (s)he forgot to
use a symmetric Groebner basis for the ideal.
'''__Coercion__'''
I discovered construction functors and pushout, and now I really
appreciate Sage's coercion system. By consequence, I make extensive use of
it --- hopefully not too much...
1.
I introduced a construction functor for infinite polynomial rings. This
functor, together with a ring, is used as the unique key of an infinite
polynomial ring (as unique parent structure. I don't know if the use of
construction functors for providing unique parents is common --- but I can
recommend it!
{{{
sage: InfinitePolynomialRing.create_key(QQ, ('y1',))
(InfPoly{[y1], "lex", "dense"}(FractionField(...)), Integer Ring)
sage: InfinitePolynomialRing.create_key(QQ, names=['beta'],
order='deglex', implementation='sparse')
(InfPoly{[beta], "deglex", "sparse"}(FractionField(...)), Integer Ring)
sage: InfinitePolynomialRing.create_key(QQ, names=['x','y'],
implementation='dense')
(InfPoly{[x,y], "lex", "dense"}(FractionField(...)), Integer Ring)
}}}
As you can see, the given base ring is generally not used in the unique
key. The reason is explained in the next paragraph.
2.
In a way, an infinite polynomial ring X is just an upgrade of a usual
polynomial ring P: The former has finitely many generators x, y and
infinitely many variables x_0, x_1,..., y_0,y_1,..., while the latter may
have finitely many variables x_0,x_1,x_2.
Now, imagine what happens if you define {{{X =
InfinitePolynomialRing(P,['x','y'])}}}? We can't simply take P as the base
ring of X, since there is a name conflict. But since P can be considered a
sub-structure of X: Why shouldn't one merge it into X?
In fact, this is what I do, still with unique parent structures:
{{{
sage: P.<a,b,x_2,x_0,y_3,y_2> = QQ[]
sage: X.<x,y> = InfinitePolynomialRing(P, order='degrevlex')
sage: X
Infinite polynomial ring in x, y over Multivariate Polynomial Ring in a, b
over Rational Field
sage: P2.<a,b> = QQ[]
sage: X2.<x,y> = InfinitePolynomialRing(P2, order='degrevlex')
sage: X2 is X
True
}}}
However, one has to be cautious: Infinite Polynomial Rings are ''ordered''
rings. Therefore, we only merge P into X if it is not only isomorphic to a
sub-ring of X, but isomorphic to an ''ordered'' sub-ring of X. If this is
not the case, an error will be raised:
{{{
sage: X3.<x,y> = InfinitePolynomialRing(P) # the standard order is lex
---------------------------------------------------------------------------
CoercionException Traceback (most recent call
last)
...
CoercionException: Incompatible term orders lex, degrevlex
sage: X3.<y,x> = InfinitePolynomialRing(P, order='degrevlex')
---------------------------------------------------------------------------
CoercionException Traceback (most recent call
last)
...
CoercionException: Overlapping variables (('y', 'x'),['x_2', 'x_0', 'y_3',
'y_2']) are incompatible
}}}
Note: We attempted to make y_* greater than x_* in X, but x_* is greater
than y_* in P.
{{{
sage: P.<a,b,x_0,x_2,y_3,y_2> = QQ[]
sage: X3.<x,y> = InfinitePolynomialRing(P, order='degrevlex')
---------------------------------------------------------------------------
CoercionException Traceback (most recent call
last)
...
CoercionException: Overlapping variables (('x', 'y'),['x_0', 'x_2', 'y_3',
'y_2']) are incompatible
}}}
Note: In any infinite polynomial ring holds x_2>x_0, but the order in P is
opposite.
The 'magical merging' is based on the multiplication of construction
functors, combined with the fact that functors are used as unique keys for
parent structures.
__Remark__
What I do here could also be a model for polynomial rings. After all, I
think it is a bug that the following does not raise an error:
{{{
sage: QQ['t']['t']
Univariate Polynomial Ring in t over Univariate Polynomial Ring in t over
Rational Field
}}}
3.
The original purpose of the coercion machinery is probably to allow for
flexible use of arithmetic with elements of different rings. There you
are:
{{{
sage: 1/2*x_2+z[3]-a/((3*z[2]+2*z[1]+3)^2).lc()
z_3 - 1/9*a + 1/2*x_2
sage: _.parent()
Infinite polynomial ring in z over Multivariate Polynomial Ring in a, b,
x_2, x_0, y_3, y_2 over Rational Field
}}}
or
{{{
sage: P.<a,b,x_2,x_0,y_3,y_2> = ZZ[]
sage: X.<y,z> = InfinitePolynomialRing(ZZ,order='degrevlex')
sage: 1/2*x_2+z[3]-a/((3*z[2]+2*z[1]+3)^2).lc()
z_3 - 1/9*a + 1/2*x_2
sage: _.parent()
Infinite polynomial ring in y, z over Multivariate Polynomial Ring in a,
b, x_2, x_0 over Rational Field
}}}
Note that the last example only works since P and X both have order
'degrevlex'; otherwise we couldn't fit both P and X into a common ring.
'''__Self-critical comments__'''
* The closed ticket #6854 provides tab completion for elements of
infinite polynomial rings. Here I provide a slightly simpler
implementation. But I wouldn't mind if the implementation from #6854 would
be used instead.
* The patch contains the changes that I suggested on #7620. It is
essential that these changes are done. So, #7620 may be considered a
duplicate (or sub-ticket).
* The new {{{InfinitePolynomialFunctor}}} has rank 9.5; this is since
{{{PolynomialFunctor}}} has rank 9 and should be applied ''before''
{{{InfinitePolynomialFunctor}}} --- but rank 10 is taken by
{{{MatrixFunctor}}}. I hope that fine tuning is ok.
* The doc tests of devel/sage/sage/numerical/mip.pyx will break, since
the name scheme for variables of infinite polynomial rings has changed.
However, #7561 suggests to remove infinite polynomial rings from mip.pyx.
So, I can live with these broken doc tests...
'''__Question to the Reviewer__'''
Can you please test on a 32 bit machine as well? I know that the hash code
on 64 bit has changed, but I have no access to 32 bit and don't know what
hash value to expect.
I hope that you enjoy that patch bomb...
Cheers,
Simon
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/7580#comment:10>
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.