5

A recent post on the Wolfram Blog offered the following function to format derivatives in a more traditional way.

pdConv[f_] := 
 TraditionalForm[
  f /. Derivative[inds__][g_][vars__] :> 
    Apply[Defer[D[g[vars], ##]] &, 
     Transpose[{{vars}, {inds}}] /. {{var_, 0} :> 
        Sequence[], {var_, 1} :> {var}}]
 ]

An example use, Dt[d[x, a]] // pdConv gives:

enter image description here

Without breaking the general capabilities of pdConv, can someone alter it to maintain the given order of variables, producing the output shown below? (of course this is purely for asthetic reasons, making derivations easier for a human to follow)

enter image description here

I suspect this will be nontrivial to implement---unless someone knows of a magical Global option that can be temporarily overridden within a Block.

For what it's worth, these SO questions may be related:

Community
  • 1
  • 1
telefunkenvf14
  • 1,011
  • 7
  • 19
  • Interesting question. Could you be a bit more specific when you say *the given order [of] variables*? – Mr.Wizard Dec 24 '11 at 12:16
  • 1
    @Mr.Wizard - To clarify, if f[b,a] is the function fed to Dt, then I'd like total differentiation to be output as Dt[b]*D[f,b] + Dt[a]*D[f,a], rather than sorting output to Dt[a]*D[f,a] + Dt[b]*D[f,b]. (you guys seem to have figured this out below... didn't want to leave you're question hanging.) – telefunkenvf14 Dec 24 '11 at 13:09

3 Answers3

4

There is probably a cleaner way to do s, but if it's purely for presentation purposes, you could do something like

pdConv[f_, vv_] :=
 Module[{v},
  (HoldForm[
       Evaluate@
        TraditionalForm[((f /. Thread[vv -> #]) /. 
           Derivative[inds__][g_][vars__] :> 
            Apply[Defer[D[g[vars], ##]] &, 
             Transpose[{{vars}, {inds}}] /. {{var_, 0} :> 
                Sequence[], {var_, 1} :> {var}}])]] /. 
      Thread[# -> vv]) &@ Table[Unique[v], {Length[vv]}]]

Here, the extra parameter vv is a list of the variables in f in the order you want the partial derivatives to appear. To use this function, you would do something like

pdConv[Dt[d[x, c]], {x, c}]

equations in right order

Basically what this solution does is to temporarily replace the list of variables vv with a list of dummy variables which are in the right lexicographical order, apply the transformation, and then replace the dummy variables with the original variables while preserving the desired order by wrapping the transformed expression in HoldForm.

Heike
  • 24,102
  • 2
  • 31
  • 45
  • @Mr.Wizard I guess there's a first for everything ;-) – Heike Dec 24 '11 at 12:39
  • May I borrow your substitution idea and implement it in my own style, or would you prefer that I not? – Mr.Wizard Dec 24 '11 at 12:43
  • @Heike I think you're idea works... An idea to improve would be to Hold the input function (via attributes) and use Level to grab the ordering of the variables automatically. That said, I'm not sure if this would mess up the other examples given in the original blog post. – telefunkenvf14 Dec 24 '11 at 13:00
  • @telefunken I'll attempt to implement that, and I'll leave you to play with the result. – Mr.Wizard Dec 24 '11 at 13:12
1

Revised after seeing Heike's far superior method. Hopefully without breaking it.

ClearAll[pdConv]

pdConv[order_List][f_] :=
  With[{R = Thread[order -> Sort@order]},
    HoldForm@TraditionalForm@# /. Reverse[R, 2] &[
     f /. R /. Derivative[inds__][g_][vars__] :>
        (Defer@D[g[vars], ##] & @@ Pick[{vars}, {inds}, 1])]
  ]

Use:

Dt[d[x, a]] // pdConv[{x, a}]

Dt[d[x, a, c, b]] // pdConv[{x, a, c, b}]

Automatic ordering for a narrow case:

ClearAll[pdConvAuto]
SetAttributes[pdConvAuto, HoldFirst]

pdConvAuto[f : Dt@_@syms__] :=
  With[{R = Thread[{syms} -> Sort@{syms}]},
    HoldForm@TraditionalForm@# /. Reverse[R, 2] &[
     f /. R /. Derivative[inds__][g_][vars__] :>
        (Defer@D[g[vars], ##] & @@ Pick[{vars}, {inds}, 1])]
  ]

Use:

Dt[d[x, a, c, b]] // pdConvAuto
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
  • You're quick! I'll play with it and will report back. May also check some of the other examples from the Wolfram blog post (to confirm they still work). – telefunkenvf14 Dec 24 '11 at 14:03
0

I realized that Dt[d[x, a, c, b]] already gives ordered output, just in reverse. I am probably misunderstanding the situation, but for some cases this appears to be sufficient:

ClearAll[pdConv]

pdConv[f_] :=
 Apply[Plus, HoldForm@TraditionalForm@#, {2}] &[
  Reverse[List @@ f] /. Derivative[inds__][g_][vars__] :>
    (Defer@D[g[vars], ##] & @@ Pick[{vars}, {inds}, 1])
  ]

Dt[d[x, a, r, c, b]] // pdConv
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125