MathGroup Archive 2004

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

Search the Archive

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


  • Prev by Date: Re: Integrating Feynman integrals in mathematica
  • Next by Date: Re: COMBINATORICAL PROBLEM (problem solved)
  • Previous by thread: Re: Re: Derivatives of user-defined control-flow functions
  • Next by thread: Re: Re: Derivatives of user-defined control-flow functions