rtoy / maxima

A Clone of Maxima's repo
Other
0 stars 0 forks source link

apply(sum,...) behaves as if it is apply(sum,ev(...)) #519

Open rtoy opened 1 week ago

rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:24:53 Created by satoshi_adachi on 2009-11-11 07:51:01 Original: https://sourceforge.net/p/maxima/bugs/1814


Dear Developers of Maxima,

This letter informs you that sum() and product() behave strangely when they are used as the first argument of apply().

The behavior actually observed for apply(sum, LIST_OF_ARGUMENTS) is not the expected one for it but coincides with the expected one for apply(sum, ev(LIST_OF_ARGUMENTS)).

The same behavior is observed for apply(product, LIST_OF_ARGUMENTS).

In my understanding, this is thought to be a bug for sum() and product().

Below, I will explain this behavior of sum() and product().

------------------------------------------------------------------------------- (1) Normal behavior of apply() -------------------------------------------------------------------------------

The following program demonstrates the normal behavior of apply():

............................................................................... /* * behavior_of_apply.maxima: * * S.Adachi 2009/11/10 */

display2d:false;

arg_lst:[x];

OK1:apply(sin, arg_lst);

x:%pi/2;

OK2:apply(sin, arg_lst);

OK3:apply(sin, ev(arg_lst));

/* END */ ...............................................................................

The result of execution is as follows:

............................................................................... Maxima 5.18.1 http://maxima.sourceforge.net Using Lisp GNU Common Lisp (GCL) GCL 2.6.7 (aka GCL) 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) batch(behavior_of_apply.maxima)

batching #p/Volumes/HFS+2/home/adachi/work/406/behavior_of_apply.maxima (%i2) display2d : false (%o2) false (%i3) arg_lst:[x] (%o3) [x] (%i4) OK1:apply(sin,arg_lst) (%o4) sin(x) (%i5) x:%pi/2 (%o5) %pi/2 (%i6) OK2:apply(sin,arg_lst) (%o6) sin(x) (%i7) OK3:apply(sin,ev(arg_lst)) (%o7) 1 (%o8) "behavior_of_apply.maxima" ...............................................................................

Please look at (%i6) and (%o6). At this point, arg_lst is equal to [x] and thereby the result of apply(sin, arg_lst) becomes sin(x). Even though the variable x is given the value %pi/2, this value is not used when apply() is called with the arguments sin and [x].

This is the normal expected behavior of apply().

If we want [x] to be evaluated in the current environment, we have to use ev(arg_lst) instead of arg_lst (see (%i7) and (%o7)).

------------------------------------------------------------------------------- (2) Strange behavior of sum() when it is used as 1st argument of apply() -------------------------------------------------------------------------------

The following program demonstrates the strange behavior of sum() when it is used as the first argument of apply():

............................................................................... /* * strange_behavior_of_sum.maxima: * * S.Adachi 2009/11/10 */

display2d:false;

arg_lst:[f(i), i, 1, n];

OK1:apply(sum, arg_lst);

n:4;

STRANGE:apply(sum, arg_lst);

OK2:apply(sum, ev(arg_lst));

/* END */ ...............................................................................

The result of execution is as follows:

............................................................................... Maxima 5.18.1 http://maxima.sourceforge.net Using Lisp GNU Common Lisp (GCL) GCL 2.6.7 (aka GCL) 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) batch(strange_behavior_of_sum.maxima)

batching #p/Volumes/HFS+2/home/adachi/work/406/strange_behavior_of_sum.maxima (%i2) display2d : false (%o2) false (%i3) arg_lst:[f(i),i,1,n] (%o3) [f(i),i,1,n] (%i4) OK1:apply(sum,arg_lst) (%o4) 'sum(f(i),i,1,n) (%i5) n:4 (%o5) 4 (%i6) STRANGE:apply(sum,arg_lst) (%o6) f(4)+f(3)+f(2)+f(1) (%i7) OK2:apply(sum,ev(arg_lst)) (%o7) f(4)+f(3)+f(2)+f(1) (%o8) "strange_behavior_of_sum.maxima" ...............................................................................

