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

2012-11-05 Thread Nicolas M. Thiery
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 nthi...@users.sf.net
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-28 Thread Nicolas M. Thiery
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 nthi...@users.sf.net
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-28 Thread Andrew Mathas
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

2012-10-28 Thread Vincent Delecroix
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

2012-10-28 Thread Travis Scrimshaw
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.



[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 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 nthi...@users.sf.net
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.