#11255: Enhance the e_one_star.Patch class
-----------------------------+----------------------------------------------
Reporter: tjolivet | Owner: sage-combinat
Type: enhancement | Status: needs_review
Priority: major | Milestone: sage-4.7.1
Component: combinatorics | Keywords:
Work_issues: | Upstream: N/A
Reviewer: | Author: Timo Jolivet
Merged: | Dependencies:
-----------------------------+----------------------------------------------
Changes (by tjolivet):
* status: needs_work => needs_review
Comment:
Replying to [comment:6 slabbe]:
> If we want Patches to be keys of dictionnary, vertices of graphs or
elements of
> sets, it must be hashable. The easiest solution I see is that an object
Patch
> be always hashable and never mutable. That means we made a mistake
earlier by
> allowing to modify a Patch. I am responsible for this as I remember I
disliked
> methods like {{{apply_substitution}}} but I were not able to verbalize
it and
> relate this with the ability of hashing the object.
>
> There are three methods that change self : {{{add}}},
{{{apply_substitution}}}
> and {{{repaint}}}. I think we can keep {{{repaint}}} as it does not
change the
> mathematical object and hence won't affect the result of the hash method
(a
> doctest making sure of that the hash method is independant of color
changes
> should be added). Surprisingly, we did not made the mistake with the
method
> {{{translate}}} which does not change self and return a new patch. I
think it
> is easy to remove the method {{{apply_substitution}}} since (1) one can
apply a
> substitution by just applying a substiution directly on it : ``E(P)``
and (2)
> the only reason I can understand the existence of the method
> {{{apply_substitution}}} is that it is faster than doing ``E(P)`` which
is not
> the case anyway since it calls ``E(P)`` anyway. I also think the method
> {{{add}}} can be easily removed. We should replace it by a method
{{{__add__}}} or {{{union}}} which adds two patches and return a new
patch.
>
> Now, the method {{{adds}}} and {{{apply_substitution}}} should not be
removed
> right now. Deprecation warnings should be added. Well usually, a
deprecation
> warning should be raised for one year before removing the method. But,
since I
> believe fixing the immutable/hashable issue is very important. I think
their
> behavior could be changed now. A deprecation warning saying something
like :
> "Object sage.combinat.e_one_star.Patch are immutable since Sage-4.7.1.
Use the
> usual addition instead which returns a new object: P + Q." A similar
warning
> should be added to the method {{{apply_substitution}}}.
OK, these methods now return a new patch, along with a deprecation
warning.
I changed the doc in favor of using {{{E1Star.__call__}}} insead of
{{{apply_substitution}}}.
> One can create a Patch from a (1) iterable of faces or (2) from a Patch.
The
> problem comes from the case (2) were a copy should be done. Here is my
first
> suggestion:
>
> {{{
> if isinstance(faces, Patch):
> self._faces = [Face(f.vector(), f.type(), f.color()) for f in faces]
> else:
> self._faces = list(faces)
> }}}
This is a good solution, I use it.
> First, there is a problem with the method {{{remove}}} because it
changes the
> Patch. Compare the methods and their name of the mutable unhashable
Python set
> and the immutable and hashable Python frozenset :
>
> {{{
> sage: python_set = set([])
> sage: [method for method in dir(python_set) if not
method.startswith('_')]
> ['add', 'clear', 'copy', 'difference', 'difference_update', 'discard',
> 'intersection', 'intersection_update', 'isdisjoint', 'issubset',
'issuperset',
> 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update',
> 'union', 'update']
> sage: frozen_set = frozenset()
> sage: [method for method in dir(frozen_set) if not
method.startswith('_')]
> ['copy', 'difference', 'intersection', 'isdisjoint', 'issubset',
'issuperset',
> 'symmetric_difference', 'union']
> }}}
>
> Hence, I suggest to implement a method called {{{difference}}} which
returns a
> new Patch instead of the method remove.
OK, I this is also a better solution. I also added a {{{union}}} method,
that does the job that {{{Patch.add}}} was supposed to do (so that the
deprecation warning of {{{add}}} is not annoying when {{{__add__}}} is
used). The method {{{remove}}} no longer exists.
> My last question concerns the representation of the Patch. Now, we
represent a
> patch as a list of faces. I think this choice was made because we wanted
an
> object Patch to be mutable without loosing time on unicity of faces
concerns
> which did not bothered us, since it is guarenteed mathematically (well
at least
> for the application of E1Stars). But, if a Patch is now immutable, maybe
a
> Python frozenset or maybe a Sage Set (also immutable) would be better.
>
> {{{
> sage: sage_set = Set([])
> sage: [method for method in dir(sage_set) if not method.startswith('_')]
> ['CartesianProduct', 'Hom', 'algebra', 'an_element', 'base',
'base_ring',
> 'cardinality', 'cartesian_product', 'categories', 'category', 'coerce',
> 'coerce_embedding', 'coerce_map_from', 'construction',
'convert_map_from',
> 'db', 'difference', 'dump', 'dumps', 'element_class', 'frozenset',
'gens_dict',
> 'get_action', 'has_base', 'has_coerce_map_from', 'hom',
'inject_variables',
> 'injvar', 'intersection', 'is_exact', 'is_finite', 'latex_name',
> 'latex_variable_names', 'list', 'normalize_names', 'object', 'objgen',
> 'objgens', 'register_action', 'register_coercion',
'register_conversion',
> 'register_embedding', 'rename', 'reset_name', 'save', 'set',
'some_elements',
> 'subsets', 'symmetric_difference', 'union', 'variable_name',
'variable_names',
> 'version']
> }}}
>
> What do you think?
Everything is cleaner if we use sets instead of lists, you're right. I
submitted a new patch that uses frozenset and made the according changes
in the doc and everywhere, which means quite a lot of stuff as you will
see in my new patch, which applies over the previous one.
Also, I added an option in {{{E1Star.__init__}}}: we can now choose
between the 'suffix' or 'prefix' version of the dual substitution. The
default one ('suffix') is the one that was used before. Adding this is
important because both versions are widely used in the literature. (I also
moved {{{_base_iter}}} from a method to a direct creation in
{{{__init__}}}, the gain of time given by {{{@lazy_attribute}}} was really
negligible.)
Thank you for your very useful corrections.
For the patchbot :
Apply trac-11255-tj.patch
Apply trac-11255-tj-modifs.patch
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/11255#comment:8>
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.