Re: Derivatives of user-defined control-flow functions
- To: mathgroup at smc.vnet.net
- Subject: [mg51187] Re: Derivatives of user-defined control-flow functions
- From: ab_def at prontomail.com (Maxim)
- Date: Thu, 7 Oct 2004 05:26:22 -0400 (EDT)
- References: <cjoiel$al2$1@smc.vnet.net> <200410041018.GAA25203@smc.vnet.net> <cjtnl4$8hr$1@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
"Maxim A. Dubinnyi" <maxim at nmr.ru> wrote in message news:<cjtnl4$8hr$1 at smc.vnet.net>... > Maxim wrote: > > >You can add a definition for D: > > > >In[1]:= > >Clear[myIf] > >myIf /: D[myIf[a_, b_, c_], vars__] := myIf[a, D[b, vars], D[c, vars]] > > > >D[myIf[a[x, y], x^2, -x^2], {x, 2}] > > > >Out[3]= > >myIf[a[x, y], 2, -2] > > > >If you need the definitions for Derivative, you can look at how it is > >done for If and emulate it: > > > >In[4]:= > >Clear[myIf] > >myIf /: Derivative[1, 0, 0][myIf] = 0&; > >myIf /: Derivative[0, 1, 0][myIf] = myIf[#, 1, 0]&; > >myIf /: Derivative[0, 0, 1][myIf] = myIf[#, 0, 1]&; > > > >D[myIf[a[x, y], x^2, -x^2], {x, 2}] > > > >Out[8]= > >-2 myIf[a[x, y], 0, 1] + 2 myIf[a[x, y], 1, 0] > > > > > >(If you omit TagSet, then the definitions will be stored as SubValues > >for Derivative, which can be pretty confusing). > > > > This answer is numerically correct, but let us see the GENERAL CASE: > > In[8a]= D[myIf[cond, f[x], g[x]], x] > Out[8a]= myIf[cond, 1, 0] f'[x] + myIf[cond, 0, 1] g'[x] > > You can see, that values of f'[x] and g'[x] will be always > evaluated, whatever value of "cond" is. But "myIf" should > be CONTROL-FLOW function, which means that only one of two > expression should be evaluated, namely f'[x] if "cond" is True, > or g'[x] if "cond" is False. So preferred answer is > > Out[8b]= myIf[cond, f'[x], g'[x]] > > The difference between Out[8a] and Out[8b] is essential for > time-consuming functions f'[x] and/or g'[x]. > > I can introduce rules for simplification of Out[8a] to Out[8b], > for example: > > In[10]= myIf/:(myIf[cond_, a_, b_]*c_):= > myIf[cond, a*c, b*c] > In[11]= myIf/:(myIf[cond_, a1_, b1_]+myIf[cond_, a2_, b2_]):= > myIf[cond, a1+b1, a2+b2] > > Now In[8a] is evaluated to: > > In[12]= D[myIf[cond, f[x], g[x]], x] > Out[12]= myIf[cond, f'[x], g'[x]] > > But we have side effects of this definition: rules [10,11] will > be applied whenever it's possible, for example: > > In[13]= myIf[cond, f[x], g[x]]h[x] > Out[13]= myIf[cond, f[x]h[x], g[x]h[x]] > > But > > In[14]= If[cond, f[x], g[x]]h[x] > Out[14]= If[cond, f[x], g[x]]h[x] > Looks more like a hack, but here goes: In[1]:= ClearAll[myIf] Attributes[myIf] = HoldRest; myIf /: D[myIf[a_, b_, c_], vars__] := myIf[a, D[b, vars], D[c, vars]] derF = True; Derivative[ord__][f_] /; derF := Block[ {derF = False}, Derivative[ord][f] /. {k_. * Derivative[1, 0, 0][myIf][__] -> 0, k_. * Derivative[0, 1, 0][myIf][a_, __] -> myIf[a, k, 0], k_. * Derivative[0, 0, 1][myIf][a_, __] -> myIf[a, 0, k]} ] This is a standard method for trapping calls to internal functions; the idea is that when the flag is set to False we fall through to the built-in transformation rules. Here's what we get: In[6]:= func[x_] := (Print[x]; x) f[x_] = myIf[a[x, y], func[x], x - x]; D[f[x], x] f'[x] Out[8]= myIf[a[x, y], D[func[x], x], D[x - x, x]] Out[9]= myIf[a[x, y], 0, -1 + 1] + myIf[a[x, y], Derivative[1][func][x], 0] Maxim Rytin m.r at inbox.ru
- References:
- Re: Derivatives of user-defined control-flow functions
- From: ab_def@prontomail.com (Maxim)
- Re: Derivatives of user-defined control-flow functions