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

**References**:**"Transparency" with respect to differentiation***From:*Martin Schoenecker <ms_usenet@gmx.de>