In this example, arg_lst is set to [f(i),i,1,n] at (%i3). After arg_lst is prepared, n is set to 4 at (%i5). At (%i6), apply(sum,arg_lst) is calculated. At (%i7), apply(sum,ev(arg_lst)) is calculated. Both results become f(4)+f(3)+f(2)+f(1) as are seen at (%o6) and (%o7). This result is expected for apply(sum,ev(arg_lst)) but is never for apply(sum,arg_lst). The result expected for apply(sum,arg_lst) is 'sum(f(i),i,1,n).

Namely, apply(sum,arg_lst) actually behaves as if it is apply(sum,ev(arg_lst)).

I think that this is a bug.

------------------------------------------------------------------------------- (3) This bug of sum() is serious for programming. -------------------------------------------------------------------------------

This bug of sum() when it is supplied to the first argument of apply() is very serious one for writing programs.

The bug causes a serious confusion of the object language and the observation language (programming language).

To demonstrate how serious this bug is, I have prepared a toy program, which traces the process of calculation for a given expression. It is as follows:

............................................................................... /* * demonstration_of_strangeness_of_sum.maxima: * * S.Adachi 2009/11/10 */

display2d:false;

trace_calc(X) := trace_calc_sub(X, 0);

trace_calc_sub(X, indent) := block([res], if (atom(X)) then ( print(smake(indent, " "),"[ATOM]:",X), res:X ) else ( block([n,i,arg_lst,a,b], print(smake(indent, " "),"[FUNC]: OP =",op(X)), arg_lst:[], n:length(X), for i:1 thru n do ( a:part(X,i), print(smake(indent, " "),"[FUNC]: ARG(",i,") = ",a," -->"), b:trace_calc_sub(a,indent+1), arg_lst:append(arg_lst,[b]) ), res:apply(op(X),arg_lst), print(smake(indent, " "),"[FUNC]: RES = ",res) ) ), res);

ex1_OK:a*b*F(n)+c*G(n);

ex1_tr_OK:trace_calc(ex1_OK);

ex2_OK:a*b*sum(f(i),i,1,n)+c*product(g(i),i,1,n);

ex2_tr_BAD:trace_calc(ex2_OK);

/* END */ ...............................................................................

The result of execution is as follows:

............................................................................... Maxima 5.18.1 http://maxima.sourceforge.net Using Lisp GNU Common Lisp (GCL) GCL 2.6.7 (aka GCL) 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) batch(demonstration_of_strangeness_of_sum.maxima)

