Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know which Maple command automatically maps on list entries or not?

Tags:

In Mathematica, almost all commands automatically thread (or map) over a list.

In Maple, how does one determine which command automatically acts over entries of a list or a set?

For example:

y+p*x=2*sqrt(x*y);
r:=[solve(%,y)];

This gives list of two entries (the solutions)

#r := [-p*x+(2*(1+sqrt(1-p)))*x, -p*x+(2*(1-sqrt(1-p)))*x]

Now I found that collect automatically maps on each list entry

collect(r,x);
   #   [(-p+2+2*sqrt(1-p))*x, (-p+2-2*sqrt(1-p))*x]

But another command does not (I just picked this one)

 MmaTranslator[Mma][LeafCount](r);
        #37

For the above one needs to explicitly iterate over the entries of a list or a set.

 map(MmaTranslator[Mma][LeafCount],r)
             #[17, 19]

Is there a way in Maple to find which command automatically threads over entries of a list or a set other than trial and error?

Maple 2018.1

like image 878
Nasser Avatar asked Aug 27 '18 14:08

Nasser


1 Answers

I don't know of any place in the documentation that says exactly which commands will automatically map over a list.

But the collection of such commands is not large. The vast majority of commands will not automatically map over a list. Most of the ones which auto-map over a list relate to simplication or related manipulation of expressions. The collection of commands which auto-map over a list contains at least these:

collect, combine, expand,
evala, evalc, evalf,
factor, normal, radnormal, rationalize, simplify

The auto-mapping over lists for those commands is mostly a convenience to provide a shorter syntax than wrapping explicitly with the map command.

There are also commands which preserve structure (unless explicitly told, via options, that the outer list structure is the thing to alter) and thus usually accomplish the same thing for a list as mapping over the list:

convert, eval, evalindets, subs, subsindets

Modern Maple has another shorter syntax which can map a command over a list (or a set, or a Vector, etc). It is called the "elementwise" operation, and its syntax consists of appending ~ (tilde) to the command.

Eg,

discont~( [ csc(x), sec(x) ], x );

     [{Pi _Z1~}, {Pi _Z2~ + 1/2 Pi}]

As far as your other example goes, note that LeafCount computes a value (metric) for the first argument considered as a single expression. But a list of items is still a single expression. So it certainly should not be surprising that (without the ~) it acts on the list as a whole, rather than automatically mapping over it. It counts the enclosing list as an additional "leaf".

MmaTranslator:-Mma:-LeafCount( L0 );

                   8

L0 := [ sin(x), 1/2*x*cos(x) ]:

MmaTranslator:-Mma:-LeafCount~( L0 );

                 [2, 5]

map( MmaTranslator:-Mma:-LeafCount, L0 );

                 [2, 5]

For an example similar to your original there is no difference in applying collect (which auto-maps) and applying it elementwise with collect~. Here, the first two results are the same because the addtional argument, x, happens to be a scalar. Eg,

r := [p*x+(2*(x^2+p^2))*x, p*x+(2*(x^2-p^2))*x]:

collect(r, x);

         3       2            3        2
     [2 x  + (2 p  + p) x, 2 x  + (-2 p  + p) x]

collect~(r, x);

         3       2            3        2
     [2 x  + (2 p  + p) x, 2 x  + (-2 p  + p) x]

map(collect, r, x);

         3       2            3        2
     [2 x  + (2 p  + p) x, 2 x  + (-2 p  + p) x]

I should mention that the above examples will behave differently if the second argument is a list such as [x,p] rather than a scalar such as x.

s := [a*b+(2*(a^2*b+b^2))*a, a*b+(2*(a^2*b-b^2))*a]:

collect(s, [a,b]);

           3       2              3        2
     [2 b a  + (2 b  + b) a, 2 b a  + (-2 b  + b) a]

map(collect, s, [a,b]);

           3       2              3        2
     [2 b a  + (2 b  + b) a, 2 b a  + (-2 b  + b) a]

collect~(s, [a,b]);

           3       2               2       3
     [2 b a  + (2 b  + b) a, -2 a b  + (2 a  + a) b]

zip(collect, s, [a,b]);

           3       2               2       3
     [2 b a  + (2 b  + b) a, -2 a b  + (2 a  + a) b]

In the above, the elementiwise collect~ example acts like zip when the second argument is also a list. That is, the first item in the first argument is collected wrt the first item in the second argument, and the second item in the first argument is collected wrt to the second item in the second argument.

Another feature of the elementwise operator syntax is that it will not map the command over the operands of a scalar expression (ie. not a list, set, Vector, etc). This is in stark contrast to map, which can be used to map an operation over the operands of an expression.

Here are two examples where map applies the command to the operands of a scalar expression, while using elementwise ~ gets the command applied only to the scalar expression itself. In the first example the operands are the summands of a sum of terms. In the second example the operands are the arguments of an unevaluated function call.

T := x^2 * sin(x) + y^2 * cos(x):

F( T );

             2           2
          F(x  sin(x) + y  cos(x))

F~( T );

             2           2
          F(x  sin(x) + y  cos(x))

map( F, T );

            2              2
         F(x  sin(x)) + F(y  cos(x))

G( arctan(a, b) );

               G(arctan(a, b))

G~( arctan(a, b) );

               G(arctan(a, b))

map( G, arctan(a, b) );

              arctan(G(a), G(b))

So, if you don't want to map a command inadvertantly over the operands of a scalar expression (addend, multiplicands, etc) then you can use the elementwise ~ syntax without having to first test whether the first expression is a scalar or a list (etc).

Again, if there is an additional argument then it makes a difference whether it is a scalar to a list.

F( T, a );

              F(sin(x) + cos(x), a)

F~( T, a );

              F(sin(x) + cos(x), a)

map( F, T, a );

            F(sin(x), a) + F(cos(x), a)

F( T, [a,b] );

             F(sin(x) + cos(x), [a, b])

map( F, T, [a,b] );

        F(sin(x), [a, b]) + F(cos(x), [a, b])

F~( T, [a,b] );

    [F(sin(x) + cos(x), a), F(sin(x) + cos(x), b)]

zip( F, T, [a,b] );

    [F(sin(x) + cos(x), a), F(sin(x) + cos(x), b)]
like image 103
acer Avatar answered Sep 28 '22 18:09

acer