Opened 10 years ago

Last modified 9 years ago

#13605 closed enhancement

Partition options and cleanup partitions documentation — at Version 6

Reported by: Travis Scrimshaw Owned by: Sage Combinat CC user
Priority: major Milestone: sage-5.8
Component: combinatorics Keywords: partition, options, output, days45
Cc: Sage Combinat CC user Merged in:
Authors: Travis Scrimshaw Reviewers:
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: #13074 Stopgaps:

Status badges

Description (last modified by Travis Scrimshaw)

Adding a Partitions.options() method which sets (globally) options for partitions as noted in #5439 - http://wiki.sagemath.org/combinat/Weirdness similar to PermutationOptions(). This will also affect tableau classes and friends. Additionally this will also clean up some of the documentation/code in the respective files.

Change History (6)

comment:1 Changed 10 years ago by Nicolas M. Thiéry

Thanks for opening this ticket, and even better working on it :-)

For the syntax, I would prefer something like:

   Partitions.options(...)

in order to not polute the global namespace. It's relatively consistent with what's done in a couple other places (e.g. CombinatorialFreeModule?). Of course, PermutationOptions? should be renamed to Permutations.options as well (and by the way the l2r option of PermutationOptions? should be deprecated because global options should not change the semantic).

Some places use set_options; options is more Pythonic; it makes it explicit that the same gadget can be used to set and get the options.

Cheers,

Nicolas

comment:2 Changed 10 years ago by Andrew Mathas

Hi Travis,

I like the concept of various methods being controlled by global options, however, I think that it would be much better if all of the methods provided by the options were also accessible directly as methods to the class.

In fact, for me this is vital. The reason I introduced the compact option to _repr_ for partitions, tableaux and their tupled variants is that I need this option in order to improve the readability of the output from some external code that I have for working inside the graded Specht modules of arbitrary level (to be made publicly available in sage some time next year).

Consider the following:

sage: S=GradedSpechtModule(3,[4,4,3,2,1]); S
Graded Specht module S(4^2,3,2,1) with e=3 over the Integer Ring
sage: S.an_element()
  2*[1,6,10,13/2,7,11,14/3,8,12/4,9/5] 
+ 2*[1,5,10,13/2,7,11,14/3,8,12/4,9/6] 
+ 3*[1,4,10,13/2,7,11,14/3,8,12/5,9/6]
sage: S.an_element().homogeneous_components()
{0: 2*[1,5,10,13/2,7,11,14/3,8,12/4,9/6], 
 1: 2*[1,6,10,13/2,7,11,14/3,8,12/4,9/5], 
-1: 3*[1,4,10,13/2,7,11,14/3,8,12/5,9/6]}
sage: S.an_element().y(3)                    
-3*[1,3,10,13/2,7,11,14/4,8,12/5,9/6]

The elements of this Specht module are indexed, as usual, by standard tableaux which are compactly printed here inbetween brackets [...]. Without the compact=True option which is passed the _repr_ methods the output here would be almost unreadable. (It's still not that easy in this example, but compare with the output of the default _repr_ methods!:)

The way your partition options code is currently written many of the individual options are coded "inline" inside the optionable methods. This means that the only way for external code to access the different variants of an optionable method is to artificially tweak partition_options, whilst making sure to reset it to its original state after the external code has finished doing whatever it was doing.

It would be more useful, I think, if each optionable variant was directly accessible and accessible in a systematic way. This would allow external code, which might have its own options, to easily access the different variants of the method. Perhaps the best way of doing this would be something like the following:

def _repr_(self):
    try:
        repr=getattr(self, '_repr_'+ self.parent().options['display'])
    except AttributeError:
        raise ValueError, "Invalid display option"
    return repr()

def _repr_list(self):
    return '[%s]' % ', '.join('%s'%m for m in self)

def _repr_exp(self):
    exp = self.to_exp()
    return '%s' % ', '.join('%s%s' % (m+1, '' if e==1 else '^%s'%e)
                                     for (m,e) in enumerate(exp) if e > 0)

def _repr_diagram(self):
    return self.ferrers_diagram()

def _repr_compact(self):
    exp=self.to_exp()[::-1]  # reversed list of exponents
    M=max(self)
    return '%s' % ','.join('%s%s' % (M-m, '' if e==1 else '^%s'%e)
                                     for (m,e) in enumerate(exp) if e>0)

This model has the advantage of being easy to read and very easy to extend: you simply add another _repr_X method and you are done. A better approach might be to write a generic optionable_method function and then simply define

def _repr_(self):
    '''
    It's probably essential to give documentation describing 
    possible global options.
    '''
    return optionable_method(self, '_repr_', option_name='display')

where option_name defaults to name of the method but which we want to override in this case. (Perhaps it is subjective that this is better?) This would allow global options to be used uniformly across all classes. If necessary, passing arguments to the optionable methods would be straightforward too.

As a final note, can there please be an honest compact variant of _repr_ which returns a string with no spaces and is as short as possible but still readable? I want this for use inside code like the above which uses partitions to index objects. Of course, such code could do this itself but it seems more sensible to have this done inside Partition_class. I have several different examples/contexts where I want to do this and presumably other people will too?

Cheers,
Andrew

ps I am happy to help in getting all of this to work if you think these ideas are reasonable

Last edited 10 years ago by Andrew Mathas (previous) (diff)

comment:3 Changed 10 years ago by Travis Scrimshaw

I will separate them out into separate functions. This is probably a cleaner/more flexable way of doing things (and I believe the extra function call is relatively small compared to the actual cost of printing). I will also add a compact option to the display output options with no spaces.

Best,
Travis

comment:4 in reply to:  3 Changed 10 years ago by Andrew Mathas

Thanks Travis!

I was thinking that the extra overhead wouldn't be significant, however, I was thinking of methods like _repr_. If this is adopted as a general framework then for methods like_cmp_ the overhead will probably be too high. To get around this it would be better to take the option parsing out of the individual methods and instead do it only once when the options are changed.

I am really thinking of a general options framework for parent/element classes here. In the parents, there would be a generic method which looks something like this:

def options(self, *option, **options):
    # print the current settings for the options in ``option``
    for opt in option:  
        try:
            print getattr(self.element_class,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:
        new_opt=option+'_'+options[opt]
        if hasattr(self.element_class,new_opt):
            self.element_class.__setattr__(opt, new_opt)
        else:
            raise ValueError, '%s is not a valid option for %s' % (options[opt], opt)

and, in the element classes, the different options would be coded something like this:

def _repr__list(self):
    return '[%s]' % ', '.join('%s'%m for m in self)

def _repr__exp(self):
    exp = self.to_exp()
    return '%s' % ', '.join('%s%s' % (m+1, '' if e==1 else '^%s'%e)
                                     for (m,e) in enumerate(exp) if e > 0)

def _repr__diagram(self):
    return self.ferrers_diagram()

_repr_= _repr__list  # default option for _repr_

Why don't I try and implement this and see how it works for a few different examples? Perhaps it's safer to discuss this first on sage-combinat. What do you think?

comment:5 Changed 10 years ago by Travis Scrimshaw

I like the concept, however how would you change the option function on those elements which have already been created? I currently don't see a way to make this feasible. This probably would be best discussed on sage-combinat-devel.

Best,
Travis

comment:6 Changed 10 years ago by Travis Scrimshaw

Dependencies: #13072#13074
Description: modified (diff)

This will also incorporate TableauTuples.

Note: See TracTickets for help on using tickets.