batching #p/Volumes/HFS+2/home/adachi/work/406/demonstration_of_strangeness_of_sum.maxima (%i2) display2d : false (%o2) false (%i3) trace_calc(X):=trace_calc_sub(X,0) (%o3) trace_calc(X):=trace_calc_sub(X,0) (%i4) trace_calc_sub(X,indent):=block([res], if atom(X) then (print(smake(indent," "),"[ATOM]:",X),res:X) else block([n,i,arg_lst,a,b], print(smake(indent," "),"[FUNC]: OP =", op(X)),arg_lst:[],n:length(X), for i thru n do (a:part(X,i), print(smake(indent," "), "[FUNC]: ARG(",i,") = ",a, " -->"), b:trace_calc_sub(a,indent+1), arg_lst:append(arg_lst,[b])), res:apply(op(X),arg_lst), print(smake(indent," "),"[FUNC]: RES = ", res)),res) (%o4) trace_calc_sub(X,indent):=block([res], if atom(X) then (print(smake(indent," "),"[ATOM]:",X),res:X) else block([n,i,arg_lst,a,b], print(smake(indent," "),"[FUNC]: OP =", op(X)),arg_lst:[],n:length(X), for i thru n do (a:part(X,i), print(smake(indent," "), "[FUNC]: ARG(",i,") = ",a, " -->"), b:trace_calc_sub(a,indent+1), arg_lst:append(arg_lst,[b])), res:apply(op(X),arg_lst), print(smake(indent," "),"[FUNC]: RES = ", res)),res) (%i5) ex1_OK:a*b*F(n)+c*G(n) (%o5) c*G(n)+a*b*F(n) (%i6) ex1_tr_OK:trace_calc(ex1_OK) [FUNC]: OP = + [FUNC]: ARG( 1 ) = c*G(n) --> [FUNC]: OP = * [FUNC]: ARG( 1 ) = c --> [ATOM]: c [FUNC]: ARG( 2 ) = G(n) --> [FUNC]: OP = G [FUNC]: ARG( 1 ) = n --> [ATOM]: n [FUNC]: RES = G(n) [FUNC]: RES = c*G(n) [FUNC]: ARG( 2 ) = a*b*F(n) --> [FUNC]: OP = * [FUNC]: ARG( 1 ) = a --> [ATOM]: a [FUNC]: ARG( 2 ) = b --> [ATOM]: b [FUNC]: ARG( 3 ) = F(n) --> [FUNC]: OP = F [FUNC]: ARG( 1 ) = n --> [ATOM]: n [FUNC]: RES = F(n) [FUNC]: RES = a*b*F(n) [FUNC]: RES = c*G(n)+a*b*F(n) (%o6) c*G(n)+a*b*F(n) (%i7) ex2_OK:a*b*sum(f(i),i,1,n)+c*product(g(i),i,1,n) (%o7) c*'product(g(i),i,1,n)+a*b*'sum(f(i),i,1,n) (%i8) ex2_tr_BAD:trace_calc(ex2_OK) [FUNC]: OP = + [FUNC]: ARG( 1 ) = c*'product(g(i),i,1,n) --> [FUNC]: OP = * [FUNC]: ARG( 1 ) = c --> [ATOM]: c [FUNC]: ARG( 2 ) = 'product(g(i),i,1,n) --> [FUNC]: OP = product [FUNC]: ARG( 1 ) = g(i) --> [FUNC]: OP = g [FUNC]: ARG( 1 ) = i --> [ATOM]: i [FUNC]: RES = g(i) [FUNC]: ARG( 2 ) = i --> [ATOM]: i [FUNC]: ARG( 3 ) = 1 --> [ATOM]: 1 [FUNC]: ARG( 4 ) = n --> [ATOM]: n [FUNC]: RES = 'product(g(i),i,1,4) [FUNC]: RES = c*'product(g(i),i,1,4) [FUNC]: ARG( 2 ) = a*b*'sum(f(i),i,1,n) --> [FUNC]: OP = * [FUNC]: ARG( 1 ) = a --> [ATOM]: a [FUNC]: ARG( 2 ) = b --> [ATOM]: b [FUNC]: ARG( 3 ) = 'sum(f(i),i,1,n) --> [FUNC]: OP = sum [FUNC]: ARG( 1 ) = f(i) --> [FUNC]: OP = f [FUNC]: ARG( 1 ) = i --> [ATOM]: i [FUNC]: RES = f(i) [FUNC]: ARG( 2 ) = i --> [ATOM]: i [FUNC]: ARG( 3 ) = 1 --> [ATOM]: 1 [FUNC]: ARG( 4 ) = n --> [ATOM]: n [FUNC]: RES = 'sum(f(i),i,1,4) [FUNC]: RES = a*b*'sum(f(i),i,1,4) [FUNC]: RES = c*'product(g(i),i,1,4)+a*b*'sum(f(i),i,1,4) (%o8) c*'product(g(i),i,1,4)+a*b*'sum(f(i),i,1,4) (%o9) "demonstration_of_strangeness_of_sum.maxima" ...............................................................................

This expected result at (%o8) is c*'product(g(i),i,1,n)+a*b*'sum(f(i),i,1,n).

But the calculated result is c*'product(g(i),i,1,4)+a*b*'sum(f(i),i,1,4).

Namely, n is accidentally replaced by 4. This strange result is caused by the coincidence of the names of the variable n in the observation language (programming language) and the variable n in the object language (given expression).

The value of the variable n used in the program is accidentally transferred to the variable n in the object expression.

------------------------------------------------------------------------------- (4) Strange behavior of product() when it is used as 1st argument of apply() -------------------------------------------------------------------------------

As is seen in the demonstration of (3), product() also has the same bug as sum() when it is supplied to the first argument of apply().

I do not know when this behavior of sum() and product() was brought into the code.

It might be some relatively recent time. In this case, this behavior could be called a bug.

