[sage-combinat-devel] Global options for elements set by their parents

2012-10-27 Thread Andrew Mathas
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 frameworkfor 
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_']
   

Re: [sage-combinat-devel] Global options for elements set by their parents

2012-10-27 Thread Anne Schilling
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

2012-10-27 Thread Nicolas M. Thiery
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

2012-10-27 Thread Andrew Mathas


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