A possible slight addition to symbolic sum operations

64 views
Skip to first unread message

Emmanuel Charpentier

unread,
Apr 26, 2017, 2:35:30 AM4/26/17
to sage-support
Sage can (awkwardly) do some simplifications of symbolic sums. For example

sage: var("j,p", domain="integer")
(j, p)
sage: X,Y=function("X,Y")
sage: (sum(X(j),j,1,p)+sum(Y(j),j,1,p)).maxima_methods().sumcontract()
sum(X(j) + Y(j), j, 1, p)


but, to the best of my (limited) knowledge, the reverse operation, useful in sime situations (trivial example : derive maximum likelihood estimators of the parameters of some distributions) is not possible (in other words, sum does not distribute over +).

The needed function can be written in Sage :

def expand_sum(ex):
    ## Only way I found to denote the needed operator constants
    def init_consts():
        a=function("a")
        b,c,d=SR.var("b,c,d")
        op_sum=sum(a(b),b,c,d).operator()
        op_add=(c-b).operator()
        return(op_sum,op_add)
    ## Build a term of the result
    def treat_term(term,loopargs):
        L=copy(loopargs) ## Copy is needed, under penalty of side effects !!
        L.insert(0,term)
        return(apply(sum,L))
    op_sum,op_add=init_consts()
    if ex.parent() is not SR:return(ex)
    op=ex.operator()
    largs=ex.operands()
    if op is None:return(ex)
    if op is op_sum:
        fa=largs[0]
        op1=fa.operator()
        if op1 is op_add:
            ra=largs[1:]    # index variable and bounds
            return(sum(map(lambda t:treat_term(expand_sum(t),ra),
                           fa.operands())))
    ## Default case : recurse to ex arguments
    return(apply(op, map(expand_sum, largs)))


It can also be written in Maxima (or in lisp) and used via one of the Maxima interfaces :

expand_sum(ex):=block([sum_op,add_op,a,b,c,d],
  sum_op:op(sum(a(b),b,c,d)),
  add_op:op(c-b),
  if atom(ex)
  then ex
  else block([op1:op(ex), largs:args(ex)],
    if equal(op1,sum_op)
    and not(atom(largs[1]))
    and equal(op(args(ex)[1]), add_op)
    then block([fa:first(largs), ra:rest(largs), lres,z],
      lres:map(lambda([t],apply(sum,append([expand_sum(t)],ra))), args(fa)),
      lsum(z,z,lres))
    else apply(op1, map(expand_sum, largs))));


Both versions allow the needed expansion. In Sage :

sage: load("/home/charpent/Feuilles Sage brutes/expand_sum.sage")
sage: expand_sum(sum(X(j)+Y(j),j,1,p))
sum(X(j), j, 1, p) + sum(Y(j), j, 1, p)


(the Maxima version also works (not shown)). Hence a few questions :
  1. Did I oversee an existing way to do this ?
  2. Is that a worthwile addition to Sage ?
  3. Should it be implemented in Sage (probably as a method for SR), or via Maxima (like other sum functions) ?
  4. Should this be a special case of the expand() method ?
  5. Are there possible improvements (I think so : for example, I have been unable to find the "right" designation of the operators : op_sum might be sage.functions.other.symbolic_sum, but I found nothing usable for op_add, hence the ridiculous re-computation of these constants at each call...).

Sincerely,

--
Emmanuel Charpentier

Ralf Stephan

unread,
Apr 27, 2017, 2:55:46 AM4/27/17
to sage-support


On Wednesday, April 26, 2017 at 8:35:30 AM UTC+2, Emmanuel Charpentier wrote:
Sage can (awkwardly) do some simplifications of symbolic sums. For example

sage: var("j,p", domain="integer")
(j, p)
sage: X,Y=function("X,Y")
sage: (sum(X(j),j,1,p)+sum(Y(j),j,1,p)).maxima_methods().sumcontract()
sum(X(j) + Y(j), j, 1, p)


but, to the best of my (limited) knowledge, the reverse operation, useful in sime situations (trivial example : derive maximum likelihood estimators of the parameters of some distributions) is not possible (in other words, sum does not distribute over +).
...

(the Maxima version also works (not shown)). Hence a few questions :
  1. Did I oversee an existing way to do this ?
Nearly. SymPy can do these things via simplify and expand.  However, Sage cannot translate your sums into SymPy via sympify because 1. there is no conversion atm for Function_sum (trivial to fix), and 2. anonymous functions like X here cannot be translated either (not so trivial). I didn't check the backwards route but expect similar problems.
  1. Is that a worthwile addition to Sage ?
Of course.
  1. Should it be implemented in Sage (probably as a method for SR), or via Maxima (like other sum functions) ?
I would do like SymPy and put it as subfunction into expand() (check for existence of Function_sum then call). 
  1. Should this be a special case of the expand() method ?
Not a special case, a default service. 
  1. Are there possible improvements (I think so : for example, I have been unable to find the "right" designation of the operators : op_sum might be sage.functions.other.symbolic_sum, but I found nothing usable for op_add, hence the ridiculous re-computation of these constants at each call...).
 Yes, and sage.symbolic.operators.add_vararg.

Best,

Emmanuel Charpentier

unread,
Apr 30, 2017, 2:46:57 PM4/30/17
to sage-support
This is now Trac#22915, which needs discussion.

--
Emmanuel Charpentier

Emmanuel Charpentier

unread,
May 3, 2017, 11:11:58 AM5/3/17
to sage-support
See sage-devel for a better proposal.


--
Emmanuel Charpentier

Le mercredi 26 avril 2017 08:35:30 UTC+2, Emmanuel Charpentier a écrit :
Reply all
Reply to author
Forward
0 new messages