Or, the behavior might originate at a long time ago in the code. In this case, you may say that this is not a bug but is a part of ''specification'' of Maxima. Even if you may, this is a serious inconsistency in Maxima and lets programming in Maxima be more difficult and be ugly since some workaround is necessary.

I hope that this bug (in my understanding) will be fixed in future.

Sincerely yours,

Satoshi Adachi

rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:24:54 Created by crategus on 2009-11-14 16:36:24 Original: https://sourceforge.net/p/maxima/bugs/1814/#6fc1


The function apply allows evaluates its arguments. This is the expected and the documented behaviour.

(%i1) args:[f(i),i,0,n]; (%o1) [f(i),i,0,n]

The variables of the list of arguments have not values:

(%i2) apply('sum,args); (%o2) 'sum(f(i),i,0,n)

Set the variable n:

(%i3) n:4; (%o3) 4

The variable n now evaluates to the number 4:

(%i4) [f(i),i,0,n]; (%o4) [f(i),i,0,4]

apply evaluates its arguments too and the function sum evaluates the expression for an upper bound n:4:

(%i6) apply('sum,args); (%o6) f(4)+f(3)+f(2)+f(1)+f(0)

It is not possible to quote the argument:

(%i8) apply('sum,[f(i),i,0,'n]); (%o8) f(4)+f(3)+f(2)+f(1)+f(0)

Setting the status of this bug report to pending and the resolution to invalid.

Dieter Kaiser

rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:24:58 Created by crategus on 2009-11-14 16:36:24 Original: https://sourceforge.net/p/maxima/bugs/1814/#9510


rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:25:01 Created by sf-robot on 2009-11-29 02:20:09 Original: https://sourceforge.net/p/maxima/bugs/1814/#3a4e


This Tracker item was closed automatically by the system. It was previously set to a Pending status, and the original submitter did not respond within 14 days (the time period specified by the administrator of this Tracker).

rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:25:05 Created by sf-robot on 2009-11-29 02:20:09 Original: https://sourceforge.net/p/maxima/bugs/1814/#09f4


rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:25:08 Created by robert_dodier on 2023-01-04 03:00:11 Original: https://sourceforge.net/p/maxima/bugs/1814/#b831


rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:25:11 Created by robert_dodier on 2023-01-04 03:00:11 Original: https://sourceforge.net/p/maxima/bugs/1814/#4199


Looks like a valid bug report to me. There are two issues here, (1) nonstandard evaluation by sum, and (2) Maxima doesn't distinguish global n from local n.

Problem (2) is fixed by lexical scope which I'm working on now. Fixing problem (1) is probably more complex because sum has had nonstandard evaluation for a long time, so fixing it now means changing expectations. But maybe we should do that. In any event, we could review sum and try to fix this one bug.

rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:25:15 Created by macrakis on 2023-01-04 16:46:03 Original: https://sourceforge.net/p/maxima/bugs/1814/#9f09


The effect of apply on functions with non-standard evaluation seems poorly defined. For example, why does apply('quote,'[print(3)]) return quote(print(3)) (the same as funmake) whereas quote(print(3)) returns print(3)?

rtoy commented 1 week ago

Imported from SourceForge on 2024-07-03 00:25:19 Created by macrakis on 2023-01-05 15:28:30 Original: https://sourceforge.net/p/maxima/bugs/1814/#15c8


This is not a bug. Many functions which quote their arguments do so because they need to evaluate their arguments in special contexts; not just sum and product, but also makelist, etc.

For example, i:99$ sum(i,i,1,3) keeps the second argument quoted (ignoring the global value 99) and only evaluates the first argument in a context where i is bound locally.

In effect, sum( expr, index, ... ) is syntactic sugar for sum( lambda([index], expr), ...). Unfortunately, Maxima isn't consistent about this. For example, although sum / product / makelist treat the second argument as a quoted dummy (like a lambda variable), integrate / limit / diff do not.

In any case, this is certainly not a bug in apply. The inconsistency probably is a design blunder, but I would argue that sum/... got it right and integrate/... got it wrong. That said, the implementors of Macsyma 50 years ago certainly intended this behavior, so it can't be considered a bug.

If we want to redesign all these functions, that would be an interesting challenge, especially because they would likely break much existing code. But it's not a bug.