Menu

#3605 Variable confusion in function handling Taylor series

None
closed
nobody
5
2021-09-19
2020-01-03
No

When a local variable in a function has the same name as the variable in a Taylor series being an argument to this function, an error can occur. In the following example, the function works correctly in the first case (the Taylor series uses the variable y) but not in the second case (with the variable x).

(%i1) display2d: false $
(%i2) test(f) := block([i:taylorinfo(f)[1]], sum(coeff(f, i[1], x) * i[1]^x, x, 0, i[3]));
(%o2) test(f):=block([i:taylorinfo(f)[1]],sum(coeff(f,i[1],x)*i[1]^x,x,0, i[3]))
(%i3) test(taylor(cos(y), y, 0, 4));
(%o3) (y^4-12*y^2+24)/24
(%i4) test(taylor(cos(x), x, 0, 4));
verbify: argument must be a symbol or a string; found: 1
#0: test(f=1-x^2/2+x^4/24)
 -- an error. To debug this try: debugmode(true);

Discussion

  • Robert Dodier

    Robert Dodier - 2020-01-04
    • labels: --> sum, taylor, scope
     
  • Robert Dodier

    Robert Dodier - 2020-01-04

    Thomas, there are 2 interacting effects here. One is more or less a bug and the other is a long-standing feature.

    The bug is that sum has a nonstandard evaluation policy; the summand and index are handled in a way which is not easily described, and different from other functions in Maxima. (You can blame me for that, I was the last person to work on sum, some years ago.)

    The long-standing feature is that the x which appears in test is the same symbol x which appears in the taylor output, and there is not yet a way to ensure that they are distinct. I am working on implementing lexical scope for symbols, which I believe could be ready some time this year; one could make use of that to get the correct output.

    Given all that, there are several ways to work around the problem and get the correct output. I find that these all seem to work:

    test2(f) := block([i:taylorinfo(f)[1]], apply("+", makelist(coeff(f, i[1], x)*i[1]^x, x, 0, i[3])))$
    
    test3(f) := block([i:taylorinfo(f)[1]], lsum(xx, xx, makelist(coeff(f, i[1], x)*i[1]^x, x, 0, i[3])))$
    
    test4(f) := block([i:taylorinfo(f)[1]], sum(coeff(f, i[1], x%)*i[1]^x%, x%, 0, i[3]))$
    

    test4 is maybe the simplest one -- just replace the summation index by a symbol (here I've chosen x%) which is unlikely to coincide with a symbol appearing in the input.

     
  • Leo Butler

    Leo Butler - 2020-01-09

    There are a number of ways to get around your particular problem, but as Robert writes, the root cause is a lack of lexical scope for some kinds of function.
    I wrote a package a while ago to work around the lack of lexical scope in Maxima. It is based on Robert's ideas.

    with_gensyms

    $ maxima --init=/dev/null
    
    Maxima 5.43.0 http://maxima.sourceforge.net
    using Lisp GNU Common Lisp (GCL) GCL 2.6.12
    Distributed under the GNU Public License. See the file COPYING.
    Dedicated to the memory of William Schelter.
    The function bug_report() provides bug reporting information.
    (%i1) load(with_gensyms);
    (%o1)                 /home/work/.maxima/with_gensyms.mac
    (%i2) test(f):=block([i:taylorinfo(f)[1]],sum(coeff(f,i[1],x)*i[1]^x,x,0, i[3]));
                                                                      x
    (%o2) test(f) := block([i : taylorinfo(f) ], sum(coeff(f, i , x) i , x, 0, i ))
                                             1                 1      1         3
    (%i3) test(taylor(cos(x), x, 0, 4));
    
    verbify: argument must be a symbol or a string; found: 1
    #0: test(f=1-x^2/2+x^4/24)
     -- an error. To debug this try: debugmode(true);
    (%i4) test(f):>block([i:taylorinfo(f)[1]],sum(coeff(f,i[1],x)*i[1]^x,x,0, i[3]));
    (%o4) test($f) := block([$i : taylorinfo($f) ], 
                                                1
                                                                   $x
                                          sum(coeff($f, $i , $x) $i  , $x, 0, $i ))
                                                          1        1            3
    (%i5) test(taylor(cos(x), x, 0, 4));
                                     4       2
                                    x  - 12 x  + 24
    (%o5)/R/                        ---------------
                                          24
    (%i6) test(taylor(cos(y), y, 0, 4));
                                     4       2
                                    y  - 12 y  + 24
    (%o6)/R/                        ---------------
                                          24
    (%i7)
    

    %i2 defines the function using the := operator, %i4 uses the :> operator from with_gensyms.

     
  • Robert Dodier

    Robert Dodier - 2021-09-19
    • status: open --> closed
     
  • Robert Dodier

    Robert Dodier - 2021-09-19

    I've implemented a change to avoid an error. (I'm not seeing an error from verbify but rather it's a Lisp error. Not sure why they're different.) The change I made doesn't fully resolve the variable confusion, which is possible, I believe, only if sum is modified. That said, I think it's reasonable to consider the error fixed, given the current definition of sum. Here's what I said about it in the commit log.

    commit 27066b

    In summation code, punt to MAXIMA-SUBSTITUTE from SUBST-IF-NOT-FREEOF.

    This avoids a Lisp error for MRAT expressions, and is more correct in general.

    This commit helps the test case for SF bug #3605 avoid the error and get to a well-defined result, although it does not change the larger problem of the conflation of symbols in global and local contexts.

    I believe the behavior with this commit is the best that can be achieved short of changing the evaluation policy of sum (namely to substitute the summation index before evaluating the summand). That is appealing since it is more consistent and therefore predictable, however, it would imply that e.g. e: 2*k; sum(e, k, 1, 3); returns 6*k instead of 12.

    Compare makelist and integrate here -- makelist(e, k, 1, 3) returns [2*k, 2*k, 2*k], while integrate(e, k, 1, 3) returns 8. So there is precedent for either option.

    With all this in mind, I will say that this commit fixes SF bug #3605: "Variable confusion in function handling Taylor series"

     

Log in to post a comment.