MathGroup Archive 1998

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Derivatives D[ ] as Functions: Summary (LONGISH)

  • To: mathgroup at smc.vnet.net
  • Subject: [mg13362] Re: Derivatives D[ ] as Functions: Summary (LONGISH)
  • From: "Allan Hayes" <hay at haystack.demon.cc.uk>
  • Date: Mon, 20 Jul 1998 02:50:15 -0400
  • References: <6nsil0$f32@smc.vnet.net> <6okijd$1ft@smc.vnet.net>
  • Sender: owner-wri-mathgroup at wolfram.com

I have intepolated comments in the following message, including, for
completeness, some from my previous related posting. Unfortunately this
raises it the posting  from Longish to Long. However the issues raised
seem important.

------------------------------------------------------------- 
Allan Hayes
Training and Consulting
Leicester UK
http://www.haystack.demon.co.uk
hay at haystack.demon.co.uk
voice: +44 (0)116 271 4198
fax: +44(0)116 271 8642

----------------------------------------------------------------------------
-

AES wrote in message <6okijd$1ft at smc.vnet.net>...
>I recently posed the question of defining a function f2 as the
>derivative of another function f1, e.g.
>
>     Remove["Global`*"];
>
>     f1[a_,x_] :=a Cos[x] + a^2 Sin[x];
>     f2[a_,x_] := D[f1[a,x],x];
>
>and then finding that f2 would not behave "as expected" in a subsequent
>Plot[ ] or Table[ ].
>
>Thanks to several people for their responses, and apologies for my
>several typos in earlier postings.  It's clear what my difficulty was.

Clear["Global`*"]

f1[a_,x_] :=a Cos[x] + a^2 Sin[x];
f2[a_,x_] := D[f1[a,x],x];

For Table we get

Table[f2[a,x],{x,1,2}]
General::ivar: 1 is not a valid variable. General::ivar: 2 is not a
valid variable.

               2                           2 {D[a Cos[1] + a  Sin[1],
1], D[a Cos[2] + a  Sin[2], 2]}

This is because Table does not evaluate f2[x,y] itself (it hs the
Attribute HoldAll); but for each numerical values of x supplied by the
iterator {x,0,1}, say x =1 it finds the corresponding table entry by a
process like

x=1;
f2[a,x]
General::ivar: 1 is not a valid variable.
              2
D[a Cos[1] + a  Sin[1], 1]

and differentiating with respect to the number 1 makes no sense.

To avoid this we need to evaluate f2[a,x] before x is assigned the value
1


With the example given, the pre-evaluation can be achieved in several
ways (method (2) below is probably the most common way) Ill modify the
example to show {x,f1[a,x], f2[a,x]}

a=2;


(1)

