MathGroup Archive 2007

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

Search the Archive

Re: "Transparency" with respect to differentiation

  • To: mathgroup at smc.vnet.net
  • Subject: [mg74093] Re: [mg73846] "Transparency" with respect to differentiation
  • From: Carl Woll <carlw at wolfram.com>
  • Date: Fri, 9 Mar 2007 02:06:32 -0500 (EST)
  • References: <200703021123.GAA03190@smc.vnet.net>

Martin Schoenecker wrote:

>I would like to use a dummy object, that has the only task to mark its 
>argument function.  So I could use a previously undefined symbol for 
>that pupose:
>
>In[1]:= quat[f[x]+g[x]]
>Out[1]= quat[f[x]+g[x]]
>
>Now I would like this flag to distribute over Plus:  each element in the 
>argument sum has the property of being "quat":
>
>In[2]:=
>quat[a_+b_]:=quat[a]+quat[b]
>quat[f[x]+g[x]+h[x]]
>DownValues[quat]
>
>Out[3]= quat[f[x]]+quat[g[x]]+quat[h[x]]
>Out[4]= {HoldPattern[quat[a_+b_]]\[RuleDelayed]quat[a]+quat[b]}
>
>So this property is stored as DownValue of quat.  Then, I would like the 
>quat to be transparent with respect to differentiation, and I thought it 
>would be a good idea to store this property as an UpValue for quat 
>rather than changing the (Protected!) D:
>
>In[6]:= quat/:D[quat[fun_],var__]:=quat[D[fun,var]]
>D[quat[f[x]],x]
>
>Out[7]= quat[f'[x]]
>
>which seems to work alright. However, a combination requiring both 
>properties does not work easily, the derivative of quat w.r.t. its 
>argument is produced:
>
>In[8]:=
>D[quat[f[x] + g[x]], x]
>(D[#1, x] &)/@quat[f[x] + g[x]]
>
>Out[8]= f'[x] quat'[f[x]] + g'[x] quat'[g[x]]
>Out[9]= quat[f'[x]] + quat[g'[x]]
>
>So how could I define an object, distributing over Plus and transparent 
>w.r.t. differentiation more conveniently?
>
>And, additionaly, how could I define a standard form of this object, 
>that returns a 'nicer' version (however maybe a bit less unambiguous), 
>like the integrate sign appearing when asking for Integrate?  My 
>attempts to understand TagBox and InterpretationBox (if these constructs 
>would help) were fruitless until now.
>
>Regards, Martin
>  
>
Another variant of this question is what property of Equal allows D to 
pass through?

In[1]:= D[f[x] == g[x], x]
Out[1]= f'[x] == g'[x]

The answer is that the Equal head is excluded from the general 
differentiation rules. You can control this behavior by using 
SystemOptions. Note that these system options are subject to change, and 
changing them from their defaults can make Mathematica unstable. At any 
rate, we can take a look at differentiation options as follows:

In[2]:=
Developer`SystemOptions["DifferentiationOptions"] // InputForm
Out[2]//InputForm=
"DifferentiationOptions" -> {"AlwaysThreadGradients" -> False,
  "DifferentiateHeads" -> True, "DirectHighDerivatives" -> True,
  "ExcludedFunctions" -> {Hold, HoldComplete, Less, LessEqual, Greater,
    GreaterEqual, Inequality, Unequal, Nand, Nor, Xor, Not, Element, 
Exists,
    ForAll, Implies, Positive, Negative, NonPositive, NonNegative},
  "ExitOnFailure" -> False, "SymbolicAutomaticDifferentiation" -> False}

The relevant suboption is "ExcludedFunctions", and we want to add quat 
to this list. So,

In[3]:=
oldheads = "ExcludedFunctions" /. ("DifferentiationOptions" /. 
Developer`SystemOptions["DifferentiationOptions"]);

In[4]:=
Developer`SetSystemOptions["DifferentiationOptions" ->
     "ExcludedFunctions" -> Append[oldheads, quat]] // InputForm
Out[4]//InputForm=
"DifferentiationOptions" -> {"AlwaysThreadGradients" -> False,
  "DifferentiateHeads" -> True, "DirectHighDerivatives" -> True,
  "ExcludedFunctions" -> {Hold, HoldComplete, Less, LessEqual, Greater,
    GreaterEqual, Inequality, Unequal, Nand, Nor, Xor, Not, Element, 
Exists,
    ForAll, Implies, Positive, Negative, NonPositive, NonNegative, quat},
  "ExitOnFailure" -> False, "SymbolicAutomaticDifferentiation" -> False}

Note that quat has been added to the list of excluded functions, so that 
D will not do anything with quat objects:

In[5]:=
D[quat[x], x] // InputForm
Out[5]//InputForm=
D[quat[x], x]

Now, we can add your own rules to quat. For example:

In[6]:=
quat /: D[quat[a_], x_] := quat[D[a, x]]

quat[a_Plus] := Distribute[Unevaluated[quat[a]]]

I prefer using the above rule to make quat distributive instead of 
defining rules for quat[a_+b_]. Some examples:

In[7]:=
D[quat[f[x] + g[x]], x] // OutputForm
Out[7]//OutputForm=
quat[f'[x]] + quat[g'[x]]

In[8]:=
D[f[x]quat[g[x]], x] // OutputForm
Out[8]//OutputForm=
f[x] quat[g'[x]] + quat[g[x]] f'[x]

Finally, a comment on the approach suggested by Jean-Marc Gulliet, of 
unprotecting D and giving it some rules for quat. Besides giving a down 
value for a system symbol, it doesn't work when quat is multiplied by 
something. For example, his code generates quat' objects for an input like:

D[2 quat[x], x]
2 quat'[x]

This is because Mathematica's chain rule code bypasses his definition for D.

Carl Woll
Wolfram Research


  • Prev by Date: Re: analytic integration of InterpolatingFunction compositions
  • Next by Date: Re: Evaluate a spline function
  • Previous by thread: "Transparency" with respect to differentiation
  • Next by thread: Re: "Transparency" with respect to differentiation