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 independent of each other because
> partitions are not fully integrated into the parent/element framework.
> 
> Please let me know what you think.
> 
> Cheers,
> Andrew
> 
> 
> ----
> 
> To save you looking at the patch here is the options method
> 
> # the keys of option_alias are aliases to options, or groups of options.
> option_alias = {'cmp':['__le__','__lt__','__ge__','__gt__'],
>                 'convention':['ferrers_diagram','_latex__diagram'],
>                 'display':['_repr_'],
>                 'latex':['_latex_']
>                 }
> 
> def options(self, *option, **options):
>     r"""
>     Print and set options for the element class of ``self``.
> 
>     Global options for the method ``foo`` of the element_class are methods
>     with names of the form ``foo_<option name>``. For example, for
>     :class:`Partition_class` the following optional methods for ``_repr_``
>     are currently implemented::
> 
>     -_repr__list(self):
>     -_repr__exp(self):
>     -_repr__exp_high(self):
>     -_repr__compact(self):
>     -_repr__compact_high(self):
>     -_repr__diagram(self):
> 
>     The global options can changed, and the current options printed, using 
> ``self.options``:
> 
>     EXAMPLES::
> 
>         sage: mu=Partition([4,4,3,2,1,1,1]); mu
>         [4, 4, 3, 2, 1, 1, 1]
>         sage: Partitions(4).options('_repr_')
>         list
>         sage: Partitions(4).options(_repr_='exp'); mu
>         1^3, 2, 3, 4^2
>         sage: Partitions(4).options(_repr_='exp_high'); mu
>         4^2, 3, 2, 1^3
>         sage: Partitions(4).options(_repr_='compact'); mu
>         1^3,2,3,4^2
>         sage: Partitions(4).options(_repr_='compact_high'); mu
>         4^2,3,2,1^3
>         sage: Partitions(4).options(_repr_='diagram');
>         sage: Partitions(4).options(convention='french'); mu
>         *
>         *
>         *
>         **
>         ***
>         ****
>         ****
>         ****
>         ****
>         sage: Partitions(4).options(convention='endlish'); mu
>         ****
>         ****
>         ***
>         **
>         *
>         *
>         *
>         sage: Partitions(4).options(cmp='dominance')
>         sage: Partition([3,1,1,1])>Partition([2,2,2])
>         False
>         sage: Partitions(4).options(cmp='lex')
>         sage: Partition([3,1,1,1])>Partition([2,2,2])
>         True
>         sage: Partitions(4).options(display='exp_low')
>         Traceback (most recent call last):
>         ...
>         ValueError: exp_low is not a valid option for display
>        
> 
>     The dictionary ``self.option_alias`` defines aliases for options
>     so that the different options can be given more user friendly names. For 
> example,
>     ``display`` is an option for ``_repr__``::
> 
>     EXAMPLES::
> 
>         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]
> 
>     The values of ``self.option_alias`` are lists of strings so that one
>     option can change several different methods. For example, the ``cmp``
>     option redefines the behaviour of the four comparison methods
>     ``__le__``, ``__lt__``, ``__ge__`` and ``__gt__``. Note that we need
>     need to append '__' to all method names which begin with '__' otherwise
>     they are treated as inaccessible private methods.
>     """
>     # todo: when called with no arguments a list of all options should be 
> printed,
>     #           ...probably needs to be done via something like 
> ``self.options_doc``
>     # --
>     # print the current settings for the options in ``option``
>     for opt in option: 
>         try:
>             opt_name=self.option_alias.get(opt,[opt])[0]
>             current_opt=getattr(self.element_class,opt_name).__name__
>             current_opt=current_opt[len(opt_name)+1:]
>             if opt_name[:2]=='__':      # some trickery to avoid private 
> classes
>                 current_opt=current_opt[:-2]  # remove trailing '__'
>             print current_opt[len(opt_name):]
>         except AttributeError:
>             raise ValueError, '%s is not a valid option' % opt
>     # change the option settings for the options in ``options`` 
>     for opt in options:
>         for opt_name in self.option_alias.get(opt,[opt]):
>             if opt_name[:2]=='__':   # some trickery to avoid private classes
>                 new_opt=opt_name+'_'+options[opt]+'__'
>             else:
>                 new_opt=opt_name+'_'+options[opt]
>             if hasattr(self.element_class,new_opt):
>                 new_opt=getattr(self.element_class,new_opt)
>                 setattr(self.element_class, opt_name, new_opt)
>             else:
>                 raise ValueError, '%s is not a valid option for %s' % 
> (options[opt], opt)

-- 
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.

Reply via email to