There is the basic PowerSeries class defined in
rings/power_series_ring_element.pyx, and then there's the derived
class PowerSeries_poly, defined in rings/power_series_poly.pyx.
However, I have not been able to come up with a single instance of
PowerSeries that is *not* an instance of PowerSeries_poly.
Should I be able to? What is the difference between the two classes,
from both the user and developer points of view?
Best,
Alex
--
Alex Ghitza -- Lecturer in Mathematics -- The University of Melbourne
-- Australia -- http://www.ms.unimelb.edu.au/~aghitza/
Aha, that makes sense. So here's my problem: I'm working on trac 111,
i.e. change all the .copy() methods to __copy__(). Having done this
in power_series_poly.pyx, I am now getting a doctest failure in
power_series_ring_element.pyx, namely
sage: copy(f) is f # !!! ok since power series are immutable.
Expected:
True
Got:
False
This is because PowerSeries already has a __copy__() method which just
returns self, while the __copy__() method of PowerSeries_poly actually
returns a copy. The doctest is failing because f is a
PowerSeries_poly and hence the derived method is used.
So I'm not sure what to do. I cannot change the doctest because I
can't construct a PowerSeries which is not a PowerSeries_poly. My
thought now is to make PowerSeries.__copy__() return
NotImplementedError and have all derived classes override it.
Is this reasonable? Is there a better solution I don't see now?
There are a few questions here.
1. If all instances of a class C are immutable, is reasonable for
__copy__ to just return self?
2. Are all instances of PowerSeries going to be immutable? Or, are we
someday going to have a class PowerSeries_mutable?
Regarding 1, fortunately Python itself provides some help with this question.
sage: import copy
sage: a = int(903840823)
sage: copy.copy(a) is a
True
sage: a = float(2.39494)
sage: copy.copy(a) is a
True
sage: a = 'hi there'
sage: copy.copy(a) is a
True
I.e., the answer to question 1 is a resounding "yes!".
Regarding question 2, note that power series are already secretly mutable:
sage: R.<x> = QQ[]
sage: f = x^3 + 3*x - 1
sage: f._unsafe_mutate(1, 10)
sage: f
x^3 + 10*x - 1
sage: R.<x> = QQ[[]]
sage: f = x^3 + 3*x - 1 + O(x^5)
sage: f._unsafe_mutate(1, 10); f
-1 + 10*x + x^3 + O(x^5)
The function _unsafe_mutate is there because long ago polynomials and
power series were trivially mutable, i.e., this used to work:
sage: f[1] = 1100
and David Harvey implemented some nice code that used this. Then in
late 2006 we went through and made many basic objects immutable in
Sage, since mutable objects should *never* be hashable, or many basic
Python algorithms break. All parents were made immutable, as were a
wide range of elements (with the notable exception of matrices and
vectors, which can now be both immutable or mutable).
Anyway, when changing things to immutable, I didn't want to break
David's fine code, so _unsafe_mutate -- whose unsafeness should be
clear -- was introduced.
The upshot of all this is that one almost always really wants
polynomials and power series to be immutable, in which case __copy__
returning self is perfectly fine. Sometimes mutating
polynomials/powerseries is very useful for certain algorithms though.
So I would say the answer to 2 is a not resounding "yes" for now, with
the caveat that one can simply do a little code refactoring later of
mutable polynomials and power series are introduced. Given that I've
not seen a single remark on any Sage list about
mutability/immutability of power series and polynomials during the
last 3 years, I doubt that the lack of mutability being fully
supported (like it is for matrices) is a serious problem.
-- William
If I understood correctly, you suggest that I remove __copy__() from
the derived class PowerSeries_poly, and leave in place the __copy__ of
PowerSeries that just returns self. This would do the correct thing
for the currently unique derived class, and if someone eventually
implements PowerSeries_mutable, they can override __copy__ with the
appropriate thing.
Alex
--
Yep, that's what I said in a very long-winded way.
-- William