#7620: Inconsistent ordering when composing functors
--------------------------+-------------------------------------------------
   Reporter:  SimonKing   |       Owner:  nthiery                  
       Type:  defect      |      Status:  new                      
   Priority:  critical    |   Milestone:  sage-4.3                 
  Component:  categories  |    Keywords:  Functor composition order
Work_issues:              |      Author:  Simon King               
   Upstream:  N/A         |    Reviewer:                           
     Merged:              |  
--------------------------+-------------------------------------------------
 Apparently the composition of construction functors is inconsistent.

 '''__Examples__'''

 {{{
 sage: from sage.categories.pushout import construction_tower
 sage: P = QQ['x','y']
 sage: construction_tower(P)
 [(None, Multivariate Polynomial Ring in x, y over Rational Field),
  (MPoly[x,y], Rational Field),
  (FractionField, Integer Ring)]
 }}}

 Let us see what the product of the two functors above does:
 {{{
 sage: F = prod([X[0] for X in construction_tower(P) if X[0] is not None])
 sage: F
 MPoly[x,y](FractionField(...))
 }}}

 OK, that's reasonable, we have {{{F1*F2(X) = F1(F2(X))}}}.

 But in a slightly more complicated example, the product gets messed up:

 {{{
 sage: P = QQ['x'].fraction_field()['y']
 sage: construction_tower(P)
 [(None,
   Univariate Polynomial Ring in y over Fraction Field of Univariate
 Polynomial Ring in x over Rational Field),
  (Poly[y],
   Fraction Field of Univariate Polynomial Ring in x over Rational Field),
  (FractionField, Univariate Polynomial Ring in x over Rational Field),
  (Poly[x], Rational Field),
  (FractionField, Integer Ring)]
 }}}

 Now we do the same product as above:
 {{{
 sage: F = prod([X[0] for X in construction_tower(P) if X[0] is not None])
 sage: F
 FractionField(Poly[x](Poly[y](FractionField(...))))
 }}}

 So, apparently the order is perturbed.

 Related with it, it seems counter-intuitive that the product over the
 expansion of a functor does not return the functor:

 {{{
 sage: F
 FractionField(Poly[x](Poly[y](FractionField(...))))
 sage: prod(F.expand())
 FractionField(Poly[x](FractionField(Poly[y](...))))
 }}}

 '''__Conventions__'''

 Possible conventions on the order of composition are:
 {{{F1*F2(X)=F1(F2(X))}}} and {{{F1*F2(X)=F2(F1(X))}}}

 My personal preference is {{{F1*F2(X)=F1(F2(X))}}}, and it happens to be
 used in the generic multiplication method of ConstructionFunctor:

 {{{
 class ConstructionFunctor(Functor):
     def __mul__(self, other):
         if not isinstance(self, ConstructionFunctor) and not
 isinstance(other, ConstructionFunctor):
             raise CoercionException, "Non-constructive product"
         return CompositConstructionFunctor(other, self)
 }}}

 So, I think the convention {{{F1*F2(X)=F1(F2(X))}}} should be (or is
 already) the official Sage convention.

 '''__About expand()__'''

 {{{
 class CompositConstructionFunctor(ConstructionFunctor):
     def expand(self):
         return self.all
 }}}
 Since the convention {{{F1*F2(X)=F1(F2(X))}}} is used, this method should
 return {{{list(reversed(self.all))}}}.

 '''__Wrong multiplication order__'''

 {{{
 class CompositConstructionFunctor(ConstructionFunctor):
     def __init__(self, *args):
         self.all = []
         for c in args:
             if isinstance(c, list):
                 self.all += c
             elif isinstance(c, CompositConstructionFunctor):
                 self.all += c.all
             else:
                 self.all.append(c)
         Functor.__init__(self, self.all[0].domain(),
 self.all[-1].codomain())
     def __mul__(self, other):
         if isinstance(self, CompositConstructionFunctor):
             all = self.all + [other]
         else:
             all = [self] + other.all
         return CompositConstructionFunctor(*all)
 }}}

 That means {{{self}}} is applied ''before'' {{{other}}}!

 '''__Suggested fix__'''

 1. I suggest that {{{CompositConstructionFunctor.expand()}}} returns
 {{{list(reversed(self.all))}}}. Then, we would have
 {{{prod(F.expand())==F}}}.

 2. Change the order of {{{self}}} and {{{other}}} in the multiplication
 method of {{{CompositFunctor}}}

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/7620>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

--

You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.


Reply via email to