Re: [sage-combinat-devel] Global options for elements set by their parents
Hi Andrew, This looks in principle good. Is it possible to display which options are set? That might be useful since the user might not know what the default options are or might have forgotten which options were set. Best, Anne On 10/27/12 5:43 AM, Andrew Mathas wrote: > Travis has is writing a nice patch #13605 which implements global options for > partitions. Among other things, these options determine how partitions are > printed (as lists, using exponential notation, > compactly, ...), whether diagrams follow the English or French conventions, > whether the default ordering is the lexicographic or dominance etc. > > I have been bugging him with suggestions and requests, of which the main ones > are: > > * each option should be accessible as an individual method > * the naming of these methods should systematic to make it easier for other > classes, which may themselves have options, to easily access these methods. > > As a result of these discussions I'd like to suggest a general framework for > implementing global options for element classes which are controlled by their > parents (being a parent myself I am of course > advocating for parental control here!:). > > The reason for this post is to ask whether need a general options mechanism > for element classes and, if so, is anyone in favour of the approach described > below. > > The main idea is that the parent inherits a generic method (see below) of the > form: > > def options(self, *option, **options): > r""" > Print and set options for the element class of ``self`` > > > > which is used to set and print the options for the element class. In the > element_class the options to the method ``foo`` are methods of the form > ``foo_option1``, ``foo_option2`` and so on. What the > ``options`` method of the parent does is simply set ``self.element.foo`` > equal to the desired option. The nice thing about this, is that the options > do not add extra overhead to the methods and they > can be added to the element class simply by adding appropriate methods: > > def _repr__fuzzy(self): return 'I am fuzzy' > def _repr__focussed(self: return 'I am focussed' > _repr_=_repr_focussed # the default > > and then you can set the option with > > sage: parentClass.options(_repr_='fuzzy') > > This will set _repr_ = _repr__fuzzy --- or raise a ValueError if this is > not a valid option. > > As a test case, I have implemented a prototype for partitions, however, the > code is completely general. Just as importantly, it seems to work quite well. > For those who want to see the details I will > upload a patch trac_13605?--generic_partition_options-am.patch to the queue > shortly. > > Here are some examples of how it works: > > sage: mu=Partition([4,4,3,2,1,1,1]); mu > [4, 4, 3, 2, 1, 1, 1] > sage: Partitions(4).options('_repr_') # the default behaviour is to > print partitions as lists > list > > Because of the underscores, using _repr_ as the option name seems slightly > "wrong", so I allow an alias which in this case is 'display': > > sage: Partitions(4).options('display') > list > sage: Partitions(4).options(display='exp'); mu > 1^3, 2, 3, 4^2 > sage: mu._repr__exp() # this is what _repr_ now calls > 1^3, 2, 3, 4^2 > sage: Partitions(4).options(display='exp_high'); mu > 4^2, 3, 2, 1^3 > sage: Partitions(4).options(display='compact'); mu > 1^3,2,3,4^2 > sage: Partitions(4).options(display='compact_high'); mu > 4^2,3,2,1^3 > sage: Partitions(4).options(display='diagram'); > sage: Partitions(4).options(convention='french'); mu > * > * > * > ** > *** > > > > > sage: Partitions(4).options(convention='english'); mu > > > *** > ** > * > * > * > sage: Partitions(4).options(cmp='dominance') > sage: Partition([3,1,1,1])>Partition([2,2,2]) > False > sage: Partitions(4).options(cmp='lex') # lexicographic ordering > sage: Partition([3,1,1,1])>Partition([2,2,2]) > True > sage: Partitions(4).options(display='exp'); mu > 1^3, 2, 3, 4^2 > sage: Partitions(4).options(display='exp_high'); mu > 4^2, 3, 2, 1^3 > sage: Partitions(4).options(display='list'); mu > [4, 4, 3, 2, 1, 1, 1] > sage: Partitions(4).options(display='exp_low') > Traceback (most recent call last): > ... > ValueError: exp_low is not a valid option for display > > > Above 'cmp' is an alias which controls the options of the four methods > '__lt__', '__le__', '__ge__' and '__gt__'. So aliases allow options to be > given sensible names and, in addition, they allow one > option to change more than one method. > > With this scheme I am able to do everything which Travis does except > (possibly?) for passing arguments to methods. (Travis allows you to globally > set the character printed in a Ferrers diagram.) In > the examples above I use Partitions(4) only because I added the options > method to Partitions_n, rather than to Partitions_all, and these two classes > are completely in
Re: [sage-combinat-devel] Global options for elements set by their parents
Hi Andrew! On Sat, Oct 27, 2012 at 05:43:08AM -0700, Andrew Mathas wrote: > Travis has is writing a nice patch #13605 which implements global options for > partitions. Among other things, these options determine how partitions are > printed (as lists, using exponential notation, compactly, ...), whether > diagrams follow the English or French conventions, whether the default > ordering > is the lexicographic or dominance etc. A big +1 on exploring this long desired feature set! One caveat: setting options for a preexisting parent should *not* affect its semantic. Otherwise, one is likely to break other pieces of Sage which rely on a given semantic. In other words: OK (that just affects the outputs in my own session): sage: Partitions().options(convention="french") OK (I own P and can do what I want with it): sage: P = Partitions(cmp=dominance) Not OK (this could break e.g. Symmetric Functions): sage: Partitions().options(cmp=dominance) > As a result of these discussions I'd like to suggest a general > framework for implementing global options for element classes which > are controlled by their parents (being a parent myself I am of > course advocating for parental control here!:). I would want to extend the framework to also allow for setting options for the parent itself. Things like Partitions(3, order=...) that would change the enumeration order. > The reason for this post is to ask whether need a general options mechanism > for > element classes and, if so, is anyone in favour of the approach described > below. > The main idea is that the parent inherits a generic method (see below) of the > form: > def options(self, *option, **options): > r""" > Print and set options for the element class of ``self`` > > > which is used to set and print the options for the element class. In the > element_class the options to the method ``foo`` are methods of the form > ``foo_option1``, ``foo_option2`` and so on. What the ``options`` method of the > parent does is simply set ``self.element.foo`` equal to the desired option. > The > nice thing about this, is that the options do not add extra overhead to the > methods and they can be added to the element class simply by adding > appropriate > methods: > def _repr__fuzzy(self): return 'I am fuzzy' > def _repr__focussed(self: return 'I am focussed' > _repr_=_repr_focussed # the default > and then you can set the option with > sage: parentClass.options(_repr_='fuzzy') > This will set _repr_ = _repr__fuzzy --- or raise a ValueError if this is > not > a valid option. > As a test case, I have implemented a prototype for partitions, however, the > code is completely general. Just as importantly, it seems to work quite well. > For those who want to see the details I will upload a patch trac_13605?-- > generic_partition_options-am.patch to the queue shortly. > ... > Please let me know what you think. I like the idea of something systematic! Some issues that could come up though: - Element classes may be shared between different parents. One needs to make sure that one does not affect by accident unrelated parents. - Assigning methods to the class won't work with Cython classes (as far as I remember). - To support options for both the parent and the elements, we probably want options names like "element_repr=...", which by the way would be nicely explicit. - One often need to change several methods (repr/latex/...) at once, so manual handling will be needed in many (most?) cases anyway. Also a comment: the result output methods like repr is meant to be eventually read by a human; if such a method is called zillions of times, then probably something got wrong. Thus, one should not worry about optimizing away callbacks to the parent in such methods: "always ask dad/mom what you should do" :-). Cheers, Nicolas -- Nicolas M. Thiéry "Isil" http://Nicolas.Thiery.name/ -- You received this message because you are subscribed to the Google Groups "sage-combinat-devel" group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Global options for elements set by their parents
> This looks in principle good. Is it possible to display which options are > set? > That might be useful since the user might not know what the default > options are > or might have forgotten which options were set. > To do this within the framework I am thinking of it would probably be necessary to add an additional _options.defaults attribute to the parent which specifies all of the options and their defaults. This would solve the general documentation issues referred to by the todo in the code of listing all available options when options() is called with no arguments. Andrew -- You received this message because you are subscribed to the Google Groups "sage-combinat-devel" group. To view this discussion on the web visit https://groups.google.com/d/msg/sage-combinat-devel/-/GP7wIf1Q_7IJ. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Global options for elements set by their parents
On Sat, Oct 27, 2012 at 09:43:37PM -0700, Andrew Mathas wrote: > To do this within the framework I am thinking of it would probably be > necessary > to add an additional _options.defaults attribute to the parent which specifies > all of the options and their defaults. +1. You can grep through the code of graphs to see some spots where something similar is done. And there is a question of whether we could unify those. A related question: should this framework be about Parents or SageObjects ... Cheers, Nicolas -- Nicolas M. Thiéry "Isil" http://Nicolas.Thiery.name/ -- You received this message because you are subscribed to the Google Groups "sage-combinat-devel" group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Global options for elements set by their parents
Hi Nicolas, Not OK (this could break e.g. Symmetric Functions): > > sage: Partitions().options(cmp=dominance) > In his patch Travis has an option for changing the default comparison method and I think that this would be useful. Below you also mention that be able to change the default ordering for enumerating the elements is also desirable but I can think of situations where this would break code. These two examples suggest to me that the "not changing the semantic policy" may be too strict. Having said this, one of the motivations behind my proposal is precisely to avoid issues like this: as each option is available as a method of the class, if external code wants or requires a particular variant of an optional method then it should call that method directly. In this instance, if the symmetric functions require the lexicographic ordering then they should explicitly call the corresponding methods, such as __le___lex__. I admit that this would be slightly annoying in this case -- and also decrease the readability of the code -- but if it was agreed that cmp methods should be optionable then this is how such problems would be dealt with using the framework that I am proposing. I would want to extend the framework to also allow for setting options > for the parent itself. Things like Partitions(3, order=...) that would > change the enumeration order. > Currently I have the parents controlling the parents but I guess that there is no reason not to make the elements responsible for their own options and the parents responsible for theirs. Alternatively, with some hacking the options method of the parent could be made to recognise whether it was a parent or element_class option. - Element classes may be shared between different parents. One needs > to make sure that one does not affect by accident unrelated parents. > Don't elements always have unique parents? Although I guess this issue does arise because of inheritance with, for example, some methods for StandardTableau being inherited from Tableau...there could be issues here. Perhaps the factory framework for such classes that Florent is developing would help here? > - Assigning methods to the class won't work with Cython classes (as > far as I remember). > I have no experience with cython yet but I wouldn't have thought this was a big problem because all that I am really doing to using optionable methods as aliases for the real methods. The idea is that a method like _repr_ simply becomes an alias for _repr_with_option and that changing an option for _repr_ just changes which function it is an alias for. > - One often need to change several methods (repr/latex/...) at once, > so manual handling will be needed in many (most?) cases anyway. > This is already catered for by my option_alias dictionary. For example, the option cmp changes __le__, __lt__, __ge__, and __gt__. > Also a comment: the result output methods like repr is meant to be > eventually read by a human; if such a method is called zillions of > times, then probably something got wrong. Thus, one should not worry > about optimizing away callbacks to the parent in such methods: "always > ask dad/mom what you should do" :-). > I agree, but if a generic solution is possible then it should be efficient because this will make a difference in some cases. > A related question: should this framework be about Parents or SageObjects ... Given your comments about parents above, perhaps this should be generally about objects...however, I am not sure how well what I am proposing will work with multiple inheritance. This could definitely be a problem. Andrew Andrew -- You received this message because you are subscribed to the Google Groups "sage-combinat-devel" group. To view this discussion on the web visit https://groups.google.com/d/msg/sage-combinat-devel/-/E_I5zChV0OQJ. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Global options for elements set by their parents
Hi, For string representation, I think that it sould be a matter of the parent via a _repr_element_ method. This method is yet used in some classes. The issue may be fixed with the modification of Element.__repr__ as def __repr__(self): if self.__custom_name: return self.__custom_name if hasattr(self._parent, '_repr_element_'): return self._parent._repr_element_(self) return self._repr_() If two parents with the same Element class would like two different representations it is natural to implement them inside the parent (otherwise Element will be full of methods like _repr_v1_, _repr_v2_, ...). What do you think ? Best, Vincent -- You received this message because you are subscribed to the Google Groups "sage-combinat-devel" group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Global options for elements set by their parents
Hey everyone, On Sunday, October 28, 2012 2:13:07 AM UTC-7, Andrew Mathas wrote: > > Hi Nicolas, > > Not OK (this could break e.g. Symmetric Functions): >> >> sage: Partitions().options(cmp=dominance) >> > > In his patch Travis has an option for changing the default comparison > method and I think that this would be useful. Below you also mention that > be able to change the default ordering for enumerating the elements is also > desirable but I can think of situations where this would break code. These > two examples suggest to me that the "not changing the semantic policy" may > be too strict. > > Having said this, one of the motivations behind my proposal is precisely > to avoid issues like this: as each option is available as a method of the > class, if external code wants or requires a particular variant of an > optional method then it should call that method directly. In this instance, > if the symmetric functions require the lexicographic ordering then they > should explicitly call the corresponding methods, such as __le___lex__. I > admit that this would be slightly annoying in this case -- and also > decrease the readability of the code -- but if it was agreed that cmp > methods should be optionable then this is how such problems would be dealt > with using the framework that I am proposing. > > I would want to extend the framework to also allow for setting options >> for the parent itself. Things like Partitions(3, order=...) that would >> change the enumeration order. >> > > Currently I have the parents controlling the parents but I guess that > there is no reason not to make the elements responsible for their own > options and the parents responsible for theirs. Alternatively, with some > hacking the options method of the parent could be made to recognise whether > it was a parent or element_class option. > I believe we should allow individually created parents to set their options only via Partitions(3, order=...), that way we don't have to worry about changing something by surprise if something is a UniqueRepresentation. However by implementing this, we could then not break things by not necessarily having to call particular methods directly. So in SymmetricFunctions, if we need lex order, we call P = Partitions(3, order='lex') and then iterate over P. (Hopefully that makes sense...) > > - Element classes may be shared between different parents. One needs >> to make sure that one does not affect by accident unrelated parents. >> > > Don't elements always have unique parents? Although I guess this issue > does arise because of inheritance with, for example, some methods for > StandardTableau being inherited from Tableau...there could be issues here. > Perhaps the factory framework for such classes that Florent is developing > would help here? > We have the following situation: class ElementFoo(Element): class Parent1(Parent): Element = ElementFoo class Parent2(Parent): Element = ElementFoo > > >> - Assigning methods to the class won't work with Cython classes (as >> far as I remember). >> > > I have no experience with cython yet but I wouldn't have thought this was > a big problem because all that I am really doing to using optionable > methods as aliases for the real methods. The idea is that a method like > _repr_ simply becomes an alias for _repr_with_option and that changing an > option for _repr_ just changes which function it is an alias for. > Couldn't we just do that with function pointers? http://docs.cython.org/src/reference/language_basics.html > > A related question: should this framework be about Parents or > SageObjects ... > > Given your comments about parents above, perhaps this should be generally > about objects...however, I am not sure how well what I am proposing will > work with multiple inheritance. This could definitely be a problem. > >From looking at it, the only problem I see with (multiple) inheritance might be making sure the display_options is coherent. Vincent, if I understand you correctly you're trying to avoid polluting the namespace of the element classes. This also makes me worry about the following situation. Suppose Elt is an element to 2 different parents Foo and Bar where the repr for Foo.Elt is (naturally) different from Bar.Elt. Thus Foo.Elt.options(repr=bar_repr) should throw an error. Best, Travis -- You received this message because you are subscribed to the Google Groups "sage-combinat-devel" group. To view this discussion on the web visit https://groups.google.com/d/msg/sage-combinat-devel/-/GquWXCpCGs4J. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Global options for elements set by their parents
On Sun, Oct 28, 2012 at 06:50:19PM -0700, Travis Scrimshaw wrote: >On Sunday, October 28, 2012 2:13:07 AM UTC-7, Andrew Mathas wrote: >Not OK (this could break e.g. Symmetric Functions): > >sage: Partitions().options(cmp=dominance) > > In his patch Travis has an option for changing the default comparison > method and I think that this would be useful. Yes, but only by creating a new parent: sage: Partitions(cmp=dominance) Not by changing an existing one: sage: Partitions().options(cmp=dominance) >I believe we should allow individually created parents to set their >options only via Partitions(3, order=...), that way we don't have to worry >about changing something by surprise if something is a >UniqueRepresentation. However by implementing this, we could then not >break things by not necessarily having to call particular methods >directly. So in SymmetricFunctions, if we need lex order, we call P = >Partitions(3, order='lex') and then iterate over P. (Hopefully that makes >sense...) +1 >- Element classes may be shared between different parents. One needs > to make sure that one does not affect by accident unrelated parents. > > Don't elements always have unique parents? Yes. But two elements with distinct parents may share the same class: sage: U = WeylGroup(["A",2]) sage: V = WeylGroup(["A",3]) sage: U.element_class is V.element_class True sage: U.element_class.foo = lambda self: 1 sage: V.an_element().foo() sage: U.element_class.foo = lambda self: 1 sage: V.an_element().foo() 1 So changing an option for the elements of one Weyl group will affect all other Weyl groups. > I have no experience with cython yet but I wouldn't have thought this > was a big problem because all that I am really doing to using optionable > methods as aliases for the real methods. The idea is that a method like > _repr_ simply becomes an alias for _repr_with_option and that changing > an option for _repr_ just changes which function it is an alias for. > >Couldn't we just do that with function >pointers? http://docs.cython.org/src/reference/language_basics.html Probably so. But then I guess you would need to predeclare in the Cython class each and every method that you might want to assign at some point. And this will use as many memory slots (besides, such changes requires to recompile all files that use that class, so we don't want to have such patches lying in the queue for long). Nicolas -- Nicolas M. Thiéry "Isil" http://Nicolas.Thiery.name/ -- You received this message because you are subscribed to the Google Groups "sage-combinat-devel" group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.