Table[Block[{x},{x, f1[a,x], f2[a,x]}]//N , {x,1,2}] // TableForm

1.   4.44649   0.478267

2.   2.8049    -3.48318


(2)
x=. (* essential for this method*)

Table[Evaluate[{x, f1[a,x], f2[a,x]}] , {x,1,2}]//N // TableForm

1.   4.44649   0.478267

2.   2.8049    -3.48318


(3)

Make the definitions of f1 and f2 immediate, so that the differentiation
is done before we construct the Table expression - this is the most
efficient way.

Clear["Global`*"]

f1[a_,x_] =a Cos[x] + a^2 Sin[x];
f2[a_,x_] = D[f1[a,x],x];

a=2;


Table[{x, f1[a,x], f2[a,x]} // N, {x,1,2}] // TableForm

1.   4.44649   0.478267

2.   2.8049    -3.48318


>
>
>However, let's look at the general issue a little further.  If for
>example we do the above and then look at the FullForm version of the
>two functions, they look very similar:
>
>     f1[a,x]//FullForm
>
>              Plus[Times[a,Cos[x]],Times[Power[a,2],Sin[x]]]
>
>     f2[a,x] // FullForm
>
>              Plus[Times[Power[a,2],Cos[x]],Times[-1,a,Sin[x]]]

>
>Note that these FullForm results, if not misleading, certainly give no
>clue that f2 has a different  character than f1 and will behave totally
>differently if you try to use it  in Plot[ ]  or Table[ ] .
> A general and frequent and serious problem with Mathematica, in fact,
>is that it  often does things that may be totally logical and even
>necessary by its  rules, but that can be mysterious, non-intuitive, and
>frustrating  to ordinary users; and the nature of the beast often makes
>these problems obscure and hard  to find.

Clear["`*"]


f1[a_,x_] :=a Cos[x] + a^2 Sin[x];
f2[a_,x_] := D[f1[a,x],x];


f2[a,x] // FullForm first evaluates f2[a,x] and then shows the full form
of the result.

This seems to me to be straight forward.

To see the stored expression we can use. ?f2
Global`f2
f2[a_, x_] := D[f1[a, x], x]

And to see all the stored definitions that would be used in a current
evaluation we can use

FullDefinition[f2]

f2[a_, x_] := D[f1[a, x], x]

                          2
f1[a_, x_] := a Cos[x] + a  Sin[x]


>
>[As another example of Mathematica's penchant for obscure difficulties,
>note that if you follow the usual practice that you are allowed to use
>for (all? most?) other compound  expressions and include the "Remove[
>]" expression in the same cell as  the two function definitions above,
>the two definitions will be Removed, even  though they come AFTER the
>Remove[ ].  Tell me why this makes sense? -- not what combination of
>rules makes Remove[ ] function this way, but why setting it up in this
>way makes sense?  Also, tell me where you're warned  about this in the
>Mathematica Book?]

This is tricky, here is my attempt at an explanation

Take an example:

Remove[a];a=5;a^2

25

?a

Information::notfound: Symbol a not found.

The explanation seems to be that on evaluating the compound expression,
Remove[a] causes a to be replaced by Removed[a] for the rest of the
evaluation.
So, we get the assignment Removed[a] = 5; then evaluate Removed[a]^2 to
get the
output 25.
But then all occurences and definitions involving Removed[a] and a are
removed.

This explanation is supported by the following TracePrint.

In[57]:=
(Remove[a];a=5;a^2)//TracePrint

                    2
Remove[a]; a = 5; a

  CompoundExpression

  Remove[a]

   Remove

  Null

  Removed[a] = 5

   Set

   5

  5

            2
  Removed[a]

   Power

   Removed[a]

   5

   2
   2
  5

  25

25
Out[57]=
25


>
>[Another general observation is that when problems -- or anyway
>"apparent problems" -- with Mathematica's ways of doing things are
>pointed out, I find it's much more common to get a detailed explanation
>of why Mathematica does what it does, rather than any discussion of the
>design choices, or design necessities, that make it necessary -- if it
>is necessary -- for Mathematica to function in this way.]

A single source for fuller information on design choices would be
welcome.

>
>In any event one way to avoid the derivative problem above is to use an
>immediate  definition, i.e., use " = " instead of " := "in defining f2:
>
>     f1[a_,x_] :=a Cos[x] + a^2 Sin[x];
>     f2[a_,x_] = D[f1[a,x],x];
>
>That's fine -- except, suppose you do this deep in a notebook in which
>"a" has already been given a value; you may not get what you want, or
>think you're getting..

I know of no general solution to this problem. Using Block can
temporarily protect a from outside definitions (Module would change a
to a$n for some positive integer n , which might not be appropriate).
More about this later.


>
>Several people also  suggested using Evaluate[f2[a,x]], or more  complex
>tricks, every time you use f2 subsequently in a Plot[ ] or  Table[ ],
>and  that of course works.
>
>However, so far as I can see the  preferred way to  accomplish this
>would seem to be to do it globally,  i.e., to write:
>
>     f1[a_,x_]  := a Cos[x] + a^2 Sin[x];
>     f2[a_,x_]  := Evaluate[ D[f1[a,x],x]];
>
>That's reasonably easy to remember, somewhat intuitive (to me  anyway),
>seems to meet the need, and what I propose to do from now on.  But, are
>there still  hidden pitfalls in this?  Further comments welcome.

What is the advantage of using f2[a_,x_]  := Evaluate[ D[f1[a,x],x]];?

It looks like

lhs:=Evaluate[rhs ];

is equivalent to

lhs=rhs;

except for two features:

(1) where an explicit = is needed:

    For example we have
    xx = {1,3}; xx[[2]]=5 ;xx
    {1, 5}

    but

    yy := Evaluate[{1,3}]; yy[[2]]=5;yy
    Set::noval: Symbol yy in part assignment does not have an
     immediate value.

    {1, 3}

(2) Output:

    The output from yy := Evaluate[{1,3}] is Null, whereas that from xx
= {1,3} is {1,3}


And, to return to the problem of protecting of variables from outside
definitions,

f2[a_,x_] :=Evaluate[ D[f1[a,x],x]];

will not avoid picking up existing definitions of a (or of x)

However as mentioned earlier this sort of thing might be tackled with
Block

a= 2;x=3;Block[{a,x},f2[a_,x_] = D[f1[a,x],x]];

?f2
Global`f2
f2[a_, x_] = a^2*Cos[x] - a*Sin[x]

I don't have a complete answer.
The matter is complicated by Mathematica allowing replacement of symbols
at particular places - so that Block[{a}, f[a]] could become Block[{b},
f[a]] or Block[{a}, f[b]].




  • Prev by Date: Re: CPU times
  • Next by Date: Re: new user help
  • Previous by thread: Re: Re: Derivatives D[ ] as Functions: Summary (LONGISH)
  • Next by thread: abcd-matrix for lens-systems