On Saturday, September 7, 2013 9:38:04 AM UTC-7, Volker Braun wrote: > Is that really true? That is basically my question. What would go wrong? > If one can only break cyclic references in specific orders then the whole > thing is probably not going to work as we can't predict how a user will > compose Sage objects. >
Let's try. I think there are structures where you can't just delete cyclic references at all, unless you take special efforts to recreate them afterwards. For instance, consider class GraphNode(object): def __init__(self,neighbours=None): if neighbours is None: self.neighbours=[] else: self.neighbours=neighbours #make the complete graph on 4 nodes C=[GraphNode() for i in range(4)] for c in C: c.neighbours.extend([b for b in C if b is not c]) I can imagine that similar situations could naturally arise in sage. Perhaps the following: Consider a class for ProjectiveSpace and its associated PicardGroup, created by P2=ProjectiveSpace(k,2) PicP2=PicardGroup(P2) Let's assume computing a PicardGroup is expensive, so we'd like to ensure that PicP2's lifetime coincides with P2's, so we put a reference from P2 to PicP2 on P2. Of course PicP2 needs a reference to P2. When pickling P2 we don't absolutely need to pickle PicP2, although not doing so means that after unpickling that P2 it might be expensive to obtain PicP2. A solution would be to pickle [P2,PicP2] instead. Even for pickling PicP2 it would not be strictly necessary to store a reference to P2 explicitly: if it gets pickled to "execute PicardGroup(P2)" the reference to P2 would be implied anyway. However, that's of course NOT how we'd pickle something that's expensive to compute. It should probably have some set_state way of recreating PicP2 with the expensively computed data explicitly passed to it. That probably includes P2. Now a different example, which I think is a little more like the graph example above. Suppose we store the affine patches to P2 as affine spaces. Since affine spaces can exist on their own, their creation doesn't necessarily imply a reference to P2. However, for pickling the constellation of P2 with its affine patches I would think that including the relations between them (which need to be stored in both directions!) is probably the expected behaviour. We can of course impose (artificially) a hierarchy here to break circularity: We can say affine patches always know about their projective closure and only cache the references on projective space to its patches for efficiency reasons. But doing so might have consequences when someone does: A2 = AffineSpace(k,2) P2= ProjectiveClosure(A2) allA2s= AllAffinePatches(P2) (i.e., here P2 is derived from A2 rather than the other way around) The problem is that the relations between the A2s and the P2 cannot be found by coercion discovery: The relations are only there because of how they are constructed. So if we were to simply break the connections and pickle P2 and allA2s, we'd end up with just a bunch of ambient spaces, without the relations that they are supposed to have. I suspect similar things can happen with number fields, where certain coercions might get installed upon creation (e.g., a "represent_relative_extension_as_absolute_extension"), but where the creation data on the number field doesn't hold a hint that this happened. So here one would not necessarily end up with a defunct pickle, but unless one also explicitly pickles the appropriate "register_coercion" the pickle would lose information. I think solving this will simply be too complicated: This is state that ends up living outside the objects explicitly referenced, so pickle can't see this. Finally, for rings there is always a fundamental circularity: Rings tend to store a "zero" and "one" element. Those being elements, they carry a pointer to their parent, so any ring tends to be part of a cycle (this is actually nice for GC purposes: it extends the life of rings automatically to the next cyclic GC, so frequent ring creation/destruction is automatically moderated. It also increases the burden on GC, making it more expensive) So automatic pickling of a ring would have to deal with circularity too. Here, the appropriate solution is to not worry about zero and one: they'll get created anyway, so you shouldn't pickle them explicitly. Most of these situations have fairly simple solutions, but in each case specific knowledge of the objects at hand seems to be required. -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at http://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/groups/opt_out.