>> Note that by saying
>> S(x) = ...
>> you define S as a symbolic function on a symbolic variable x, and if you
>> re-define x later, then the variable of S will still be symbolic, and
>> not belong to a polynomial ring.
>>
>
> Ok, my bad. I am still fairly new to Sage (even if I tried to submit a
> super small patch) and I don't completely understand what's the difference
> here,
A symbolic expression is something fairly general---so general that many
methods won't make sense in this generality. A symbolic expression may
contain all "strange" stuff like sin(x^2), exp(pi), x^x, etc.
In contrast, a polynomial ring is a structure that has a fixed base ring
(finite field of order 16, in your example) and has one or several
generators (x, in your example), so that *all* elements are sums of
terms of the form "element of the base ring times product of
generators". Hence, x^x is not a polynomial (the exponent must be a
natural number), there is no sin, no pi, etc.
Polynomials are of course quite useful in some branches of mathematics.
And concerning your problem: Polynomial rings over fields are Euclidean
domains, and thus there is an algorithm to compute quotient with
remainder or gcd and so on.
From computer science point of view, the mathematical algorithms are
implemented in methods of certain (base) classes. The polynomials we want
to consider here belong to classes that provide a quo_rem method. But
general symbolic expressions belong to a different class, and a quo_rem
method would make no sense for them.
In your example, a particular situation occurs: You define a and b.
While a *is* a polynomial, b is not. Hence, the method a.quo_rem
exists, but the method realises that b is no suitable input.
> Unfortunately I am an undergraduate student in Computer Science (not even
> math) so there are some concepts which are still obscure to me. :P For
> example, what is the meaning of these two lines?
>
> P.<x> = f[]
This line is a shortcut for
P = PolynomialRing(f,'x')
x = P.gen()
It is syntactical sugar: P.<x>=f[] is not valid in Python, but it is a
convenient notation well known from the Magma computer algebra system.
Hence, the Sage developers wanted to make this notation available, by
means of a pre-processor.
> x = P.gen()
As I mentioned above, a polynomial ring knows its base ring and it
generator(s). Here, we have the base ring f, which you could check by
sage: P.base_ring() is f
True
And P.gen() returns the generator (i.e., the "variable") of this
polynomial ring. Note that this "variable" is by no means the same as a
symbolic variable of the same name:
sage: x = var('x')
sage: x
x
sage: P.gen()
x
sage: type(x)
sage.symbolic.expression.Expression
sage: type(P.gen())
sage.rings.polynomial.polynomial_zz_pex.Polynomial_ZZ_pEX
sage: hasattr(x, 'quo_rem')
False
sage: hasattr(P.gen(), 'quo_rem')
True
By the way, you can get the documentation of a method by appending a
question mark (and hitting return resp. shift-return in the notebook).
Hence, P.gen?<ret>
By appending two question marks, you can get the source code (in most
cases). If you start typing the name of a method and hit the tab key,
you'll get a list of all methods starting with what you typed. Hence,
P.ge<tab> will give you P.gen, P.gens, P.gens_dict, P.gens_dict_recursive,
P.get_action, P.get_action_c, P.get_action_impl, for each of which you
could then check the documentation.
Best regards,
Simon